-
Notifications
You must be signed in to change notification settings - Fork 516
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: postgresql responseHook support #528
Conversation
Codecov Report
@@ Coverage Diff @@
## main #528 +/- ##
========================================
Coverage 94.92% 94.93%
========================================
Files 162 159 -3
Lines 9991 9828 -163
Branches 992 932 -60
========================================
- Hits 9484 9330 -154
+ Misses 507 498 -9
|
Hey @obecny, fixed the commits issue (had to create a new PR), tnx! |
@@ -199,6 +200,7 @@ export class PgInstrumentation extends InstrumentationBase { | |||
.then((result: unknown) => { | |||
// Return a pass-along promise which ends the span and then goes to user's orig resolvers | |||
return new Promise(resolve => { |
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 understand that nested new Promise
was here before but it really is not needed.
You can just do the sync calls inside the then callback function and it behaves exactly the same.
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.
thanks @rauno56, I agree and also noticed it when writing this PR. However, and if that is alright with you, I'd prefer to leave this change to a different PR?
Generally looks good! Thanks for the effort you've put into it and sorry for the late review! |
plugins/node/opentelemetry-instrumentation-pg/src/instrumentation.ts
Outdated
Show resolved
Hide resolved
plugins/node/opentelemetry-instrumentation-pg/src/instrumentation.ts
Outdated
Show resolved
Hide resolved
import { InstrumentationConfig } from '@opentelemetry/instrumentation'; | ||
|
||
export interface PgInstrumentationExecutionResponseHook { | ||
(span: api.Span, data: pgTypes.QueryResult | pgTypes.QueryArrayResult): void; |
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.
Instead of sending data
as the second parameter, it might be better to send an responseInfo
with the data on it.
That way, when someone wants to add new parameters in the future, the function signature will not grow more and more.
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 Idea! will change.
}, | ||
err => { | ||
if (err) { | ||
diag.error('Error running response hook', err); |
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.
optional: I like to add a prefix to my logs so if it prints, there is context on where it's coming from. Something like: pg instrumentation: ${...}
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.
Great idea, I’d suggest implementing this (in a separate PR, of course) at the InstrumentationBase level so that it won't be necessary to manually add the prefix separately for each instrumentation class. 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.
I think it's a great idea :)
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 now read the v0.21.0 release notes and looks like it was added there:
open-telemetry/opentelemetry-js#2261
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.
It was indeed added on instrumentation but you should use this._diag
from the instrumentation class to be able to use it. I think you'll need to give the instance class here to make it work
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.
@vmarchaud, @blumamir for this PR I recommend not adding this change.
_diag
is a protected member, it's accessible only internally within the class or any class that extends it but not externally. Since the pg instrumentation uses the utils
module, passing the instrumentation will not be enough and a refactor is needed here.
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.
Yes, I agree. We tried to refactor our instrumentations as well and bumped into the same issue, and decided not to use this component logger after all.
However, we made sure all the log prints are prefixed with ${packageName} instrumentation:
, for example.
But I see there is no convention for the contrib instrumentations on that, so it's up to you.
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.
why not passing the component logger to the util class directly from class when you call the util method ? @blumamir @nata7che in worst scenario I would change the signature to be public from protected instead of trying to mimic the behaviour of component diag logger. But it should be possible to simply pass the logger from class to util
pgResult: pgTypes.QueryResult | pgTypes.QueryArrayResult | unknown | ||
) { | ||
if ( | ||
config.enhancedDatabaseReporting && |
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.
why do you require truthy enhancedDatabaseReporting
for calling responseHook?
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.
will be removed also in accordance to @rauno56's comment above
0 | ||
); | ||
runCallbackTest(span, pgAttributes, events, unsetStatus, 2, 1); | ||
assert.ok(result, 'pool.query() returns a promise'); |
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.
result
here was already awaited, right? so it's not a promise, it's the actual response for the invocation. Not sure what this assertion is meant to test... (but I don't mind if it stays here as well).
@@ -176,7 +212,10 @@ export function patchCallback( | |||
code: SpanStatusCode.ERROR, | |||
message: err.message, | |||
}); | |||
} else { | |||
handleExecutionResult(instrumentationConfig, span, res); |
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.
Shouldn't we also call the response hook in the patchCallbackPGPool
function below?
Probably not, as I see there are tests for that, but how come it works?
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 PgPool instrumentation added an additional patching to the pgPool.connect
method, and uses the same query
patching.
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 have to admit I'm not very familiar with this instrumentation and its behavior.
So in what cases is "patchCallbackPGPool" being called?
hey @rauno56! I'd love to get your approval if you don't have any further comments 🙏🏻 |
plugins/node/opentelemetry-instrumentation-pg/src/instrumentation.ts
Outdated
Show resolved
Hide resolved
span: Span, | ||
pgResult: pgTypes.QueryResult | pgTypes.QueryArrayResult | unknown | ||
) { | ||
if (config.responseHook !== undefined && pgResult !== undefined) { |
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.
Same comment from the other "add responseHook", why explicitly only checking against undefined? Why not if (config.responseHook && pg...)
Or event better if (typeof config.responseHook === "function" && pg...)
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 we should just have if (typeof config.responseHook === "function")
if user adds hook we should always run it whether the pgResult
is undefined or not as this is also some kind of information for someone. Preventing running this hook in such case will confuse user why the hook didn't run soo I would definitely remove it.
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.
@obecny pushed 👍🏻 good idea!
@obecny @MSNev @vmarchaud thanks for your approval 💪🏻 are we good to go ahead and merge? |
Which problem is this PR solving?
Short description of the changes
enhancedDatabaseReporting
flag, safely use it to collect the data from the execution result