Files
flyer-crawler.projectium.com/docs/adr/0052-granular-debug-logging-strategy.md
2026-01-26 04:51:09 -08:00

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.

  1. Logger Namespaces: Every service/module logger must be initialized with a module property (e.g., logger.child({ module: 'ai-service' })).
  2. Environment Filter: We will support a DEBUG_MODULES environment 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:

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

  1. Use Scoped Loggers for Long-Running Services: Services with complex workflows or external API calls should use createScopedLogger to allow targeted debugging.

  2. 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');
    }
    
  3. Module Naming Convention: Use kebab-case suffixed with -service or -worker (e.g., ai-service, email-worker).

  4. Production Usage: DEBUG_MODULES can 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)