Mastering Fastify: Tailoring Your Logging Approach
Written on
Chapter 1: Introduction to Fastify
Fastify is a lightweight framework for Node.js that is designed for building backend web applications. In this article, we will explore how to create backend applications using Fastify and focus on customizing the logging functionality.
Section 1.1: Customizing Response Logging
We can tailor the way responses are logged within Fastify. For example, you can implement the following code:
const fastify = require('fastify')({
logger: {
prettyPrint: true,
serializers: {
res(reply) {
return {
statusCode: reply.statusCode,};
},
req(request) {
return {
method: request.method,
url: request.url,
path: request.path,
parameters: request.parameters,
headers: request.headers,
};
},
},
},
});
fastify.get('/', (request, reply) => {
request.log.info('Some info');
reply.send({ hello: 'world' });
});
const start = async () => {
try {
await fastify.listen(3000, '0.0.0.0');} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
This code snippet shows how to serialize the log content of responses using the res method. Similarly, you can create a req method for request logging. Setting prettyPrint to true ensures that the output is formatted nicely.
Section 1.2: Logging Request Payloads
To log the payload of incoming requests, you can add a hook as shown below:
const fastify = require('fastify')({
logger: 'info',
});
fastify.addHook('preHandler', (req, reply, done) => {
if (req.body) {
req.log.info({ body: req.body }, 'parsed body');}
done();
});
fastify.post('/', (request, reply) => {
reply.send({ hello: 'world' });
});
const start = async () => {
try {
await fastify.listen(3000, '0.0.0.0');} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
In this setup, we utilize req.body and log it using req.log.info. Furthermore, you can also leverage the logger outside of route handlers.
Chapter 2: Using the Logger in Different Contexts
For instance, you can define a logger like this:
const log = require('pino')({ level: 'info' });
const fastify = require('fastify')({ logger: log });
log.info('does not have request information');
fastify.get('/', function (request, reply) {
request.log.info('includes request information, but is the same logger instance as log');
reply.send({ hello: 'world' });
});
const start = async () => {
try {
await fastify.listen(3000, '0.0.0.0');} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
In this code, log.info is called outside the route handler, while request.log.info is used within it.
Section 2.1: Redacting Sensitive Information
You can also redact sensitive information from your logs. For example:
const split = require('split2');
const stream = split(JSON.parse);
const fastify = require('fastify')({
logger: {
stream,
redact: ['req.headers.authorization'],
level: 'info',
serializers: {
req(request) {
return {
method: request.method,
url: request.url,
headers: request.headers,
hostname: request.hostname,
remoteAddress: request.ip,
remotePort: request.socket.remotePort,
};
},
},
},
});
fastify.get('/', function (request, reply) {
reply.send({ hello: 'world' });
});
const start = async () => {
try {
await fastify.listen(3000, '0.0.0.0');} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
Here, we add the redact property to avoid logging the value of req.headers.authorization.
This video, "Fastify Application Development | Logging with Pino.js," delves into practical logging techniques using Fastify.
The video titled "Pino JS - Logging in JavaScript / Node.js applications" offers insights into effective logging strategies in JavaScript and Node.js applications.
Conclusion
Fastify provides a flexible way to customize your logging strategy. For more detailed information, refer to the original source at plainenglish.io.