Files
MixedAssets/server/services/appLogs.js

59 lines
2.1 KiB
JavaScript

const fs = require('fs');
const { LOG_FILE } = require('../logger');
// Read the application/event log (JSON lines written by the Winston file transport) for the admin
// Application Logs viewer. Reads the current log file, parses the most recent lines, and returns them
// newest-first with optional category/level/search filtering plus the available filter facets.
const SCAN_LINES = 8000; // how many trailing lines to parse (the file is size-rotated, ~5MB)
function readLogs(filters = {}, limit = 500) {
let lines = [];
try {
lines = fs.readFileSync(LOG_FILE, 'utf8').split('\n').filter(Boolean);
} catch {
return { logs: [], total: 0, categories: [], levels: [] };
}
// Parse the trailing window, newest first.
const parsed = [];
for (let i = lines.length - 1, scanned = 0; i >= 0 && scanned < SCAN_LINES; i -= 1, scanned += 1) {
try {
const obj = JSON.parse(lines[i]);
parsed.push({
timestamp: obj.timestamp || null,
level: obj.level || 'info',
category: obj.category || 'system',
message: obj.message || '',
meta: stripMeta(obj)
});
} catch {
// skip malformed lines
}
}
const categories = [...new Set(parsed.map((p) => p.category))].sort();
const levels = [...new Set(parsed.map((p) => p.level))].sort();
let filtered = parsed;
if (filters.category) filtered = filtered.filter((p) => p.category === filters.category);
if (filters.level) filtered = filtered.filter((p) => p.level === filters.level);
if (filters.q) {
const needle = String(filters.q).toLowerCase();
filtered = filtered.filter((p) => `${p.message} ${JSON.stringify(p.meta)}`.toLowerCase().includes(needle));
}
return { logs: filtered.slice(0, Math.min(2000, Number(limit) || 500)), total: filtered.length, categories, levels };
}
// Everything on a log line except the standard fields is "meta" (the structured detail).
function stripMeta(obj) {
const meta = {};
for (const [key, value] of Object.entries(obj)) {
if (!['timestamp', 'level', 'category', 'message'].includes(key)) meta[key] = value;
}
return meta;
}
module.exports = { readLogs };