-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
feat: implement conditional request logging #5732
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| ignoreTrailingSlash: { type: 'boolean', default: defaultInitOptions.ignoreTrailingSlash }, | ||
| ignoreDuplicateSlashes: { type: 'boolean', default: defaultInitOptions.ignoreDuplicateSlashes }, | ||
| disableRequestLogging: { | ||
| type: 'boolean', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there seem to be no existing precedents of defining a config value as a function, neither for adding a custom validation keyword, so I went for relaxing the validation altogether.
If a different approach is preferred, I would appreciate being pointed in the right direction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, there is a precedent - genReqId, and we do not validate it, so current solution is actually consistent with existing implementation. If we choose to add validation, I'd suggest doing it in a separate PR, and cover both cases.
| var valid0 = _errs47 === errors; | ||
| if(valid0){ | ||
| let data15 = data.onProtoPoisoning; | ||
| let data15 = data.onConstructorPoisoning; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why there are so many changes in this generated files after regeneration, I assume it was last generated with a different generator version
|
|
||
| globalExposeHeadRoutes = options.exposeHeadRoutes | ||
| disableRequestLogging = options.disableRequestLogging | ||
| if (typeof disableRequestLogging === 'function') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check is placed here so that we don't need to repeat it on every request, which is a hot path
| const request = new context.Request(id, params, req, query, childLogger, context) | ||
| const reply = new context.Reply(res, request, childLogger) | ||
| if (disableRequestLogging === false) { | ||
| if (resolvedDisableRequestLogging === false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not apply same logic for cases like 404, since I assume that error cases should generally be logged, but if consistent behaviour is expected across all of cases, I'm happy to apply this logic everywhere where we log requests
Eomm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not?
const Fastify = require('./')
const fastify = Fastify({ logger: true })
fastify.get('/', {
handler: () => { return 'foo' },
logLevel: 'silent',
})
fastify.inject('/')|
@Eomm That is an option in some cases, but it has very limited granularity, and sometimes you may not even have necessary level of control, e. g. if route is registered by a third-party plugin that you are using. Also you may want to log some domain business logic, but not the "incoming request". |
metcoder95
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it can be useful to apply custom logic to decide wether or not trigger logs accordingly to specific filters; but I'm wondering if this does not overlaps with route-level (e.g. the ones that @Eomm pointed out).
Also think that maybe this should be allowed to be set on a request basis, in case implementers want to fully disable logging for a registered route or apply custom logic to only that route.
lib/route.js
Outdated
| } | ||
| const childLogger = createChildLogger(context, logger, req, id, loggerOpts) | ||
| childLogger[kDisableRequestLogging] = disableRequestLogging | ||
| const resolvedDisableRequestLogging = disableRequestLoggingFn ? disableRequestLoggingFn(context, req) : disableRequestLogging |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% convinced that we should be passing the context object. I believe that calling the function (if passed) with the constructed Fastify Request object should be enough to have access the APIs from Fastify (they can access the server instance from there as well).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, context should never be passed to users directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for the delay, will do the change this week
…onditional-request-logging
|
@metcoder95 @climba03003 I've adjusted the code. Are we good with the approach now, can I proceed with TS types and documentation? |
| const resolvedDisableRequestLogging = disableRequestLoggingFn ? disableRequestLoggingFn(req) : disableRequestLogging | ||
| childLogger[kDisableRequestLogging] = resolvedDisableRequestLogging |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we better evaluate this once after the FastifyRequest has been constructed?
If done in this way, the caller has all the decorations and potential customization available to implement a robust logic. Otherwise it relies on the IncomingMessage object.
It should be safe to instantiate before evaluating, as we just depend on the child logger but not on the kDisableRequestLogging value at that specific moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you for the idea, I'll try it out!
This is a preliminary PR to gather feedback on the approach and the overall idea. If this is accepted and after implementation is polished, I will also add TS types and documentation in the same PR.
Use-case for this is following: some endpoints generate excessive amount of irrelevant noise (e. g. healthcheck) and are not useful in logs, so it would be great to be able to be able to resolve variable for logging their requests or not conditionally.
Checklist
npm run testandnpm run benchmarkand the Code of conduct