From 32eca01d3d94188964130b38c97bc1dc9be0a761 Mon Sep 17 00:00:00 2001 From: Mrugesh Mohapatra Date: Sun, 19 Jan 2025 11:45:50 +0530 Subject: [PATCH] fix(api): improve logging --- api/src/routes/public/status.ts | 22 +++++++++++++++++++++- api/src/server.ts | 33 ++++++++++++++++++++++++++++----- api/src/utils/env.ts | 2 +- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/api/src/routes/public/status.ts b/api/src/routes/public/status.ts index d42c42762f9..c31953e6df5 100644 --- a/api/src/routes/public/status.ts +++ b/api/src/routes/public/status.ts @@ -1,4 +1,5 @@ import { type FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebox'; +import { isEmpty } from 'lodash'; /** * Plugin for the health check endpoint. @@ -13,7 +14,26 @@ export const statusRoute: FastifyPluginCallbackTypebox = ( _options, done ) => { - fastify.get('/status/ping', async (_req, _reply) => { + fastify.get('/status/ping', async (req, _reply) => { + const url = req.url || 'URL not found'; + const reqId = req.id || 'REQ_ID not found'; + const headers = isEmpty(req.headers) ? 'HEADERS not found' : req.headers; + const ip = + req.headers['x-forwarded-for'] || + req.headers['x-real-ip'] || + req.ip || + 'IP not found'; + const params = isEmpty(req.params) ? 'PARAMS not found' : req.params; + + fastify.log + .child({ + URL: url, + REQ_ID: reqId, + HEADERS: headers, + IP: ip, + PARAMS: params + }) + .debug('returning a ping'); return { msg: 'pong' }; }); diff --git a/api/src/server.ts b/api/src/server.ts index c846c60e197..6d3b3ecf87f 100644 --- a/api/src/server.ts +++ b/api/src/server.ts @@ -3,6 +3,8 @@ // is not included in the build (it's a dev dependency). // eslint-disable-next-line @typescript-eslint/triple-slash-reference /// +import { randomBytes } from 'crypto'; +import { FastifyRequest } from 'fastify'; import { build } from './app'; import { FREECODECAMP_NODE_ENV, @@ -11,25 +13,46 @@ import { PORT } from './utils/env'; +const requestSerializer = (request: FastifyRequest) => ({ + method: request.method, + url: request.url, + ip: request.headers['x-forwarded-for'] || request.ip, + hostname: request.hostname, + remoteAddress: Array.isArray(request.headers['x-forwarded-for']) + ? request.headers['x-forwarded-for'][0] + : request.headers['x-forwarded-for'] || request.ip, + remotePort: request.socket.remotePort +}); + const envToLogger = { development: { transport: { target: 'pino-pretty', options: { + singleLine: true, translateTime: 'HH:MM:ss Z', ignore: 'pid,hostname' } }, - level: FCC_API_LOG_LEVEL || 'info' + level: FCC_API_LOG_LEVEL || 'info', + serializers: { + req: requestSerializer + } }, production: { - level: FCC_API_LOG_LEVEL || 'info' - }, - test: undefined + level: FCC_API_LOG_LEVEL || 'info', + serializers: { + req: requestSerializer + } + } }; const start = async () => { - const fastify = await build({ logger: envToLogger[FREECODECAMP_NODE_ENV] }); + const fastify = await build({ + logger: envToLogger[FREECODECAMP_NODE_ENV] ?? true, + genReqId: () => randomBytes(8).toString('hex'), + disableRequestLogging: true + }); try { const port = Number(PORT); fastify.log.info(`Starting server on port ${port}`); diff --git a/api/src/utils/env.ts b/api/src/utils/env.ts index 2c77a646725..9c6aa02d0d8 100644 --- a/api/src/utils/env.ts +++ b/api/src/utils/env.ts @@ -6,7 +6,7 @@ import { LogLevel } from 'fastify'; const envPath = path.resolve(__dirname, '../../../.env'); const { error } = config({ path: envPath }); -if (error) { +if (error && process.env.FREECODECAMP_NODE_ENV !== 'production') { console.warn(` ---------------------------------------------------- Warning: .env file not found.