/** * Centralized logging utility for FitAI Admin App * Uses Pino for structured logging with appropriate log levels */ import pino from "pino"; /** * Create logger instance based on environment * - Development: JSON logs to console (pino-pretty disabled due to Turbopack compatibility) * - Production: JSON logs for aggregation/monitoring */ const logger = pino({ level: process.env.LOG_LEVEL || (process.env.NODE_ENV === "production" ? "info" : "debug"), formatters: { level: (label) => { return { level: label }; }, }, // Note: pino-pretty transport disabled for Next.js 15+ Turbopack compatibility // The transport uses worker threads which cause module resolution issues // Logs will be in JSON format in all environments }); /** * Log levels: * - debug: Detailed information for debugging (only in dev) * - info: General informational messages * - warn: Warning messages for potentially harmful situations * - error: Error messages for failures that don't stop the app * - fatal: Critical errors that may cause the app to crash */ export { logger }; /** * Convenience functions for common logging patterns */ export const log = { /** * Log debug information (only in development) */ debug: (message: string, data?: Record) => { logger.debug(data || {}, message); }, /** * Log general information */ info: (message: string, data?: Record) => { logger.info(data || {}, message); }, /** * Log warnings */ warn: (message: string, data?: Record) => { logger.warn(data || {}, message); }, /** * Log errors with optional error object */ error: (message: string, error?: unknown, data?: Record) => { const errorData: Record = { ...(data || {}), }; if (error instanceof Error) { errorData.error = { name: error.name, message: error.message, stack: error.stack, }; } else if (error && typeof error === "object") { errorData.error = error; } logger.error(errorData, message); }, /** * Log fatal errors (should be rare) */ fatal: (message: string, error?: unknown, data?: Record) => { const errorData: Record = { ...(data || {}), }; if (error instanceof Error) { errorData.error = { name: error.name, message: error.message, stack: error.stack, }; } else if (error && typeof error === "object") { errorData.error = error; } logger.fatal(errorData, message); }, /** * Log API requests (use in middleware or API routes) */ apiRequest: ( method: string, path: string, data?: Record, ) => { logger.info({ method, path, ...(data || {}) }, "API request"); }, /** * Log API responses */ apiResponse: ( method: string, path: string, status: number, duration?: number, data?: Record, ) => { logger.info( { method, path, status, duration, ...(data || {}) }, "API response", ); }, /** * Log database operations */ database: ( operation: string, table?: string, data?: Record, ) => { logger.debug({ operation, table, ...(data || {}) }, "Database operation"); }, /** * Log authentication events */ auth: (event: string, userId?: string, data?: Record) => { logger.info({ event, userId, ...(data || {}) }, "Authentication event"); }, }; export default log;