@@ -45,20 +45,17 @@ class AgentApiService {
|
||||
}
|
||||
|
||||
async searchLogs(filters?: LogFilters): Promise<LogEntry[]> {
|
||||
const response = await apiClient.get<LogEntry[]>(
|
||||
`${this.logsBasePath}/mock`,
|
||||
{
|
||||
params: {
|
||||
level: filters?.level,
|
||||
service: filters?.service,
|
||||
agent: filters?.agent,
|
||||
date_from: filters?.date_from,
|
||||
date_to: filters?.date_to,
|
||||
limit: filters?.limit ?? 100,
|
||||
offset: filters?.offset ?? 0,
|
||||
},
|
||||
const response = await apiClient.get<LogEntry[]>(this.logsBasePath, {
|
||||
params: {
|
||||
level: filters?.level,
|
||||
service: filters?.service,
|
||||
agent: filters?.agent,
|
||||
date_from: filters?.date_from,
|
||||
date_to: filters?.date_to,
|
||||
limit: filters?.limit ?? 100,
|
||||
offset: filters?.offset ?? 0,
|
||||
},
|
||||
);
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,12 +63,20 @@ export const LogsPage: React.FC = () => {
|
||||
try {
|
||||
const filters = getFilters();
|
||||
const data = await agentApiService.searchLogs(filters);
|
||||
if (!Array.isArray(data)) {
|
||||
console.error("[Logs] Expected array, got:", typeof data);
|
||||
setLogs([]);
|
||||
setTotalLogs(0);
|
||||
return;
|
||||
}
|
||||
setLogs(data);
|
||||
setTotalLogs(data.length);
|
||||
} catch (err) {
|
||||
setError(
|
||||
err instanceof Error ? err.message : "Ошибка при загрузке логов",
|
||||
);
|
||||
setLogs([]);
|
||||
setTotalLogs(0);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -76,14 +84,44 @@ export const LogsPage: React.FC = () => {
|
||||
|
||||
const fetchDistinctData = useCallback(async () => {
|
||||
try {
|
||||
const [services, agents] = await Promise.all([
|
||||
const [servicesResult, agentsResult] = await Promise.allSettled([
|
||||
agentApiService.getDistinctServices(),
|
||||
agentApiService.getDistinctAgents(),
|
||||
]);
|
||||
setAvailableServices(services);
|
||||
setAvailableAgents(agents);
|
||||
|
||||
if (
|
||||
servicesResult.status === "fulfilled" &&
|
||||
Array.isArray(servicesResult.value)
|
||||
) {
|
||||
setAvailableServices(servicesResult.value);
|
||||
} else {
|
||||
console.error(
|
||||
"[Logs] Failed to fetch services:",
|
||||
servicesResult.status === "rejected"
|
||||
? servicesResult.reason
|
||||
: "non-array response",
|
||||
);
|
||||
setAvailableServices([]);
|
||||
}
|
||||
|
||||
if (
|
||||
agentsResult.status === "fulfilled" &&
|
||||
Array.isArray(agentsResult.value)
|
||||
) {
|
||||
setAvailableAgents(agentsResult.value);
|
||||
} else {
|
||||
console.error(
|
||||
"[Logs] Failed to fetch agents:",
|
||||
agentsResult.status === "rejected"
|
||||
? agentsResult.reason
|
||||
: "non-array response",
|
||||
);
|
||||
setAvailableAgents([]);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch distinct data:", err);
|
||||
console.error("[Logs] Failed to fetch distinct data:", err);
|
||||
setAvailableServices([]);
|
||||
setAvailableAgents([]);
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -108,8 +146,10 @@ export const LogsPage: React.FC = () => {
|
||||
setOffset(Math.max(0, offset - limit));
|
||||
};
|
||||
|
||||
const formatTimestamp = (timestamp: string) => {
|
||||
const formatTimestamp = (timestamp: string | undefined | null) => {
|
||||
if (!timestamp) return "—";
|
||||
const date = new Date(timestamp);
|
||||
if (isNaN(date.getTime())) return "—";
|
||||
return date.toLocaleString("ru-RU", {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
@@ -266,8 +306,9 @@ export const LogsPage: React.FC = () => {
|
||||
</thead>
|
||||
<tbody>
|
||||
{logs.map((log, index) => {
|
||||
const level = log.level || "INFO";
|
||||
const colors =
|
||||
logLevelColors[log.level] || logLevelColors.INFO;
|
||||
logLevelColors[level] || logLevelColors.INFO;
|
||||
return (
|
||||
<tr
|
||||
key={index}
|
||||
@@ -295,27 +336,27 @@ export const LogsPage: React.FC = () => {
|
||||
borderColor: colors.border,
|
||||
}}
|
||||
>
|
||||
{logLevelIcons[log.level]}
|
||||
{log.level}
|
||||
{logLevelIcons[level]}
|
||||
{level}
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
className="px-4 py-3 text-sm"
|
||||
style={{ color: "var(--text-primary)" }}
|
||||
>
|
||||
{log.service}
|
||||
{log.service || "—"}
|
||||
</td>
|
||||
<td
|
||||
className="px-4 py-3 text-sm font-mono"
|
||||
style={{ color: "var(--text-primary)" }}
|
||||
>
|
||||
{log.agent}
|
||||
{log.agent || "—"}
|
||||
</td>
|
||||
<td
|
||||
className="px-4 py-3 text-sm"
|
||||
style={{ color: "var(--text-primary)" }}
|
||||
>
|
||||
{log.message}
|
||||
{log.message || "—"}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user