fix(analyze_logs): scan-all-Modus funktionierte nicht
docker logs ohne Container-Argument schlägt fehl → 0 Treffer. Jetzt: Loop über alle laufenden Container (docker ps), pro Match Container-Name in sample_matches + containers_with_matches im Output. Tool-Beschreibung angepasst.
This commit is contained in:
1 parent
c8c767d45b
commit
c4c9752521
2 files changed
+25
-8
No files matched your search
+24
-7
@@ -325,23 +325,39 @@ export async function analyzeContainerLogs(
|
|||||||
const patterns = severityLevels[severity] ?? severityLevels["error"];
|
const patterns = severityLevels[severity] ?? severityLevels["error"];
|
||||||
const regex = new RegExp(`(${patterns.join("|")})`, "i");
|
const regex = new RegExp(`(${patterns.join("|")})`, "i");
|
||||||
|
|
||||||
let logCmd = `logs --timestamps --since ${since} --tail ${scanTail}`;
|
// Ziel-Container: einzelner Container oder alle laufenden
|
||||||
if (container) logCmd += ` ${container}`;
|
let targets: string[];
|
||||||
const raw = await dockerExec(logCmd, 120);
|
if (container) {
|
||||||
const lines = raw.split("\n");
|
targets = [container];
|
||||||
|
} else {
|
||||||
|
const psRaw = await dockerExec("ps --format '{{.Names}}'", 30);
|
||||||
|
targets = psRaw
|
||||||
|
.split("\n")
|
||||||
|
.map((l) => l.trim())
|
||||||
|
.filter((l) => l.length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
const matches: { pattern: string; line: string }[] = [];
|
const matches: { pattern: string; line: string; container: string }[] = [];
|
||||||
const counts: Record<string, number> = {};
|
const counts: Record<string, number> = {};
|
||||||
for (const line of lines) {
|
const containersWithMatches: Record<string, number> = {};
|
||||||
|
|
||||||
|
for (const name of targets) {
|
||||||
|
const logCmd = `logs --timestamps --since ${since} --tail ${scanTail} ${name}`;
|
||||||
|
const raw = await dockerExec(logCmd, 120);
|
||||||
|
let containerMatches = 0;
|
||||||
|
for (const line of raw.split("\n")) {
|
||||||
const m = line.match(regex);
|
const m = line.match(regex);
|
||||||
if (m) {
|
if (m) {
|
||||||
const key = m[1].toLowerCase();
|
const key = m[1].toLowerCase();
|
||||||
counts[key] = (counts[key] ?? 0) + 1;
|
counts[key] = (counts[key] ?? 0) + 1;
|
||||||
|
containerMatches++;
|
||||||
if (matches.length < maxResults) {
|
if (matches.length < maxResults) {
|
||||||
matches.push({ pattern: m[1], line: line.trim().slice(0, 300) });
|
matches.push({ pattern: m[1], line: line.trim().slice(0, 300), container: name });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (containerMatches > 0) containersWithMatches[name] = containerMatches;
|
||||||
|
}
|
||||||
|
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
schema_version: "1.0",
|
schema_version: "1.0",
|
||||||
@@ -351,6 +367,7 @@ export async function analyzeContainerLogs(
|
|||||||
scan_tail: scanTail,
|
scan_tail: scanTail,
|
||||||
total_matches: Object.values(counts).reduce((a, b) => a + b, 0),
|
total_matches: Object.values(counts).reduce((a, b) => a + b, 0),
|
||||||
pattern_counts: counts,
|
pattern_counts: counts,
|
||||||
|
containers_with_matches: containersWithMatches,
|
||||||
sample_matches: matches,
|
sample_matches: matches,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -85,7 +85,7 @@ export const TOOLS: ToolDef[] = [
|
|||||||
enum: ["error", "warn", "info"],
|
enum: ["error", "warn", "info"],
|
||||||
description: "Log severity to scan for",
|
description: "Log severity to scan for",
|
||||||
},
|
},
|
||||||
container: str("Container name (optional, scans all if omitted)"),
|
container: str("Container name (optional, scans all running containers if omitted)"),
|
||||||
since: str("Time filter (default 24h)"),
|
since: str("Time filter (default 24h)"),
|
||||||
scan_tail: int("Max lines to scan (default 1000)"),
|
scan_tail: int("Max lines to scan (default 1000)"),
|
||||||
max_results: int("Max sample matches (default 50)"),
|
max_results: int("Max sample matches (default 50)"),
|
||||||
|
|||||||
Reference in new issue
Block a user