read format
This commit is contained in:
75
index.html
75
index.html
@@ -31,7 +31,7 @@
|
||||
--text3: #555966;
|
||||
--accent: #4f8ef7;
|
||||
--accent-dim: #4f8ef720;
|
||||
--trace: #818594;
|
||||
--trace: #808080;
|
||||
--debug: #555966;
|
||||
--info: #4f8ef7;
|
||||
--warn: #f5a623;
|
||||
@@ -841,8 +841,8 @@
|
||||
}
|
||||
|
||||
// ---- Log parsing ----
|
||||
function parseLogs(text) {
|
||||
const lines = text.split('\n').filter(l => l.trim());
|
||||
function parseLogs(text, filedate = null) {
|
||||
const lines = text.split(/\r?\n/).filter(l => l.trim());
|
||||
const logs = [];
|
||||
|
||||
// Try JSON Lines
|
||||
@@ -859,9 +859,12 @@ function parseLogs(text) {
|
||||
/^(\w{3}\s+\d{1,2}\s+\d{2}:\d{2}:\d{2})\s+(DEBUG|INFO|WARN(?:ING)?|ERROR|FATAL)\s+(.+)$/i,
|
||||
// INFO 2024-01-15 10:23:45 message
|
||||
/^(DEBUG|INFO|WARN(?:ING)?|ERROR|FATAL)\s+(\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?)\s+(.+)$/i,
|
||||
// 10:23:43.333 [INF] message
|
||||
/^(\d{2}:\d{2}:\d{2}\.\d{3})\s\[(INF|WRN|ERR|CRT|DBG|TRC)\]\s(.*)$/
|
||||
];
|
||||
|
||||
let i = 0;
|
||||
debugger
|
||||
while (i < lines.length) {
|
||||
const line = lines[i].trim();
|
||||
let matched = false;
|
||||
@@ -875,7 +878,17 @@ function parseLogs(text) {
|
||||
} else {
|
||||
timeStr = g1; levelStr = g2.toUpperCase().replace('WARNING', 'WARN'); msg = g3;
|
||||
}
|
||||
const time = new Date(timeStr);
|
||||
levelStr = translateLogLevel(levelStr)
|
||||
let time
|
||||
if (filedate === null) {
|
||||
time = new Date(timeStr)
|
||||
}
|
||||
else {
|
||||
const [hours, mins, secs, ms] = timeStr.split(/[:.]/).map(Number);
|
||||
let temp_date = filedate.setHours(hours, mins, secs, ms)
|
||||
time = new Date(filedate)
|
||||
}
|
||||
|
||||
if (!isNaN(time)) {
|
||||
// Collect continuation lines (stack traces etc.)
|
||||
let exception = '';
|
||||
@@ -937,7 +950,7 @@ function parseLogs(text) {
|
||||
|
||||
const buckets = Array.from({ length: BUCKETS }, (_, i) => ({
|
||||
t: new Date(minT + i * bucketSize),
|
||||
DEBUG: 0, INFO: 0, WARN: 0, ERROR: 0, FATAL: 0, total: 0
|
||||
TRACE: 0, DEBUG: 0, INFO: 0, WARN: 0, ERROR: 0, FATAL: 0, total: 0
|
||||
}));
|
||||
|
||||
for (const log of logs) {
|
||||
@@ -950,14 +963,14 @@ function parseLogs(text) {
|
||||
if (chart) chart.destroy();
|
||||
|
||||
const colorMap = {
|
||||
DEBUG: '#55596640', INFO: '#4f8ef760', WARN: '#f5a62370', ERROR: '#e8504a80', FATAL: '#c72b2b90'
|
||||
TRACE: '#80808080', DEBUG: '#55596640', INFO: '#4f8ef760', WARN: '#f5a62370', ERROR: '#e8504a80', FATAL: '#c72b2b90'
|
||||
};
|
||||
|
||||
chart = new Chart(canvas, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: buckets.map(b => b.t),
|
||||
datasets: ['FATAL', 'ERROR', 'WARN', 'INFO', 'DEBUG'].map(level => ({
|
||||
datasets: ['FATAL', 'ERROR', 'WARN', 'INFO', 'DEBUG', 'TRACE'].map(level => ({
|
||||
label: level,
|
||||
data: buckets.map(b => b[level]),
|
||||
backgroundColor: colorMap[level],
|
||||
@@ -1161,13 +1174,55 @@ function parseLogs(text) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = e => {
|
||||
const text = e.target.result;
|
||||
allLogs = parseLogs(text);
|
||||
var date = parseDateFromFilename(file.name);
|
||||
allLogs = parseLogs(text, date);
|
||||
if (!allLogs.length) { allLogs = generateDemoLogs(); }
|
||||
initView(file.name);
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
|
||||
function parseDateFromFilename(filename) {
|
||||
const formats = [
|
||||
{ regex: /(\d{4})[-_](\d{2})[-_](\d{2})/, map: (m) => `${m[1]}-${m[2]}-${m[3]}` }, // YYYY-MM-DD
|
||||
{ regex: /(\d{2})[-_](\d{2})[-_](\d{4})/, map: (m) => `${m[3]}-${m[2]}-${m[1]}` }, // DD-MM-YYYY
|
||||
{ regex: /(\d{4})(\d{2})(\d{2})/, map: (m) => `${m[1]}-${m[2]}-${m[3]}` } // YYYYMMDD
|
||||
];
|
||||
|
||||
for (const { regex, map } of formats) {
|
||||
const match = filename.match(regex);
|
||||
if (match) {
|
||||
const isoString = map(match);
|
||||
const date = new Date(isoString);
|
||||
if (!isNaN(date.getTime())) return date;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function translateLogLevel(level) {
|
||||
//DEBUG: 0, INFO: 0, WARN: 0, ERROR: 0, FATAL: 0, total: 0
|
||||
// Normalize input to handle lowercase or uppercase variations
|
||||
switch (level.toLowerCase()) {
|
||||
case 'trc':
|
||||
return "TRACE";
|
||||
case 'dbg':
|
||||
return "DEBUG";
|
||||
case 'inf':
|
||||
return "INFO";
|
||||
case 'wrn':
|
||||
case 'warning': // Multiple cases can map to the same result
|
||||
return "WARN";
|
||||
case 'error':
|
||||
return "ERROR";
|
||||
case 'fatal':
|
||||
case 'crt':
|
||||
return "FATAL";
|
||||
default:
|
||||
return level; // Unknown level
|
||||
}
|
||||
}
|
||||
|
||||
function loadDemo() {
|
||||
allLogs = generateDemoLogs();
|
||||
initView('demo.log');
|
||||
@@ -1257,7 +1312,7 @@ function parseLogs(text) {
|
||||
const file = e.dataTransfer.files[0];
|
||||
if (file) loadFile(file);
|
||||
});
|
||||
|
||||
|
||||
// Load demo on start
|
||||
loadDemo();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user