![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/lavocat.ca/public_html/src/lib/ |
import { NextApiRequest } from 'next';
export interface LogContext {
userId?: string;
email?: string;
role?: string;
ip?: string;
userAgent?: string;
path?: string;
method?: string;
timestamp?: string;
[key: string]: any;
}
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'security';
class Logger {
private isDevelopment = process.env.NODE_ENV === 'development';
private formatMessage(level: LogLevel, message: string, context?: LogContext): string {
const timestamp = new Date().toISOString();
const contextStr = context ? JSON.stringify(context, null, 2) : '';
return `[${timestamp}] [${level.toUpperCase()}] ${message}${contextStr ? `\nContext: ${contextStr}` : ''}`;
}
private log(level: LogLevel, message: string, context?: LogContext): void {
const formattedMessage = this.formatMessage(level, message, context);
// In development, always log to console with colors
if (this.isDevelopment) {
const colors = {
debug: '\x1b[36m', // Cyan
info: '\x1b[32m', // Green
warn: '\x1b[33m', // Yellow
error: '\x1b[31m', // Red
security: '\x1b[35m', // Magenta
};
const reset = '\x1b[0m';
console.log(`${colors[level]}${formattedMessage}${reset}`);
} else {
// In production, log to console (you can extend this to send to external services)
console.log(formattedMessage);
}
// For security events, always log regardless of environment
if (level === 'security') {
// In production, you might want to send this to a security monitoring service
console.error(`🔒 SECURITY EVENT: ${formattedMessage}`);
}
}
debug(message: string, context?: LogContext): void {
if (this.isDevelopment) {
this.log('debug', message, context);
}
}
info(message: string, context?: LogContext): void {
this.log('info', message, context);
}
warn(message: string, context?: LogContext): void {
this.log('warn', message, context);
}
error(message: string, error?: Error | unknown, context?: LogContext): void {
const errorContext = {
...context,
error: error instanceof Error ? {
name: error.name,
message: error.message,
stack: error.stack,
} : error
};
this.log('error', message, errorContext);
}
security(message: string, context?: LogContext): void {
this.log('security', message, context);
}
// Helper to extract context from API request
getRequestContext(req: NextApiRequest, additionalContext?: LogContext): LogContext {
return {
ip: req.headers['x-forwarded-for'] as string || req.connection.remoteAddress || 'unknown',
userAgent: req.headers['user-agent'] || 'unknown',
path: req.url || 'unknown',
method: req.method || 'unknown',
timestamp: new Date().toISOString(),
...additionalContext
};
}
// Helper for authentication events
authEvent(event: 'login' | 'logout' | 'impersonate' | 'stop_impersonate' | 'failed_login', context: LogContext): void {
this.security(`AUTH_EVENT: ${event}`, {
event,
...context
});
}
// Helper for admin actions
adminAction(action: string, context: LogContext): void {
this.security(`ADMIN_ACTION: ${action}`, {
action,
...context
});
}
}
// Export singleton instance
export const logger = new Logger();
// Export types
export default logger;