@@ -47,16 +47,19 @@ server.register(compression, {
4747server.setErrorHandler((error, request, reply) => {
4848 const alreadySent = reply.sent || reply.raw.headersSent || reply.raw.writableEnded;
4949 const errorCode = error.statusCode || 500;
50- const errorLog = {
51- reqId: request.id,
52- correlationId: request.correlationId,
53- url: request.url,
54- method: request.method,
55- statusCode: errorCode,
56- error: error.message,
57- stack: error.stack
58- };
59- request.log.error(errorLog);
50+ if(error.stack){
51+ const wrappedError = new Error(error.message);
52+ wrappedError.stack = error.stack;
53+ // important! the first parameter of log.error is the error object with an optional second parameter
54+ // for the message.
55+ request.log.error(wrappedError, `Request error: ${error.message}`);
56+ } else {
57+ // if the error is not an instance of Error, we should log it as a string. if first parameter is a string,
58+ // then args from the second parameter are ignored. so always only log:
59+ // one string parameter or (err,string) for request.log.error
60+ // for request.log.info, pino only supports a single string parameter. this is important for logs to work.
61+ request.log.error(`Request error: ${error.message}`);
62+ }
6063 if(alreadySent){
6164 // the api already set the appropriate error message. we shouldnt do anything now.
6265 return;
@@ -85,11 +88,20 @@ server.addHook('onRequest', (request, reply, done) => {
8588
8689 request.startTime = Date.now();
8790 if (request.headers['content-length']) {
91+ // for request.log.info, pino only supports a single string parameter or a serializable json
92+ // with a `message` attribute like below. this is important for logs to work. you can put in url and other
93+ // ewll known fields we support in our logging dashboard. you need not do this, only a string is needed and
94+ // in dashboard the request id is injected with the log line. use object instead of string only for
95+ // additional attributes like correlation id, url, size etc. these needs not be with every request as you
96+ // can search all these with the request id in the dashboard to get context, so plain strings are
97+ // recommended for logging info in most cases.
8898 request.log.info({
99+ message: 'Request size',
89100 reqId: request.id,
101+ url: request.url,
90102 correlationId: request.correlationId,
91103 size: `${request.headers['content-length']} bytes`
92- }, 'Request size' );
104+ });
93105 }
94106 done();
95107});
@@ -109,31 +121,27 @@ server.addHook('onRequest', (request, reply, done) => {
109121 });
110122 if (!routeExists) {
111123 request.log.error({
124+ message: 'Route not found',
112125 reqId: request.id,
113126 correlationId: request.correlationId,
114127 url: sanitizedUrl,
115128 method: request.method,
116129 ip: request.ips
117- }, "Route not found" );
130+ });
118131 reply.code(HTTP_STATUS_CODES.NOT_FOUND);
119132 return reply.send({error: 'Not Found'});
120133 } else if (!isAuthenticated(request)) {
121134 request.log.warn({
135+ message: 'Unauthorized access attempt',
122136 reqId: request.id,
123137 correlationId: request.correlationId,
124138 url: sanitizedUrl,
125139 method: request.method,
126140 ip: request.ips
127- }, "Unauthorized access attempt" );
141+ });
128142 reply.code(HTTP_STATUS_CODES.UNAUTHORIZED);
129143 return reply.send({error: 'Unauthorized'});
130144 }
131- request.log.info({
132- reqId: request.id,
133- correlationId: request.correlationId,
134- url: sanitizedUrl,
135- method: request.method
136- }, "Request authenticated");
137145 done();
138146});
139147
@@ -153,13 +161,14 @@ server.addHook('onRequest', (request, reply, done) => {
153161server.addHook('onResponse', (request, reply, done) => {
154162 const duration = Date.now() - request.startTime;
155163 request.log.info({
164+ message: 'Request completed',
156165 reqId: request.id,
157166 correlationId: request.correlationId,
158167 url: request.url,
159168 method: request.method,
160169 statusCode: reply.statusCode,
161170 duration: `${duration}ms`
162- }, 'Request completed' );
171+ });
163172 done();
164173});
165174
@@ -264,9 +273,9 @@ export async function startServer() {
264273 port: configs.port,
265274 host: configs.allowPublicAccess ? '0.0.0.0' : 'localhost'
266275 });
267- server.log.info({message: `Server started on port ${configs.port}`} );
276+ server.log.info(`Server started on port ${configs.port}`);
268277 } catch (err) {
269- server.log.error({message: 'Error starting server', error: err} );
278+ server.log.error(err, 'Error starting server');
270279 process.exit(1);
271280 }
272281}
@@ -278,41 +287,45 @@ export async function close() {
278287 server.log.info({message: 'Shutting down server...'});
279288 try {
280289 const shutdownTimeout = setTimeout(() => {
281- server.log.error({message: 'Forced shutdown after timeout'} );
290+ server.log.error('Forced shutdown after timeout');
282291 process.exit(1);
283292 }, CLEANUP_GRACE_TIME_5SEC);
284293
285294 await server.close();
286295 clearTimeout(shutdownTimeout);
287- server.log.info({message: 'Server shut down successfully'} );
296+ server.log.info('Server shut down successfully');
288297 } catch (err) {
289- server.log.error({message: 'Error during shutdown', error: err} );
298+ server.log.error(err, 'Error during shutdown');
290299 process.exit(1);
291300 }
292301}
293302
294303// Handle process termination
295304process.on('SIGTERM', async () => {
296- server.log.info({message: 'SIGTERM received'} );
305+ server.log.info('SIGTERM received');
297306 await close();
298307 process.exit(0);
299308});
300309
301310process.on('SIGINT', async () => {
302- server.log.info({message: 'SIGINT received'} );
311+ server.log.info('SIGINT received');
303312 await close();
304313 process.exit(0);
305314});
306315
307316// Handle uncaught exceptions
308317process.on('uncaughtException', (err) => {
309- server.log.error({message: 'Uncaught Exception', error: err} );
318+ server.log.error(err, 'Uncaught Exception');
310319 close().then(() => process.exit(1));
311320});
312321
313322// Handle unhandled promise rejections
314323process.on('unhandledRejection', (reason, promise) => {
315324 // non error rejections do not have a stack trace and hence cannot be located.
316- server.log.error({message: 'Unhandled Rejection at promise', error: reason instanceof Error ? reason : { reason }, promise});
325+ if(reason instanceof Error){
326+ server.log.error(reason, 'Unhandled Rejection at promise');
327+ } else {
328+ server.log.error('Unhandled Rejection at promise. reason:' + reason);
329+ }
317330 close().then(() => process.exit(1));
318331});
0 commit comments