UNPKG

logsdx

Version:

log streaming with dx on the 🧠

361 lines (337 loc) • 12.5 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _chunkMA4X2JPVcjs = require('./chunk-MA4X2JPV.cjs'); var _chunkQ46SBW3Rcjs = require('./chunk-Q46SBW3R.cjs'); // src/cli/index.ts var _commander = require('commander'); var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs); // src/parsers/regex/line.ts function createRegexLineParser(rules) { return (line) => { let result; for (const rule of rules) { const match = line.match(rule.match); if (match) { const extracted = _optionalChain([rule, 'access', _ => _.extract, 'optionalCall', _2 => _2(line, match)]) || {}; if (extracted.timestamp && extracted.level && extracted.message) { return extracted; } result = { ...extracted, ...result // This ensures earlier matches take precedence }; } } if (result) { if (!result.timestamp) { const timestampMatch = line.match( /(\d{4}-\d{2}-\d{2}(?:T|\s+)\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?)/ ); if (timestampMatch) { result.timestamp = timestampMatch[1]; } } if (!result.message) { const messageMatch = line.match( /(?:\]|\d{2}(?:Z|[+-]\d{2}:?\d{2})?)\s+(?:\[\w+\])?\s+(.+)$/ ); if (messageMatch) { result.message = messageMatch[1]; } } return result; } return void 0; }; } // src/parsers/json/index.ts var _json5 = require('json5'); var _json52 = _interopRequireDefault(_json5); var DEFAULT_JSON_RULES = [ { match: "\\{.*\\}", lang: "json", level: "info", meta: { service: "service", timestamp: "timestamp", message: "message", level: "level" } } ]; function mapLogLevel(level) { const levelMap = { // Standard levels debug: "debug", info: "info", warn: "warn", warning: "warn", error: "error", err: "error", success: "success", trace: "trace", // Common variations fatal: "error", critical: "error", notice: "info", verbose: "debug", silly: "debug", // Status-based levels fail: "error", failed: "error", failure: "error", pending: "warn", in_progress: "info", completed: "success" }; const normalizedLevel = level.toLowerCase().trim(); return levelMap[normalizedLevel] || "info"; } async function loadJsonRules(filePath) { let rules = DEFAULT_JSON_RULES; if (filePath) { try { const data = _fs2.default.readFileSync(filePath, "utf-8"); const customRules = _json52.default.parse(data); if (Array.isArray(customRules) && customRules.length > 0) { rules = customRules; } } catch (error) { _chunkMA4X2JPVcjs.logger.warn( `Failed to load custom JSON rules: ${_json52.default.stringify(error)}` ); _chunkMA4X2JPVcjs.logger.info("Using default JSON rules instead"); } } return (line) => { try { if (!line.trim().startsWith("{") || !line.trim().endsWith("}")) { return void 0; } const json = _json52.default.parse(line); const result = { level: mapLogLevel( json.level || json.status || json.severity || "info" ), timestamp: json.timestamp || json.time || json.date || json["@timestamp"], message: json.message || json.msg || json.log || json.text, language: "json" }; for (const [key, value] of Object.entries(json)) { if (![ "level", "status", "severity", "timestamp", "time", "date", "@timestamp", "message", "msg", "log", "text" ].includes(key)) { result[key] = value; } } return result; } catch (error) { return void 0; } }; } // src/parsers/default.ts var defaultLineParser = (line) => { const result = {}; if (line.startsWith("[json]")) result.lang = "json"; if (line.startsWith("[sql]")) result.lang = "sql"; if (line.includes("ERROR")) result.level = "error"; if (line.includes("WARN")) result.level = "warn"; if (line.includes("INFO")) result.level = "info"; return result; }; // src/parsers/registry.ts var DEFAULT_CONFIG = { defaultRules: [ { match: /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z)\s+\[(\w+)\]\s+(.*)$/, extract: (line, match) => ({ timestamp: match[1], level: match[2].toLowerCase(), message: match[3] }) } ], levels: { debug: 0, info: 1, warn: 2, error: 3 } }; var parserRegistry = { // Default parser default: async () => defaultLineParser, // Built-in parsers regex: async () => { return createRegexLineParser(DEFAULT_CONFIG.defaultRules); }, json: async (options) => { return loadJsonRules(_optionalChain([options, 'optionalAccess', _3 => _3.rulesFile])); } }; function registerParser(name, factory) { parserRegistry[name] = factory; } async function getParser(name, options) { if (!parserRegistry[name]) { throw new Error( `Parser '${name}' not found. Available parsers: ${Object.keys(parserRegistry).join(", ")}` ); } return parserRegistry[name](options); } function getRegisteredParsers() { return Object.keys(parserRegistry); } // src/cli/index.ts var program = new (0, _commander.Command)(); program.name("logsdx").description("A powerful log parsing and formatting tool").version("0.0.1"); program.option("-q, --quiet", "Suppress all output except errors").option("-d, --debug", "Enable debug mode").option("-l, --level <level>", "Minimum log level to display", "info").option("-p, --parser <parser>", "Parser to use for log parsing", "default").option("-r, --rules <file>", "Path to custom rules file").option("-o, --output <file>", "Path to output file").option("--list-parsers", "List available parsers").option( "-t, --theme <theme>", "Theme to use (default, dark, light, minimal, or custom theme name)" ).option("--list-themes", "List available themes").argument("[input]", "Input file to process (defaults to stdin)").action(async (input, options) => { try { if (options.listParsers) { const parsers = getRegisteredParsers(); _chunkMA4X2JPVcjs.logger.info("Available parsers:"); parsers.forEach((parser2) => _chunkMA4X2JPVcjs.logger.info(` - ${parser2}`)); process.exit(0); } if (options.listThemes) { const config2 = _chunkQ46SBW3Rcjs.loadConfig.call(void 0, ); const themes = config2 ? Object.keys(config2.customThemes || {}) : []; _chunkMA4X2JPVcjs.logger.info("Available themes:"); _chunkMA4X2JPVcjs.logger.info("Built-in themes:"); _chunkMA4X2JPVcjs.logger.info(" - default"); _chunkMA4X2JPVcjs.logger.info(" - dark"); _chunkMA4X2JPVcjs.logger.info(" - light"); _chunkMA4X2JPVcjs.logger.info(" - minimal"); if (themes.length > 0) { _chunkMA4X2JPVcjs.logger.info("Custom themes:"); themes.forEach((theme) => _chunkMA4X2JPVcjs.logger.info(` - ${theme}`)); } process.exit(0); } if (options.debug) { _chunkMA4X2JPVcjs.logger.withConfig({ level: "debug", prefix: "CLI" }).debug("Debug mode enabled"); } const config = _chunkQ46SBW3Rcjs.loadConfig.call(void 0, ); if (options.theme) { if (options.debug) { _chunkMA4X2JPVcjs.logger.withConfig({ level: "debug", prefix: "CLI" }).debug(`Using theme: ${options.theme}`); } _chunkQ46SBW3Rcjs.setTheme.call(void 0, options.theme); } else if (_optionalChain([config, 'optionalAccess', _4 => _4.theme])) { if (options.debug) { _chunkMA4X2JPVcjs.logger.withConfig({ level: "debug", prefix: "CLI" }).debug(`Using theme from config: ${config.theme}`); } _chunkQ46SBW3Rcjs.setTheme.call(void 0, config.theme); } if (options.level && !["debug", "info", "warn", "error"].includes(options.level)) { throw new Error(`Invalid log level: ${options.level}`); } const inputStream = input ? _fs2.default.createReadStream(input) : process.stdin; if (input && options.debug) { _chunkMA4X2JPVcjs.logger.withConfig({ level: "debug", prefix: "CLI" }).debug(`Input file set to: ${input}`); } const outputStream = options.output ? _fs2.default.createWriteStream(options.output) : process.stdout; if (options.output && options.debug) { _chunkMA4X2JPVcjs.logger.withConfig({ level: "debug", prefix: "CLI" }).debug(`Output file set to: ${options.output}`); } const parser = await getParserForOptions(options); let buffer = ""; inputStream.on("data", (chunk) => { buffer += chunk.toString(); const lines = buffer.split("\n"); buffer = lines.pop() || ""; for (const line of lines) { if (!line.trim()) continue; const parsed = parser(line); const level = _optionalChain([parsed, 'optionalAccess', _5 => _5.level]) || "info"; if (shouldRender(level, options.level)) { const formattedLine = _chunkQ46SBW3Rcjs.styleManager.styleLine( line, parsed, options.parser || "default" ); if (outputStream === process.stdout) { process.stdout.write(formattedLine + "\n"); } else { outputStream.write(formattedLine + "\n"); } } } }); inputStream.on("end", () => { if (buffer.trim()) { const parsed = parser(buffer); const level = _optionalChain([parsed, 'optionalAccess', _6 => _6.level]) || "info"; if (shouldRender(level, options.level)) { const formattedLine = _chunkQ46SBW3Rcjs.styleManager.styleLine( buffer, parsed, options.parser || "default" ); if (outputStream === process.stdout) { process.stdout.write(formattedLine + "\n"); } else { outputStream.write(formattedLine + "\n"); } } } if (options.output) { outputStream.end(); } }); inputStream.on("error", (error) => { _chunkMA4X2JPVcjs.logger.error("Error reading input:", error); process.exit(1); }); } catch (error) { _chunkMA4X2JPVcjs.logger.error("Error:", error); process.exit(1); } }); program.parse(); async function getParserForOptions(options) { const parserName = options.parser || "default"; try { if (options.debug) { _chunkMA4X2JPVcjs.logger.withConfig({ level: "debug", prefix: "CLI" }).debug(`Using parser: ${parserName}`); } return await getParser(parserName, { rulesFile: options.rules }); } catch (error) { _chunkMA4X2JPVcjs.logger.error(`Error loading parser '${parserName}':`, error); _chunkMA4X2JPVcjs.logger.info(`Available parsers: ${getRegisteredParsers().join(", ")}`); process.exit(1); } } function shouldRender(level, minLevel) { if (!minLevel || !level) return true; const levelPriorities = { debug: 0, info: 1, warn: 2, error: 3, success: 1, trace: 0 }; const current = _nullishCoalesce(levelPriorities[level], () => ( 0)); const min = _nullishCoalesce(levelPriorities[minLevel], () => ( 0)); return current >= min; } exports.createRegexLineParser = createRegexLineParser; exports.DEFAULT_JSON_RULES = DEFAULT_JSON_RULES; exports.loadJsonRules = loadJsonRules; exports.defaultLineParser = defaultLineParser; exports.registerParser = registerParser; exports.getParser = getParser; exports.getRegisteredParsers = getRegisteredParsers; exports.program = program; exports.getParserForOptions = getParserForOptions; exports.shouldRender = shouldRender; //# sourceMappingURL=chunk-QBEC4U26.cjs.map