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.
| Level | Used for |
|---|---|
fatal | The server cannot continue |
error | An error while handling a request |
warn | A suspicious situation |
info | Normal events: requests, server start |
debug | Details for debugging |
trace | The 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.