mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-31 04:38:11 +00:00
Merge pull request #21 from AnsoCode/feature/global-logs-classification
fix: replace naive log level detection with robust 3-tier regex class…
This commit is contained in:
@@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
- **Fixed:** Global logs false-positive error misclassifications caused by Docker containers writing INFO logs to STDERR. Replaced naive regex with a robust 3-tier classification engine supporting `level=info`, `[INFO]`, and ` INFO ` format standards.
|
||||||
- **Added:** Developer Mode setting to enable true Real-Time (SSE) global log streaming and infinite scroll.
|
- **Added:** Developer Mode setting to enable true Real-Time (SSE) global log streaming and infinite scroll.
|
||||||
- **Added:** Configurable polling rates for standard global logs monitoring.
|
- **Added:** Configurable polling rates for standard global logs monitoring.
|
||||||
- **Added:** React Throttle Buffer to prevent UI freezing during heavy real-time log ingestion.
|
- **Added:** React Throttle Buffer to prevent UI freezing during heavy real-time log ingestion.
|
||||||
|
|||||||
+39
-10
@@ -806,17 +806,28 @@ app.get('/api/logs/global', async (req: Request, res: Response) => {
|
|||||||
cleanMessage = timeMatch[2];
|
cleanMessage = timeMatch[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default to INFO, or ERROR if coming from STDERR.
|
||||||
let level = source === 'STDERR' ? 'ERROR' : 'INFO';
|
let level = source === 'STDERR' ? 'ERROR' : 'INFO';
|
||||||
|
|
||||||
if (/\b(warn|warning)\b/i.test(cleanMessage)) {
|
// 1. Explicitly check for INFO/DEBUG indicators (Overrides STDERR defaults)
|
||||||
level = 'WARN';
|
if (/level=["']?(info|debug|trace)["']?/i.test(cleanMessage) ||
|
||||||
} else if (/\b(error|err|fatal|exception)\b/i.test(cleanMessage)) {
|
/\[\s*(info|inf|debug|dbg|trace)\s*\]/i.test(cleanMessage) ||
|
||||||
level = 'ERROR';
|
/(?:\s|^)(info|inf|debug|trace)(?:\s|:|\(|\[|$)/i.test(cleanMessage)) {
|
||||||
}
|
|
||||||
|
|
||||||
if (/\[\s*(info|inf|debug|dbg)\s*\]/i.test(cleanMessage) || /^(info|debug)\b/i.test(cleanMessage)) {
|
|
||||||
level = 'INFO';
|
level = 'INFO';
|
||||||
}
|
}
|
||||||
|
// 2. Check for WARN indicators
|
||||||
|
else if (/level=["']?(warn|warning)["']?/i.test(cleanMessage) ||
|
||||||
|
/\[\s*(warn|warning)\s*\]/i.test(cleanMessage) ||
|
||||||
|
/(?:\s|^)(warn|warning)(?:\s|:|\(|\[|$)/i.test(cleanMessage)) {
|
||||||
|
level = 'WARN';
|
||||||
|
}
|
||||||
|
// 3. Check for ERROR indicators
|
||||||
|
else if (/level=["']?(error|err|fatal|crit|critical|panic)["']?/i.test(cleanMessage) ||
|
||||||
|
/\[\s*(error|err|fatal|crit|critical|panic)\s*\]/i.test(cleanMessage) ||
|
||||||
|
/(?:\s|^)(error|err|fatal|crit|critical|panic)(?:\s|:|\(|\[|$)/i.test(cleanMessage) ||
|
||||||
|
/Exception:/i.test(cleanMessage)) {
|
||||||
|
level = 'ERROR';
|
||||||
|
}
|
||||||
|
|
||||||
allLogs.push({ stackName, containerName, source, level, message: cleanMessage, timestampMs });
|
allLogs.push({ stackName, containerName, source, level, message: cleanMessage, timestampMs });
|
||||||
};
|
};
|
||||||
@@ -891,10 +902,28 @@ app.get('/api/logs/global/stream', async (req: Request, res: Response) => {
|
|||||||
cleanMessage = timeMatch[2];
|
cleanMessage = timeMatch[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default to INFO, or ERROR if coming from STDERR.
|
||||||
let level = source === 'STDERR' ? 'ERROR' : 'INFO';
|
let level = source === 'STDERR' ? 'ERROR' : 'INFO';
|
||||||
if (/\[\s*(info|inf|debug|dbg)\s*\]/i.test(cleanMessage) || /^(info|debug)\b/i.test(cleanMessage)) level = 'INFO';
|
|
||||||
else if (/\b(warn|warning)\b/i.test(cleanMessage)) level = 'WARN';
|
// 1. Explicitly check for INFO/DEBUG indicators (Overrides STDERR defaults)
|
||||||
else if (/\b(error|err|fatal|exception)\b/i.test(cleanMessage)) level = 'ERROR';
|
if (/level=["']?(info|debug|trace)["']?/i.test(cleanMessage) ||
|
||||||
|
/\[\s*(info|inf|debug|dbg|trace)\s*\]/i.test(cleanMessage) ||
|
||||||
|
/(?:\s|^)(info|inf|debug|trace)(?:\s|:|\(|\[|$)/i.test(cleanMessage)) {
|
||||||
|
level = 'INFO';
|
||||||
|
}
|
||||||
|
// 2. Check for WARN indicators
|
||||||
|
else if (/level=["']?(warn|warning)["']?/i.test(cleanMessage) ||
|
||||||
|
/\[\s*(warn|warning)\s*\]/i.test(cleanMessage) ||
|
||||||
|
/(?:\s|^)(warn|warning)(?:\s|:|\(|\[|$)/i.test(cleanMessage)) {
|
||||||
|
level = 'WARN';
|
||||||
|
}
|
||||||
|
// 3. Check for ERROR indicators
|
||||||
|
else if (/level=["']?(error|err|fatal|crit|critical|panic)["']?/i.test(cleanMessage) ||
|
||||||
|
/\[\s*(error|err|fatal|crit|critical|panic)\s*\]/i.test(cleanMessage) ||
|
||||||
|
/(?:\s|^)(error|err|fatal|crit|critical|panic)(?:\s|:|\(|\[|$)/i.test(cleanMessage) ||
|
||||||
|
/Exception:/i.test(cleanMessage)) {
|
||||||
|
level = 'ERROR';
|
||||||
|
}
|
||||||
|
|
||||||
res.write(`data: ${JSON.stringify({ stackName, containerName, source, level, message: cleanMessage, timestampMs })}\n\n`);
|
res.write(`data: ${JSON.stringify({ stackName, containerName, source, level, message: cleanMessage, timestampMs })}\n\n`);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user