pinojs / pino

🌲 super fast, all natural json logger
http://getpino.io
MIT License
14.22k stars 874 forks source link

Access to child object in logMethod #897

Open kevinsimper opened 4 years ago

kevinsimper commented 4 years ago

I was looking to access the child object, I want to make so that it prepends the message object.

Here I log what inputArgs contains inside hooks.logMethod

after having called logger.child({"featureName":"MY FEATURE"}

{ inputArgs: [ 'special' ] }
{"level":30,"time":1597765635449,"featureName":"MY FEATURE","message":"special"}

I am trying to make a function that will prepend that name to message, so it becomes

{"level":30,"time":1597765635449,"featureName":"MY FEATURE","message":"MY FEATURE: special"}
jsumners commented 4 years ago

The hook has no way of obtaining that context:

https://github.com/pinojs/pino/blob/95856d1198a4067f9916a2b7e636b71f58bebeb2/lib/tools.js#L30-L35

mcollina commented 4 years ago

Is not this?

jsumners commented 4 years ago

Is not this?

Maybe? I think bindings are rendered to a string at child creation.

danielmahon commented 3 years ago

Is there anywhere to obtain the "parent" binding context? I have tried pretty much every hook/method and can't find a way to access the context before the new bindings are written. It would be nice to have some way to designate that child loggers are children of other loggers, for example to append the log name:

const log = logger.child({ name: 'app' });
const log2 = log.child({ name: `service` });
// via hook or formatter set log2's name to "app:service"

This would also allow easy filtering of logs in logMethod to mirror debug filtering:

function logMethod(this: any, inputArgs: any, method: pino.LogFn) {
  // Check child against debug variable
  const { name } = this.bindings();
  if (!debug.enabled(name)) return;
  return method.apply(this, inputArgs);
}

I initially assumed this could be done via formatters.bindings but it doesn't have access to the logger instance and (this might be a bug) it is only run during pino instance creation and NOT during subsequent child calls... which is how it is stated in the documentation

danielmahon commented 3 years ago

Best way I've found so far is to wrap the logger.child method:

const defaultChildMethod = logger.child;
logger.child = function child(newBindings) {
  const { name } = this.bindings();
  const newName = newBindings.name;
  if (name && newName) {
    newBindings.name = `${name}:${newName}`;
  }
  return defaultChildMethod.apply(this, [newBindings]);
};
mcollina commented 3 years ago

I think we should extend formatters.bindings so that it forward this to the current logger.

https://github.com/pinojs/pino/blob/185dc159166d8d31471a31532fede220d5a8d588/lib/tools.js#L157

Could you send a PR?