node-bunyan
node-bunyan copied to clipboard
child logger with dynamic bound fields
I like the concept of child loggers with additional bound fields. However, they would be more useful for me if the fields were serialized "on the fly". My use case is something like this:
var log = ... // global logger, defined elsewhere
function Session(id, socket) { // create a session object for a new connection
this.id = id;
this.socket = socket;
this.log = log.child({session: this, serializers: {
session: function serialize(s) {
return s.id + (s.user ? '/' + s.user.id : '');
}
}});
}
Where the session's user
property is initialized at a later stage (after authentication).
Currently, the session field is serialized during initialization of the child logger, so it never changes after that, i.e. the user ID is never included. If I am reading bunyan correctly, this behavior is by design, but I think dynamically serializable bound fields would be useful.
I understand the desire for that kind of feature, but I can't change the current behaviour. (I was independently asked for something like this today, too.)
There is value in the current behaviour too: only serializing the object once at Logger creation time.
To support this we'd need a reasonable design that allowed both forms... or punt on this feature and require the app using bunyan to wrap log record writing to delay serializing "session" (in this case), or delay creating the log.child
until s.user
is set (in this case).
Thanks for the reply. I understand the reasoning behind the current behavior, in many cases it makes perfect sense.
At first glance, it would seem to be fairly straightforward to integrate this as an option, which is disabled (ie. the current behavior) by default, and can be enabled by supplying a dynBoundFields
property in the createLogger
options. It's quite possible I'm missing some pitfalls there though.
If you would consider including such a feature, I might have a go at it if I can find the time.
Being able to pass a function (executed on every log msg) whose object return value is merged into the logged JSON would be useful.
Being able to pass a function (executed on every log msg) whose object return value is merged into the logged JSON would be useful.
This is an old issue, but I still think this idea is useful. I think if the field is a function and has no serializer, then bunyan could call the function and save the value it returns on the record. This would probably be a breaking change, but you can do it yourself with a custom object stream.
Another case: I want to use Datadog's log and trace correlation feature.
The active trace and span IDs are maintained continuation-local-storage-type management.
I need to dynamically fetch these and add them to each log message.
No updates on this?
Any updates on this?
For anyone who wants to use something similar, you can take advantage of the get
accessor property.
const logger = bunyan.createLogger({ ...options })
Object.defineProperty(log.fields, 'traceId', {
enumable: true,
get: function () {
return 'some-id' // e.g., you can retrieve it from AsyncLocalStorage
}
})