From c5e8dca8ac451cb224c3705e26b19507c23a869c Mon Sep 17 00:00:00 2001 From: Al Azhar Date: Wed, 29 Apr 2026 09:43:59 +0700 Subject: [PATCH] read format --- index.html | 75 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/index.html b/index.html index 9c46573..f1c68b4 100644 --- a/index.html +++ b/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();