245 lines
4.0 KiB
Markdown
245 lines
4.0 KiB
Markdown
Logging & Correlation ID Design Guide (Clean Architecture)
|
|
|
|
This document defines a clean, strict, and production-ready logging architecture with correlation IDs.
|
|
|
|
It removes ambiguity around:
|
|
• where logging belongs
|
|
• how context is attached
|
|
• how logs stay machine-readable
|
|
• how Clean Architecture boundaries are preserved
|
|
|
|
The rules below are non-negotiable.
|
|
|
|
⸻
|
|
|
|
Core Principles
|
|
|
|
Logs are data, not text.
|
|
Context is injected, never constructed in the Core.
|
|
|
|
Logging must:
|
|
• be machine-readable
|
|
• be framework-agnostic in the Core
|
|
• support correlation across requests
|
|
• be safe for parallel execution
|
|
|
|
⸻
|
|
|
|
Architectural Responsibilities
|
|
|
|
Core
|
|
• describes intent
|
|
• never knows about correlation IDs
|
|
• never knows about log destinations
|
|
|
|
App Layer (API)
|
|
• defines runtime context (request, user)
|
|
• binds correlation IDs
|
|
|
|
Adapters
|
|
• implement concrete loggers (console, file, structured)
|
|
• decide formatting and transport
|
|
|
|
⸻
|
|
|
|
1. Logger Port (Core)
|
|
|
|
Purpose
|
|
|
|
Defines what logging means, without defining how logging works.
|
|
|
|
⸻
|
|
|
|
Rules
|
|
• exactly one logging interface
|
|
• no framework imports
|
|
• no correlation or runtime context
|
|
|
|
⸻
|
|
|
|
Location
|
|
|
|
core/shared/application/LoggerPort.ts
|
|
|
|
|
|
⸻
|
|
|
|
Contract
|
|
• debug(message, meta?)
|
|
• info(message, meta?)
|
|
• warn(message, meta?)
|
|
• error(message, meta?)
|
|
|
|
Messages are semantic.
|
|
Metadata is optional and structured.
|
|
|
|
⸻
|
|
|
|
2. Request Context (App Layer)
|
|
|
|
Purpose
|
|
|
|
Represents runtime execution context.
|
|
|
|
⸻
|
|
|
|
Contains
|
|
• correlationId
|
|
• optional userId
|
|
|
|
⸻
|
|
|
|
Rules
|
|
• never visible to Core
|
|
• created per request
|
|
|
|
⸻
|
|
|
|
Location
|
|
|
|
apps/api/context/RequestContext.ts
|
|
|
|
|
|
⸻
|
|
|
|
3. Logger Implementations (Adapters)
|
|
|
|
Purpose
|
|
|
|
Provide concrete logging behavior.
|
|
|
|
⸻
|
|
|
|
Rules
|
|
• implement LoggerPort
|
|
• accept context via constructor
|
|
• produce structured logs
|
|
• no business logic
|
|
|
|
⸻
|
|
|
|
Examples
|
|
• ConsoleLogger
|
|
• FileLogger
|
|
• PinoLogger
|
|
• LokiLogger
|
|
|
|
⸻
|
|
|
|
Location
|
|
|
|
adapters/logging/
|
|
|
|
|
|
⸻
|
|
|
|
4. Logger Factory
|
|
|
|
Purpose
|
|
|
|
Creates context-bound logger instances.
|
|
|
|
⸻
|
|
|
|
Rules
|
|
• factory is injected
|
|
• logger instances are short-lived
|
|
• component name is bound here
|
|
|
|
⸻
|
|
|
|
Location
|
|
|
|
adapters/logging/LoggerFactory.ts
|
|
adapters/logging/LoggerFactoryImpl.ts
|
|
|
|
|
|
⸻
|
|
|
|
5. Correlation ID Handling
|
|
|
|
Where it lives
|
|
• API middleware
|
|
• message envelopes
|
|
• background job contexts
|
|
|
|
⸻
|
|
|
|
Rules
|
|
• generated once per request
|
|
• propagated across async boundaries
|
|
• never generated in the Core
|
|
|
|
⸻
|
|
|
|
6. Usage Rules by Layer
|
|
|
|
Layer Logging Allowed Notes
|
|
Domain ❌ No Throw domain errors instead
|
|
Use Cases ⚠️ Minimal Business milestones only
|
|
API Services ✅ Yes Main logging location
|
|
Adapters ✅ Yes IO, integration, failures
|
|
Frontend ⚠️ Limited Errors + analytics only
|
|
|
|
|
|
⸻
|
|
|
|
7. Forbidden Patterns
|
|
|
|
❌ Manual string prefixes ([ServiceName])
|
|
❌ Global/singleton loggers with mutable state
|
|
❌ any in logger abstractions
|
|
❌ Correlation IDs in Core
|
|
❌ Logging inside domain entities
|
|
|
|
⸻
|
|
|
|
8. File Structure (Final)
|
|
|
|
core/
|
|
└── shared/
|
|
└── application/
|
|
└── LoggerPort.ts # * required
|
|
|
|
apps/api/
|
|
├── context/
|
|
│ └── RequestContext.ts # * required
|
|
├── middleware/
|
|
│ └── CorrelationMiddleware.ts
|
|
└── modules/
|
|
└── */
|
|
└── *Service.ts
|
|
|
|
adapters/
|
|
└── logging/
|
|
├── LoggerFactory.ts # * required
|
|
├── LoggerFactoryImpl.ts # * required
|
|
├── ConsoleLogger.ts # optional
|
|
├── FileLogger.ts # optional
|
|
└── PinoLogger.ts # optional
|
|
|
|
|
|
⸻
|
|
|
|
Mental Model (Final)
|
|
|
|
The Core describes events.
|
|
The App provides context.
|
|
Adapters deliver telemetry.
|
|
|
|
If any layer violates this, the architecture is broken.
|
|
|
|
⸻
|
|
|
|
Summary
|
|
• one LoggerPort in the Core
|
|
• context bound outside the Core
|
|
• adapters implement logging destinations
|
|
• correlation IDs are runtime concerns
|
|
• logs are structured, searchable, and safe
|
|
|
|
This setup is:
|
|
• Clean Architecture compliant
|
|
• production-ready
|
|
• scalable
|
|
• refactor-safe |