Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Logging with Pino

A log is a record of what happens on the server: a request arrived, an error occurred, a post was created. Fastify uses the Pino logger, which writes each record as one JSON line — easy to read for log collection tools.

Turning it on and the level

The logger is turned on with the logger option when creating the application. Instead of true you can pass an object with settings:

// src/server.js
import { buildApp } from './app.js';
 
const app = buildApp({
  logger: { level: 'info' },
});

The level filters out less important records: with info, debug and trace messages are not written.

LevelUsed for
fatalThe server cannot continue
errorAn error while handling a request
warnA suspicious situation
infoNormal events: requests, server start
debugDetails for debugging
traceThe finest details

Logging from a route

Each request has its own logger, request.log. Add a record to the create-post route:

// src/routes/posts.js
app.post('/posts', async (request, reply) => {
  const post = { id: app.posts.length + 1, ...request.body };
  app.posts.push(post);
  request.log.info({ postId: post.id }, 'Post created');
  return reply.code(201).send(post);
});

After POST /posts the terminal shows a line with the fields "postId":3, "msg":"Post created" and reqId — the request number. With reqId you can find every record of one request.

Readable output

JSON is hard to read by eye. For development install pino-pretty:

npm install --save-dev pino-pretty
// src/server.js
const app = buildApp({
  logger: {
    level: 'debug',
    transport: { target: 'pino-pretty' },
  },
});

Now each record is a coloured line with the time, level and message. On a production server transport is left out: plain JSON is needed there.

Hiding secrets

The redact option replaces the values of the listed fields with [Redacted]:

// src/server.js
const app = buildApp({
  logger: {
    level: 'info',
    redact: ['req.headers.authorization'],
  },
});

Tokens from the Authorization header never reach the logs, even if a request is logged in full.

The application log

Outside requests use app.log — for example, on start and stop:

// src/server.js
app.log.info('The blog is starting');

Common mistake

console.log inside routes works, but such records have no level and no reqId, so they cannot be filtered or turned off. Write through request.log in routes and app.log outside them.

Thanks for reading!

Donate to the site — we work hard for you.