Skip to content

refactor: replace ConsoleLogger with nestjs-pino for ISO 8601 timestamps#445

Open
silent-cipher wants to merge 3 commits intomainfrom
fix/human-friendly-timestamp
Open

refactor: replace ConsoleLogger with nestjs-pino for ISO 8601 timestamps#445
silent-cipher wants to merge 3 commits intomainfrom
fix/human-friendly-timestamp

Conversation

@silent-cipher
Copy link
Copy Markdown
Collaborator

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 NestJS ConsoleLogger with nestjs-pino / pino-http to 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

Copilot AI review requested due to automatic review settings April 14, 2026 11:27
@FilOzzy FilOzzy added this to FOC Apr 14, 2026
@github-project-automation github-project-automation bot moved this to 📌 Triage in FOC Apr 14, 2026
@rjan90 rjan90 moved this from 📌 Triage to 🔎 Awaiting review in FOC Apr 14, 2026
@rjan90 rjan90 added this to the M4.2: mainnet GA milestone Apr 14, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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, and pino-http dependencies and lockfile updates.
  • Introduce shared pino configuration (buildLoggerModuleParams, createPinoExitLogger) and wire LoggerModule into AppModule and WorkerModule.
  • Update bootstrap/startup logging paths (main.ts, database.module.ts) to use pino-based loggers and remove the old log-levels.ts helper.

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 before ConfigModule.forRoot(...), so any .env values loaded by Nest Config (including LOG_LEVEL) won’t be available when buildLoggerModuleParams() reads process.env. Reorder the imports array so ConfigModule.forRoot(...) is evaluated first, or switch to LoggerModule.forRootAsync and inject ConfigService to 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 before ConfigModule.forRoot(...), so .env-loaded values (e.g., LOG_LEVEL) won’t be present when logger params are built. Reorder these calls or use forRootAsync with ConfigService so 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.

Comment thread apps/backend/src/common/pino.config.ts Outdated
Comment thread apps/backend/src/main.ts
Comment thread apps/backend/src/database/database.module.ts Outdated
Comment thread apps/backend/src/main.ts Outdated
Comment thread apps/backend/src/common/pino.config.ts
Comment thread apps/backend/src/common/pino.config.ts Outdated
Comment thread apps/backend/src/common/pino.config.ts
Copy link
Copy Markdown
Contributor

@rjan90 rjan90 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small nit to reduce extra logging. Else it looks good to me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 🔎 Awaiting review

Development

Successfully merging this pull request may close these issues.

Dealbot logs should use human-friendly ISO8601 for timestamp

4 participants