Platform review round 2: audit logging migration, nav unification, DB indexes, and UI polish
- Migrate ~41 inline audit log calls to shared logAudit() utility across all routers - Add transaction-aware prisma parameter to logAudit() for atomic operations - Unify jury/mentor/observer navigation into shared RoleNav component - Add composite DB indexes (Evaluation, GracePeriod, AuditLog) for query performance - Fix profile page: consolidate dual save buttons, proper useEffect initialization - Enhance auth error page with MOPC branding and navigation - Improve observer dashboard with prominent read-only badge - Fix DI-3: fetch projects before bulk status update for accurate notifications - Remove unused aiBoost field from smart-assignment scoring - Add shared image-upload utility and structured logger module Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
59
src/lib/logger.ts
Normal file
59
src/lib/logger.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Structured Logger Utility
|
||||
*
|
||||
* Provides tagged, level-aware logging for consistent output across the application.
|
||||
* Respects LOG_LEVEL environment variable and NODE_ENV for default levels.
|
||||
*
|
||||
* Usage:
|
||||
* import { logger } from '@/lib/logger'
|
||||
* logger.info('AI Assignment', 'Processing batch', { batchSize: 15 })
|
||||
* logger.error('Storage', 'Upload failed', error)
|
||||
*/
|
||||
|
||||
type LogLevel = 'debug' | 'info' | 'warn' | 'error'
|
||||
|
||||
const LOG_LEVELS: Record<LogLevel, number> = {
|
||||
debug: 0,
|
||||
info: 1,
|
||||
warn: 2,
|
||||
error: 3,
|
||||
}
|
||||
|
||||
function getConfiguredLevel(): LogLevel {
|
||||
const envLevel = process.env.LOG_LEVEL?.toLowerCase()
|
||||
if (envLevel && envLevel in LOG_LEVELS) {
|
||||
return envLevel as LogLevel
|
||||
}
|
||||
return process.env.NODE_ENV === 'production' ? 'warn' : 'debug'
|
||||
}
|
||||
|
||||
function shouldLog(level: LogLevel): boolean {
|
||||
return LOG_LEVELS[level] >= LOG_LEVELS[getConfiguredLevel()]
|
||||
}
|
||||
|
||||
function formatTimestamp(): string {
|
||||
return new Date().toISOString()
|
||||
}
|
||||
|
||||
export const logger = {
|
||||
debug: (tag: string, message: string, data?: unknown): void => {
|
||||
if (shouldLog('debug')) {
|
||||
console.debug(`${formatTimestamp()} [DEBUG] [${tag}]`, message, data ?? '')
|
||||
}
|
||||
},
|
||||
info: (tag: string, message: string, data?: unknown): void => {
|
||||
if (shouldLog('info')) {
|
||||
console.info(`${formatTimestamp()} [INFO] [${tag}]`, message, data ?? '')
|
||||
}
|
||||
},
|
||||
warn: (tag: string, message: string, data?: unknown): void => {
|
||||
if (shouldLog('warn')) {
|
||||
console.warn(`${formatTimestamp()} [WARN] [${tag}]`, message, data ?? '')
|
||||
}
|
||||
},
|
||||
error: (tag: string, message: string, data?: unknown): void => {
|
||||
if (shouldLog('error')) {
|
||||
console.error(`${formatTimestamp()} [ERROR] [${tag}]`, message, data ?? '')
|
||||
}
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user