4.5 KiB
ADR-052: Granular Debug Logging Strategy
Date: 2026-01-11
Status: Accepted (Fully Implemented)
Related: ADR-004
Context
Global log levels (INFO vs DEBUG) are too coarse. Developers need to inspect detailed debug information for specific subsystems (e.g., ai-service, db-pool) without being flooded by logs from the entire application.
Decision
We will adopt a namespace-based debug filter pattern, similar to the debug npm package, but integrated into our Pino logger.
- Logger Namespaces: Every service/module logger must be initialized with a
moduleproperty (e.g.,logger.child({ module: 'ai-service' })). - Environment Filter: We will support a
DEBUG_MODULESenvironment variable that overrides the log level for matching modules.
Implementation
Core Implementation (Completed 2026-01-11)
Implemented in src/services/logger.server.ts:140-150:
const debugModules = (process.env.DEBUG_MODULES || '').split(',').map((s) => s.trim());
export const createScopedLogger = (moduleName: string) => {
// If DEBUG_MODULES contains "ai-service" or "*", force level to 'debug'
const isDebugEnabled = debugModules.includes('*') || debugModules.includes(moduleName);
return logger.child({
module: moduleName,
level: isDebugEnabled ? 'debug' : logger.level,
});
};
Adopted Services (Completed 2026-01-26)
Services currently using createScopedLogger:
ai-service- AI/Gemini integration (src/services/aiService.server.ts:1020)flyer-processing-service- Flyer upload and processing (src/services/flyerProcessingService.server.ts:20)
Usage
Enable Debug Logging for Specific Modules
To debug only AI and flyer processing:
DEBUG_MODULES=ai-service,flyer-processing-service npm run dev
Enable All Debug Logging
Use wildcard to enable debug logging for all modules:
DEBUG_MODULES=* npm run dev
Common Module Names
| Module Name | Purpose | File |
|---|---|---|
ai-service |
AI/Gemini API interactions | src/services/aiService.server.ts |
flyer-processing-service |
Flyer upload, validation, and processing | src/services/flyerProcessingService.server.ts |
Best Practices
-
Use Scoped Loggers for Long-Running Services: Services with complex workflows or external API calls should use
createScopedLoggerto allow targeted debugging. -
Use Child Loggers for Contextual Data: Even within scoped loggers, create child loggers with job/request-specific context:
const logger = createScopedLogger('my-service'); async function processJob(job: Job) { const jobLogger = logger.child({ jobId: job.id, jobName: job.name }); jobLogger.debug('Starting job processing'); } -
Module Naming Convention: Use kebab-case suffixed with
-serviceor-worker(e.g.,ai-service,email-worker). -
Production Usage:
DEBUG_MODULEScan be set in production for temporary debugging, but should not be used continuously due to increased log volume.
Examples
Development Debugging
Debug AI service issues during development:
# Dev container
DEBUG_MODULES=ai-service npm run dev
# Or via PM2
DEBUG_MODULES=ai-service pm2 restart flyer-crawler-api-dev
Production Troubleshooting
Temporarily enable debug logging for a specific subsystem:
# SSH into production server
ssh root@projectium.com
# Set environment variable and restart
DEBUG_MODULES=ai-service pm2 restart flyer-crawler-api
# View logs
pm2 logs flyer-crawler-api --lines 100
# Disable debug logging
pm2 unset DEBUG_MODULES flyer-crawler-api
pm2 restart flyer-crawler-api
Consequences
Positive:
- Developers can inspect detailed logs for specific subsystems without log flooding
- Production debugging becomes more targeted and efficient
- No performance impact when debug logging is disabled
- Compatible with existing Pino logging infrastructure
Negative:
- Requires developers to know module names (mitigated by documentation above)
- Not all services have adopted scoped loggers yet (gradual migration)