/** * Common log enrichers */ import type { LogEntry, LogEnricher } from './types.js'; import { hostname } from 'os'; /** * Add hostname to log entry */ export const addHostInfo: LogEnricher = (entry: LogEntry): LogEntry => { return { ...entry, host: hostname(), }; }; /** * Add environment from NODE_ENV */ export const addEnvironment: LogEnricher = (entry: LogEntry): LogEntry => { return { ...entry, environment: process.env.NODE_ENV || 'development', }; }; /** * Add service info from environment variables */ export const addServiceInfo: LogEnricher = (entry: LogEntry): LogEntry => { return { ...entry, service: entry.service || process.env.SERVICE_NAME, version: entry.version || process.env.SERVICE_VERSION, }; }; /** * Add process info (PID, memory, uptime) */ export const addProcessInfo: LogEnricher = (entry: LogEntry): LogEntry => { const memoryUsage = process.memoryUsage(); return { ...entry, metadata: { ...entry.metadata, process: { pid: process.pid, uptime: process.uptime(), memory: { heapUsed: memoryUsage.heapUsed, heapTotal: memoryUsage.heapTotal, external: memoryUsage.external, rss: memoryUsage.rss, }, }, }, }; }; /** * Add timestamp if not present */ export const addTimestamp: LogEnricher = (entry: LogEntry): LogEntry => { return { ...entry, timestamp: entry.timestamp || new Date().toISOString(), }; }; /** * Sanitize sensitive data from log entry */ export const sanitizeSensitiveData = ( patterns: Array<{ path: string; replacement?: string }> ): LogEnricher => { return (entry: LogEntry): LogEntry => { const sanitized = { ...entry }; for (const { path, replacement = '[REDACTED]' } of patterns) { const parts = path.split('.'); let current: any = sanitized; for (let i = 0; i < parts.length - 1; i++) { if (current === null || current === undefined) break; current = current[parts[i] as string]; } if (current && parts.length > 0) { const lastPart = parts[parts.length - 1]; if (lastPart && current[lastPart] !== undefined) { current[lastPart] = replacement; } } } return sanitized; }; }; /** * Add custom tags based on log content */ export const addDynamicTags = ( taggers: Array<{ condition: (entry: LogEntry) => boolean; tag: string }> ): LogEnricher => { return (entry: LogEntry): LogEntry => { const tags = new Set(entry.tags || []); for (const { condition, tag } of taggers) { if (condition(entry)) { tags.add(tag); } } return { ...entry, tags: Array.from(tags), }; }; }; /** * Chain multiple enrichers */ export const chainEnrichers = (...enrichers: LogEnricher[]): LogEnricher => { return async (entry: LogEntry): Promise => { let enriched = entry; for (const enricher of enrichers) { enriched = await enricher(enriched); } return enriched; }; };