Files
gridpilot.gg/apps/website/lib/infrastructure/logging/ConsoleLogger.ts
2026-01-17 18:28:10 +01:00

104 lines
3.6 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 { injectable } from 'inversify';
import { Logger } from '../../interfaces/Logger';
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
@injectable()
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];
const timestamp = new Date().toISOString();
// 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} [${timestamp}] [${source.toUpperCase()}] ${prefix}: ${message}`, `color: ${color}; font-weight: bold;`);
} else {
// Simple format for edge runtime
console.log(`${emoji} [${timestamp}] [${source.toUpperCase()}] ${prefix}: ${message}`);
}
console.log(`%cTimestamp:`, 'color: #666; font-weight: bold;', timestamp);
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);
}
}