Dung (Donny) Nguyen

Senior Software Engineer

AdonisJS Logger

AdonisJS includes a built-in logging system powered by Pino, one of the fastest Node.js logging libraries that generates logs in NDJSON format. Here’s a comprehensive summary of its features:

Basic Usage

// Import the logger service
import logger from '@adonisjs/core/services/logger'

// Write logs
logger.info('this is an info message')
logger.error({ err: error }, 'Something went wrong')

For HTTP requests, use the context-aware logger:

router.get('/users/:id', async ({ logger, params }) => {
  logger.info('Fetching user by id %s', params.id)
  const user = await User.find(params.id)
})

Configuration

Transport Targets

Conditional Targets

// Using the targets helper for cleaner configuration
transport: {
  targets: targets()
    .pushIf(app.inDev, targets.pretty())
    .pushIf(app.inProduction, targets.file())
    .toArray()
}

Multiple Loggers

// Configure multiple loggers
loggers: {
  app: { /* config */ },
  payments: { /* config */ }
}

// Access specific loggers
logger.use('payments')
logger.use('app')
logger.use() // Default logger

Dependency Injection

import { inject } from '@adonisjs/core'
import { Logger } from '@adonisjs/core/logger'

@inject()
class UserService {
  constructor(protected logger: Logger) {}
  
  async find(userId: string | number) {
    this.logger.info('Fetching user by id %s', userId)
    // ...
  }
}

Logging Methods

Conditional Logging

// Check if level is enabled before computing expensive data
if (logger.isLevelEnabled('debug')) {
  const data = await getLogData()
  logger.debug(data, 'Debug message')
}

// Or use the helper method
logger.ifLevelEnabled('debug', async () => {
  const data = await getLogData()
  logger.debug(data, 'Debug message')
})

Child Loggers

// Create isolated logger instance with inherited config
const requestLogger = logger.child({ requestId: ctx.request.id() })

// Child logger with different log level
logger.child({}, { level: 'warn' })

File Logging

// Write logs to a file
transport: {
  targets: targets()
    .push({
      transport: 'pino/file',
      options: {
        destination: '/var/log/apps/adonisjs.log'
      }
    })
    .toArray()
}

File Rotation

Hiding Sensitive Data

// Using redaction
redact: {
  paths: ['password', '*.password'],
  censor: '[PRIVATE]' // Optional custom placeholder
}

// Or using the Secret class
import { Secret } from '@adonisjs/core/helpers'
const password = new Secret(request.input('password'))
logger.info({ username, password }, 'user signup')
// Output: {"username":"virk","password":"[redacted]"}

Serialize Objects

To log the full internal data of an object with the Adonis logger, you need to manually serialize the object to a string, typically using JSON.stringify().

import Logger from '@ioc:Adonis/Core/Logger'

Logger.info('affiliate %s', JSON.stringify(affiliate, null, 2))

This logging system provides a flexible, performant solution for application logging with support for multiple environments and sensitive data handling.