Skip to content
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

Use parent bindings formatter in child loggers #2129

Open
DamienGarrido opened this issue Feb 13, 2025 · 0 comments
Open

Use parent bindings formatter in child loggers #2129

DamienGarrido opened this issue Feb 13, 2025 · 0 comments

Comments

@DamienGarrido
Copy link

I have hundreds of possible log fields, and I'd like to make sure that my logs are formatted consistently between the different loggers in my applications.

For example, if a field is named method, I'd like its contents to always be in UPPERCASE.

For example, if called as follows:

logger.info({ msg: 'HTTP call', method: 'post' });

It should always be logged in this way:

{ "msg": "HTTP call", "method": "POST" }

Or so that another body field is always serialized in JSON, for example, if it is called as follows:

logger.info({ msg: 'HTTP body', body: { some: "value" } });

It should always be logged this way:

{ "msg": "HTTP body", "body": "{\"some\":\"value\"}" }

With this in mind, I thought I'd use a function for the bindings and log formatters that centralizes the modifications to be made to the objects passed as parameters.

For example, in the code below, the shapeObject function, which converts the values of the method, logger and partner fields to uppercase and serializes the value of the body field to JSON, is used as the formatter for log and bindings formatters:

const pino = require('pino')

function shapeObject(object) {
  if (typeof object.method === 'string') object.method = object.method.toUpperCase()
  if (typeof object.logger === 'string') object.logger = object.logger.toUpperCase()
  if (typeof object.partner === 'string') object.partner = object.partner.toUpperCase()
  if (object.body !== undefined) object.body = JSON.stringify(object.body)

  return object
}

const logger = pino({
  base: {},
  formatters: {
    level(label) { return { level: label } },
    log: shapeObject,
    bindings: shapeObject
  }
})

logger.setBindings({ logger: 'parent' })
logger.info({ msg: 'HTTP call', method: 'post', url: 'http://example.com/api', body: { key: 'value' } })

const childLogger = logger.child({ partner: 'Apple' })
childLogger.setBindings({ logger: 'child' })

childLogger.info({ msg: 'HTTP call', method: 'post', url: 'http://apple.com/api', body: { key: 'value' } })

const otherChildLogger = logger.child({ partner: 'Google' })
otherChildLogger.setBindings({ logger: 'otherChild' })

otherChildLogger.info({ msg: 'HTTP call', method: 'post', url: 'http://google.com/api', body: { key: 'value' } })

The above code gives me the following result:

{"level":"info","time":1739462112769,"logger":"PARENT","msg":"HTTP call","method":"POST","url":"http://example.com/api","body":"{\"key\":\"value\"}"}
{"level":"info","time":1739462112771,"logger":"PARENT","partner":"Apple","logger":"child","msg":"HTTP call","method":"POST","url":"http://apple.com/api","body":"{\"key\":\"value\"}"}
{"level":"info","time":1739462112771,"logger":"PARENT","partner":"Google","logger":"otherChild","msg":"HTTP call","method":"POST","url":"http://google.com/api","body":"{\"key\":\"value\"}"}

My problems are as follows:

  • Unlike the log formatter, the bindings formatting is not applied to child logs in the same way as to parent logs.
  • The bindings passed when calling child() (chindings) are not formatted.

How can I get the following result instead?

{"level":"info","time":1739462112769,"logger":"PARENT","msg":"HTTP call","method":"POST","url":"http://example.com/api","body":"{\"key\":\"value\"}"}
{"level":"info","time":1739462112771,"logger":"PARENT","partner":"APPLE","logger":"CHILD","msg":"HTTP call","method":"POST","url":"http://apple.com/api","body":"{\"key\":\"value\"}"}
{"level":"info","time":1739462112771,"logger":"PARENT","partner":"GOOGLE","logger":"OTHERCHILD","msg":"HTTP call","method":"POST","url":"http://google.com/api","body":"{\"key\":\"value\"}"}

I've opened Pull Request 1950 a few months ago to show an example of a modification that would allow me this behavior by adding an options object, which shouldn't add too much overhead.

But maybe there's another way to do it in a more clean/optimized way?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant