137 lines
3.0 KiB
TypeScript
137 lines
3.0 KiB
TypeScript
|
|
/**
|
||
|
|
* 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<LogEntry> => {
|
||
|
|
let enriched = entry;
|
||
|
|
for (const enricher of enrichers) {
|
||
|
|
enriched = await enricher(enriched);
|
||
|
|
}
|
||
|
|
return enriched;
|
||
|
|
};
|
||
|
|
};
|