Files
gridpilot.gg/apps/website/lib/infrastructure/logging/ConsoleLogger.ts
2026-01-16 01:00:03 +01:00

101 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Logger } from '../../interfaces/Logger';
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
export class ConsoleLogger implements Logger {
private readonly COLORS: Record<LogLevel, string> = {
debug: '#888888',
info: '#00aaff',
warn: '#ffaa00',
error: '#ff4444',
};
private readonly EMOJIS: Record<LogLevel, string> = {
debug: '🐛',
info: '',
warn: '⚠️',
error: '❌',
};
private readonly PREFIXES: Record<LogLevel, string> = {
debug: 'DEBUG',
info: 'INFO',
warn: 'WARN',
error: 'ERROR',
};
private shouldLog(level: LogLevel): boolean {
if (process.env.NODE_ENV === 'test') return level === 'error';
if (process.env.NODE_ENV === 'production') return level !== 'debug';
return true;
}
private formatOutput(level: LogLevel, source: string, message: string, context?: unknown, error?: Error): void {
const color = this.COLORS[level];
const emoji = this.EMOJIS[level];
const prefix = this.PREFIXES[level];
// Edge runtime doesn't support console.groupCollapsed/groupEnd
// Fallback to simple logging for compatibility
const supportsGrouping = typeof console.groupCollapsed === 'function' && typeof console.groupEnd === 'function';
if (supportsGrouping) {
// Safe to call - we've verified both functions exist
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(console as any).groupCollapsed(`%c${emoji} [${source.toUpperCase()}] ${prefix}: ${message}`, `color: ${color}; font-weight: bold;`);
} else {
// Simple format for edge runtime
console.log(`${emoji} [${source.toUpperCase()}] ${prefix}: ${message}`);
}
console.log(`%cTimestamp:`, 'color: #666; font-weight: bold;', new Date().toISOString());
console.log(`%cSource:`, 'color: #666; font-weight: bold;', source);
if (context) {
console.log(`%cContext:`, 'color: #666; font-weight: bold;');
// console.dir may not be available in edge runtime
if (typeof console.dir === 'function') {
console.dir(context, { depth: 3, colors: true });
} else {
console.log(JSON.stringify(context, null, 2));
}
}
if (error) {
console.log(`%cError Details:`, 'color: #666; font-weight: bold;');
console.log(`%cType:`, 'color: #ff4444; font-weight: bold;', error.name);
console.log(`%cMessage:`, 'color: #ff4444; font-weight: bold;', error.message);
if (process.env.NODE_ENV === 'development' && error.stack) {
console.log(`%cStack Trace:`, 'color: #666; font-weight: bold;');
console.log(error.stack);
}
}
if (supportsGrouping) {
// Safe to call - we've verified the function exists
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(console as any).groupEnd();
}
}
debug(message: string, context?: unknown): void {
if (!this.shouldLog('debug')) return;
this.formatOutput('debug', 'website', message, context);
}
info(message: string, context?: unknown): void {
if (!this.shouldLog('info')) return;
this.formatOutput('info', 'website', message, context);
}
warn(message: string, context?: unknown): void {
if (!this.shouldLog('warn')) return;
this.formatOutput('warn', 'website', message, context);
}
error(message: string, error?: Error, context?: unknown): void {
if (!this.shouldLog('error')) return;
this.formatOutput('error', 'website', message, context, error);
}
}