diff --git a/docs/Reference/Server.md b/docs/Reference/Server.md index 2be8393d7d..1283f41d8c 100644 --- a/docs/Reference/Server.md +++ b/docs/Reference/Server.md @@ -385,9 +385,15 @@ been sent. By setting this option to `true`, these log messages will be disabled. This allows for more flexible request start and end logging by attaching custom `onRequest` and `onResponse` hooks. -Please note that this option will also disable an error log written by the -default `onResponse` hook on reply callback errors. Other log messages -emitted by Fastify will stay enabled, like deprecation warnings and messages +The other log entries that will be disabled are: +- an error log written by the default `onResponse` hook on reply callback errors +- the error and info logs written by the `defaultErrorHandler` +on error management +- the info log written by the `fourOhFour` handler when a +non existent route is requested + +Other log messages emitted by Fastify will stay enabled, +like deprecation warnings and messages emitted when requests are received while the server is closing. ```js diff --git a/lib/error-handler.js b/lib/error-handler.js index 53f52631bb..0b9dbdbb99 100644 --- a/lib/error-handler.js +++ b/lib/error-handler.js @@ -7,7 +7,8 @@ const { kReplyNextErrorHandler, kReplyIsRunningOnErrorHook, kReplyHasStatusCode, - kRouteContext + kRouteContext, + kDisableRequestLogging } = require('./symbols.js') const { @@ -35,10 +36,12 @@ function handleError (reply, error, cb) { try { reply.raw.writeHead(reply.raw.statusCode, reply[kReplyHeaders]) } catch (error) { - reply.log.warn( - { req: reply.request, res: reply, err: error }, - error && error.message - ) + if (!reply.log[kDisableRequestLogging]) { + reply.log.warn( + { req: reply.request, res: reply, err: error }, + error && error.message + ) + } reply.raw.writeHead(reply.raw.statusCode) } reply.raw.end(payload) @@ -79,15 +82,19 @@ function defaultErrorHandler (error, request, reply) { reply.code(statusCode >= 400 ? statusCode : 500) } if (reply.statusCode < 500) { - reply.log.info( - { res: reply, err: error }, - error && error.message - ) + if (!reply.log[kDisableRequestLogging]) { + reply.log.info( + { res: reply, err: error }, + error && error.message + ) + } } else { - reply.log.error( - { req: request, res: reply, err: error }, - error && error.message - ) + if (!reply.log[kDisableRequestLogging]) { + reply.log.error( + { req: request, res: reply, err: error }, + error && error.message + ) + } } reply.send(error) } @@ -112,8 +119,10 @@ function fallbackErrorHandler (error, reply, cb) { statusCode: { value: statusCode } })) } catch (err) { - // error is always FST_ERR_SCH_SERIALIZATION_BUILD because this is called from route/compileSchemasForSerialization - reply.log.error({ err, statusCode: res.statusCode }, 'The serializer for the given status code failed') + if (!reply.log[kDisableRequestLogging]) { + // error is always FST_ERR_SCH_SERIALIZATION_BUILD because this is called from route/compileSchemasForSerialization + reply.log.error({ err, statusCode: res.statusCode }, 'The serializer for the given status code failed') + } reply.code(500) payload = serializeError(new FST_ERR_FAILED_ERROR_SERIALIZATION(err.message, error.message)) } diff --git a/lib/fourOhFour.js b/lib/fourOhFour.js index da12232ec1..de0575475b 100644 --- a/lib/fourOhFour.js +++ b/lib/fourOhFour.js @@ -29,7 +29,7 @@ const { getGenReqId } = require('./reqIdGenFactory.js') * kFourOhFourContext: the context in the reply object where the handler will be executed */ function fourOhFour (options) { - const { logger } = options + const { logger, disableRequestLogging } = options // 404 router, used for handling encapsulated 404 handlers const router = FindMyWay({ onBadUrl: createOnBadUrl(), defaultRoute: fourOhFourFallBack }) @@ -49,7 +49,9 @@ function fourOhFour (options) { function basic404 (request, reply) { const { url, method } = request.raw const message = `Route ${method}:${url} not found` - request.log.info(message) + if (!disableRequestLogging) { + request.log.info(message) + } reply.code(404).send({ message, error: 'Not Found', diff --git a/test/logger/logging.test.js b/test/logger/logging.test.js index da4945ed9b..517b514468 100644 --- a/test/logger/logging.test.js +++ b/test/logger/logging.test.js @@ -17,7 +17,7 @@ t.test('logging', (t) => { let localhost let localhostForURL - t.plan(12) + t.plan(13) t.before(async function () { [localhost, localhostForURL] = await helper.getLoopbackHost() @@ -253,7 +253,7 @@ t.test('logging', (t) => { }) t.test('should not log incoming request and outgoing response when disabled', async (t) => { - t.plan(3) + t.plan(1) const stream = split(JSON.parse) const fastify = Fastify({ disableRequestLogging: true, logger: { level: 'info', stream } }) t.teardown(fastify.close.bind(fastify)) @@ -266,18 +266,12 @@ t.test('logging', (t) => { await fastify.inject({ method: 'GET', url: '/500' }) - { - const [line] = await once(stream, 'data') - t.ok(line.reqId, 'reqId is defined') - t.equal(line.msg, '500 error', 'message is set') - } - // no more readable data t.equal(stream.readableLength, 0) }) - t.test('should not log incoming request and outgoing response for 404 onBadUrl when disabled', async (t) => { - t.plan(3) + t.test('should not log incoming request, outgoing response and route not found for 404 onBadUrl when disabled', async (t) => { + t.plan(1) const stream = split(JSON.parse) const fastify = Fastify({ disableRequestLogging: true, logger: { level: 'info', stream } }) t.teardown(fastify.close.bind(fastify)) @@ -286,12 +280,6 @@ t.test('logging', (t) => { await fastify.inject({ method: 'GET', url: '/%c0' }) - { - const [line] = await once(stream, 'data') - t.ok(line.reqId, 'reqId is defined') - t.equal(line.msg, 'Route GET:/%c0 not found', 'message is set') - } - // no more readable data t.equal(stream.readableLength, 0) }) @@ -403,4 +391,37 @@ t.test('logging', (t) => { if (lines.length === 0) break } }) + + t.test('should not log the error if request logging is disabled', async (t) => { + t.plan(4) + + const stream = split(JSON.parse) + const fastify = Fastify({ + logger: { + stream, + level: 'info' + }, + disableRequestLogging: true + }) + t.teardown(fastify.close.bind(fastify)) + + fastify.get('/error', function (req, reply) { + t.ok(req.log) + reply.send(new Error('a generic error')) + }) + + await fastify.ready() + await fastify.listen({ port: 0, host: localhost }) + + await request(`http://${localhostForURL}:` + fastify.server.address().port + '/error') + + { + const [line] = await once(stream, 'data') + t.type(line.msg, 'string') + t.ok(line.msg.startsWith('Server listening at'), 'message is set') + } + + // no more readable data + t.equal(stream.readableLength, 0) + }) })