refactor: replace ConsoleLogger with nestjs-pino for ISO 8601 timestamps#445
refactor: replace ConsoleLogger with nestjs-pino for ISO 8601 timestamps#445
Conversation
There was a problem hiding this comment.
Pull request overview
This PR switches the backend’s logging implementation from Nest’s ConsoleLogger to nestjs-pino/pino-http to emit ISO 8601 timestamps (and keep a ConsoleLogger-like JSON shape) for improved readability in production logs.
Changes:
- Add
nestjs-pino,pino, andpino-httpdependencies and lockfile updates. - Introduce shared pino configuration (
buildLoggerModuleParams,createPinoExitLogger) and wireLoggerModuleintoAppModuleandWorkerModule. - Update bootstrap/startup logging paths (
main.ts,database.module.ts) to use pino-based loggers and remove the oldlog-levels.tshelper.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds lock entries for nestjs-pino, pino, and pino-http. |
| apps/backend/package.json | Adds runtime deps needed for the new logger stack. |
| apps/backend/src/common/pino.config.ts | New shared logger config + exit logger factory. |
| apps/backend/src/app.module.ts | Registers LoggerModule for API runtime logging. |
| apps/backend/src/worker.module.ts | Registers LoggerModule for worker/metrics runtime logging. |
| apps/backend/src/main.ts | Activates NativeLogger during bootstrap and replaces pre-bootstrap logger. |
| apps/backend/src/database/database.module.ts | Replaces startup diagnostics logger with pino-based logger. |
| apps/backend/src/common/log-levels.ts | Removes old ConsoleLogger log-level resolution helper. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (2)
apps/backend/src/app.module.ts:24
LoggerModule.forRoot(buildLoggerModuleParams())is evaluated beforeConfigModule.forRoot(...), so any.envvalues loaded by Nest Config (includingLOG_LEVEL) won’t be available whenbuildLoggerModuleParams()readsprocess.env. Reorder the imports array soConfigModule.forRoot(...)is evaluated first, or switch toLoggerModule.forRootAsyncand injectConfigServiceto resolve the log level after config initialization.
imports: [
LoggerModule.forRoot(buildLoggerModuleParams()),
ConfigModule.forRoot({
load: [loadConfig],
validationSchema: configValidationSchema,
isGlobal: true,
}),
apps/backend/src/worker.module.ts:17
- Same issue as
AppModule:LoggerModule.forRoot(buildLoggerModuleParams())runs beforeConfigModule.forRoot(...), so.env-loaded values (e.g.,LOG_LEVEL) won’t be present when logger params are built. Reorder these calls or useforRootAsyncwithConfigServiceso logger configuration uses the validated/loaded config.
imports: [
LoggerModule.forRoot(buildLoggerModuleParams()),
ConfigModule.forRoot({
load: [loadConfig],
validationSchema: configValidationSchema,
isGlobal: true,
}),
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
rjan90
left a comment
There was a problem hiding this comment.
One small nit to reduce extra logging. Else it looks good to me
SgtPooki
left a comment
There was a problem hiding this comment.
lgtm, but i am running locally quick to confirm that logs are appearing properly
|
logs seem to be outputting fine |
Summary
Backend JSON logs emitted a Unix millisecond integer for the timestamp field (
"timestamp":1775081543138), making logs difficult to read in production tooling without post-processing. This PR replaces the default NestJSConsoleLoggerwith nestjs-pino /pino-httpto produce human-friendly ISO 8601 timestamps while preserving the existing ConsoleLogger-compatible JSON field layout.Log format (before -> after)
Before:
{"level":"log","pid":12671,"timestamp":1776163682800,"message":{"event":"synapse_initialization","message":"Creating shared Synapse instance"},"context":"DealService"} {"level":"log","pid":12671,"timestamp":1776163682802,"message":{"event":"pgboss_initialization","message":"Starting pg-boss initialization"},"context":"JobsService"}After:
{"level":"log","timestamp":"2026-04-14T11:05:01.191Z","pid":13785,"context":"DealService","message":{"event":"synapse_initialization","message":"Creating shared Synapse instance"}} {"level":"log","timestamp":"2026-04-14T11:05:01.193Z","pid":13785,"context":"JobsService","message":{"event":"pgboss_initialization","message":"Starting pg-boss initialization"}}closes #432