-
Notifications
You must be signed in to change notification settings - Fork 539
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
feat: pino instrumentation #432
Conversation
Codecov Report
@@ Coverage Diff @@
## main #432 +/- ##
=======================================
Coverage 95.83% 95.83%
=======================================
Files 15 15
Lines 624 624
Branches 94 94
=======================================
Hits 598 598
Misses 26 26 |
cc @mcollina @davidmarkclements if you'd like to take a look |
} | ||
|
||
if (semver.satisfies(version, pino5Versions)) { | ||
const proto = Object.getPrototypeOf(pinoModule()); |
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.
do the constructor have a side effect ? I mean we are creating a new instance here which can be problematic
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.
Afaik it does not, it's just a factory function: https://github.com/pinojs/pino/blob/v5.17.0/pino.js#L63 so no global state gets set.
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 think what would make more sense is to retrieve the lib/proto
file to patch it, WDYT ?
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.
The thing with this is that the file hook gets called first, but in order to patch the prototype I need the value of writeSym
. lib/proto
gets loaded before lib/symbols
, not sure if there is a non-hackish way to do it. Will give it some thought 🙂
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.
Indeed, i don't think its possible then. Might be worth checking though
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.
Changed it to mixins patching now, should be simpler.
I would like to ask why would you need to monkeypatch pino? Pino is inherently sync in how it logs, so there should not be no need to monkeypatch anything here. (streams are async, but those are separate). |
could this be turned off anyway? |
The end goal is to 💯% offload the logic of adding span context fields (when available) to the logs. The span context consists of
Yes, it will never be turned on unless the user has installed the |
I wonder if "Instrumentation" is a bad name for this, since it isn't actually instrumenting anything? Maybe we should use some other name like |
Also, pino supports "mixins" as a first party API. Maybe we should just release an official opentelemetry pino mixin that injects the span data. It would likely be a much more stable interface than patching internal methods. |
For now I'm retracting my approval until we are sure this is the direction we want to go. |
I don't get it, it's meant for automatic instrumentation and is completely optional. If you want to use a mixin and have separate configuration for this, fine. Besides, the spec even has a section for auto instrumentation about this exact same use case: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/overview.md#auto-instrumenting-existing-logging Other languages already have similar mechanisms, e.g. Java @naseemkullah is completely correct on this one.
On a side note, what does it being sync or async have to do with this PR? It's about achieving log correlation. |
To avoid monkey patching a pino API to register global mixins would be needed. |
i would prefer to keep them as instrumentation, someone could decide to add metrics for how much logs you are emitting etc. |
The feature we added for supporting this use case was the If mixin is enough, I would recommend either:
I do not have much time to work on this right now but happy to review. I'm ok with both approach with a slight preference to 1. |
I'm all for option 1, but with our current instrumentation API how can we achieve this? I am perhaps missing something here. Edit: Can return the wrapper inside |
You probably know this but I can confirm that mixin works great with the following option passed in to pino : mixin: () => (getSpan(context.active())?.context() ?? {}), |
Personally I'm in favor of option 2 as it requires no monkey patching of pino. Noone knows if we will be ever able to reliable monkey patch ESM modules therefore getting public APIs is future proof. But clearly this can't happen within this PR. |
Instrument (verb): equip (something) with measuring instruments. Since we are not measuring anything, we are not instrumenting the module.
If spec says this it's probably fine for now. I would also prefer to take advantage of public, supported APIs. As @Flarna says we will not be able to monkeypatch once ESM is widely supported. I generally support option 2, but since it relies on options which don't yet exist 1 is probably a better solution at the moment. |
I'm going to approve anyways as this can always be reworked later. |
Changing it to mixin patching, don't merge yet. This will bring the min version to 5.14, but should be fine |
Adding blocked label until you finish |
@dyladan Done. Added additional tests regarding options and mixins handling. Upped the required version to 5.14.0 and ran both 5.14.0 and 6.x through an example app. |
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.
Looks good
args.splice(0, 0, { | ||
mixin: instrumentation._getMixinFunction(), | ||
}); | ||
return pinoModule(...(args as Parameters<Pino>)); |
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.
This can be done in a single step I think
args.splice(0, 0, { | |
mixin: instrumentation._getMixinFunction(), | |
}); | |
return pinoModule(...(args as Parameters<Pino>)); | |
return pinoModule({ mixin: instrumentation._getMixinFunction() }, ...args); |
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.
Good point, although this won't compile due to pino taking 0-2 args and ...(args as Parameters<Pino>)
already expands to 2 args and it can't be untyped 😦
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.
We are under the case of args.length == 1
, so it can also be written as return pinoModule({ mixin: instrumentation._getMixinFunction() }, args[0] as pino.DestinationStream)
maybe?
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.
lgtm, thx for contribution, one comment
|
||
disable() { | ||
super.disable(); | ||
this._isEnabled = 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.
hmm we already have such functionality, can you add todo here to remove it once the base class will be changed. I created an issue for that -> open-telemetry/opentelemetry-js#2131
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.
Added a TODO, found it kinda awkward 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.
lgtm, really good work!
Which problem is this PR solving?
Adds automatic injection of trace context to pino (
5.x
and6.x
) similarly to bunyan and winston instrumentations.