-
Notifications
You must be signed in to change notification settings - Fork 116
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
Unable to log query
nor params
for request serializers
#155
Comments
Could you please provide a complete example to reproduce your problem? |
It turns out my problem was a misunderstanding of the API. The serializer functions always expect the value being logged as the first parameter. I was expecting the express request object as it is from a route handler, but instead I got a the “context object” ( Figuring this out took longer than it would have if there was stronger typing for the serializers for pino-http. I understand how the typing of serializer functions could be challenging due to their dynamic nature. So this leads me to an alternative API idea: what if the library just gave you the request, response and error objects in a callback, and then you decide everything that should be logged from that callback? |
how would that API look like? |
pinoMiddleware({
logger,
onResFinished: (req, res, err) => {
return { ... } // Return whatever you want from the req, res, or err objects.
}
}) The object returned from the |
This could be done by changing: function onResFinished (err) {
this.removeListener('error', onResFinished)
this.removeListener('finish', onResFinished)
var log = this.log
var responseTime = Date.now() - this[startTime]
var level = customLogLevel ? customLogLevel(this, err) : useLevel
if (err || this.err || this.statusCode >= 500) {
var error = err || this.err || new Error('failed with status code ' + this.statusCode)
log[level]({
[resKey]: this,
[errKey]: error,
[responseTimeKey]: responseTime
}, errorMessage(error, this))
return
}
log[level]({
[resKey]: this,
[responseTimeKey]: responseTime
}, successMessage(this))
} Into: function onResFinished (err) {
this.removeListener('error', onResFinished)
this.removeListener('finish', onResFinished)
var log = this.log
var responseTime = Date.now() - this[startTime]
var level = customLogLevel ? customLogLevel(this, err) : useLevel
var logOut = {
[resKey]: this,
[responseTimeKey]: responseTime,
}
if (err || this.err || this.statusCode >= 500) {
var error = err || this.err || new Error('failed with status code ' + this.statusCode)
logOut[errKey] = error
logOut.msg = errorMessage(error, this),
}
else {
logOut.msg = successMessage(this),
}
log[level]({
...logOut
...logHandler(req, res, err)
})
} Here we're going with the name |
I don't think we have |
loggerMiddleware has req. |
Indeed. The code is written so that we avoid allocating a new closure for each request. |
If memory footprint is a concern, then we could leak the abstraction: Pass a ctx object to the log |
That would still add something somewhere :/. I'm not sure what @jsumners thinks, but I'm kind of ok to how this module works now. |
@mcollina I see; so you want to avoid creating any closure whatsoever per request. I'm assuming this is because closures have significant performance implications. Regardless, use of a closure is only an implementation detail. You could get a bit more hacky and just add the |
Honestly, I've never actually used this module. And I haven't really followed the code in this thread. I get the impression there is a misunderstanding of what the module is and how it works, but, again, I haven't really been paying much attention here. |
@samholmes I think your view of what you would like to achieve with this module is quite different from the current scope of it. I have not used this in a while as well and I would prefer not to significantly change this. |
Fair enough. My only suggestion then is somehow addressing the slight lack of clarity for using the API through documentation. One thing that wasn’t clear at first was that pino-http logged a specific object that could then be changed either through serializer functions or some other handlers. Documenting what exactly this object is would be helpful. 🙂 |
This issue still persists as of April 2024. Indeed, when making a request using parameters, it resolves to a URL rather than to params. Even when using custom serializers, the information that reaches the serializer about the request is already resolved to a URL, even though in the request (for example in Express.js), it belongs to the params attribute. Log in Express.js:
Log in Pino:
|
@UderMoreiraDeAssis Seems like this is expected behavior. Express middleware doesn't inherently know the structure of route parameters across different routes unless you explicitly define it. If you register the pino-http logger middleware without explicitly providing any routes, @samholmes In your example code, you could try registering the middleware as: app.use('/*',
pinoMiddleware({
logger,
customLogLevel: res => {
return res.statusCode >= 500 ? 'warn' : 'info'
},
serializers: {
req: numbRequest,
res: numbResponse
}
})
) Of course, it's not perfect as you would have to duplicate the exact route param names to get the correct object. |
The
query
andparams
console.log
output is showing in the terminal, however the fields are not showing up in the final log output. The fieldfoo
is showing, so this means thatparams
andquery
are treated in a special way that is not documented.The text was updated successfully, but these errors were encountered: