-
Notifications
You must be signed in to change notification settings - Fork 838
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: add ability to filter grpc methods #1353
feat: add ability to filter grpc methods #1353
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1353 +/- ##
==========================================
- Coverage 93.90% 93.72% -0.18%
==========================================
Files 148 148
Lines 4396 4481 +85
Branches 895 929 +34
==========================================
+ Hits 4128 4200 +72
- Misses 268 281 +13
|
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.
Overall LGTM. Added few comments
export const methodIsIgnored = ( | ||
methodName: string, | ||
ignoredMethods?: string[] | ||
): boolean => { | ||
if (!ignoredMethods) { | ||
return false; | ||
} | ||
for (const pattern of ignoredMethods) { | ||
if (new RegExp(`^${pattern}$`, 'i').test(methodName)) { | ||
return true; | ||
} | ||
} | ||
return 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.
Could this be made like http plugin and support both partial regex and exact string matching?
opentelemetry-js/packages/opentelemetry-plugin-http/src/utils.ts
Lines 140 to 153 in 03981e4
export const satisfiesPattern = <T>( | |
constant: string, | |
pattern: IgnoreMatcher | |
): boolean => { | |
if (typeof pattern === 'string') { | |
return pattern === constant; | |
} else if (pattern instanceof RegExp) { | |
return pattern.test(constant); | |
} else if (typeof pattern === 'function') { | |
return pattern(constant); | |
} else { | |
throw new TypeError('Pattern is in unsupported datatype'); | |
} | |
}; |
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.
Yep! I'll just use the exact same approach as in the http plugin
/** | ||
* Metadata key used to denote an outgoing opentelemetry request. | ||
*/ | ||
const _otRequestHeader = 'x-opentelemetry-outgoing-request'; |
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.
nit: This seems to be getting defined in a lot of separate places. @open-telemetry/javascript-approvers Should it be moved to somewhere common like /core or /tracing or /semantic-conventions?
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.
Once I get consensus here I can make the change thats required
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 just keeping it here is fine for now, because a better solution in the form of #1344 is coming.
return false; | ||
} | ||
for (const pattern of ignoredMethods) { | ||
if (new RegExp(`^${pattern}$`, 'i').test(methodName)) { |
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.
Is there a benefit to newing up a regex here each time instead of doing a standard inequality check?
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's a case insensitive match which I believe it needs to be for grpc since the method names may be either lower or upper camel case. I could switch to using toLowerCase()
instead
Not sure whats up with the CI? The same commands run locally, and the thrown error doesn't look related to the changes in the last 2 commits |
looks like npm returned a 404. I'm able to download the tarball it missed. I'll restart the build and see if that helps. |
Looks like that solved the issue. Thanks! |
* Returns true if the server call should not be traced. | ||
*/ | ||
function shouldNotTraceServerCall( | ||
this: GrpcJsPlugin, |
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.
can you please change this
into grpcJsPlugin
, I find it a bit misleading later in code
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.
If I change this
to grpcJsPlugin then I cant access the _config
of the plugin because it is a protected field. Do you have any suggestions around this?
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.
then function shouldNotTraceServerCall
should not be a standalone function but a private of GrpcJsPlugin
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.
Because the function needs to be called in patchServer(grpcJsPlugin)
I cant actually make the function a private member of the class.
One alternative would be to remove the this
keyword from shouldNotTraceServerCall
and pass in the list of ignored gRPC methods in as parameter:
/**
* Returns true if the server call should not be traced.
*/
function shouldNotTraceServerCall(
metadata: grpcJs.Metadata,
methodName: string,
ignoreGrpcMethods?: IgnoreMatcher[]
): boolean {
const parsedName = methodName.split('/');
return (
containsOtelMetadata(metadata) ||
methodIsIgnored(
parsedName[parsedName.length - 1] || methodName,
ignoreGrpcMethods
)
);
}
That being said, the original implementation is consistent with the rest of the package
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.
When the first parameter is named this
in typescript it carries special meaning. It only carries typing info and is compiled away. Example Playground Link to illustrate.
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.
Please make this function a private member of the class.
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 maybe I still don't fully understand how to make this work. By moving the function over to class GrpcJsPlugin
I get a compile error:
src/grpcJs.ts:107:11 - error TS6133: 'shouldNotTraceServerCall' is declared but its value is never read.
107 private shouldNotTraceServerCall(
~~~~~~~~~~~~~~~~~~~~~~~~
src/server/patchServer.ts:75:24 - error TS2341: Property 'shouldNotTraceServerCall' is private and only accessible within class 'GrpcJsPlugin'.
75 if (plugin.shouldNotTraceServerCall(call.metadata, name)) {
~~~~~~~~~~~~~~~~~~~~~~~~
Found 2 errors.
Do I need to change anything else in patchServer
to make this 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.
Just checking in to see if there's any advice on this issue?
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.
Ah I see it is called from patchserver not from within the same class. You can make it a util function, but please do not use call
to call it. It would be much better if you could pass any required configs or properties as arguments to the function.
originalFunc: HandleCall<RequestType, ResponseType>, | ||
call: ServerCallWithMeta<RequestType, ResponseType>, | ||
callback: SendUnaryDataCallback<unknown> | ||
): 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.
Are you sure the return type of originalFunc
will always be 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.
According to the grpc-js types, HandleCall is always going to be a void function
export type IgnoreMatcher = string | RegExp | ((str: string) => boolean); | ||
|
||
export interface GrpcPluginOptions extends PluginConfig { | ||
/* Omits tracing on any RPC methods that match any of |
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.
/* Omits tracing on any RPC methods that match any of | |
/* Omits tracing on any GRPC methods that match any of |
/* Omits tracing on any RPC methods that match any of | ||
* the IgnoreMatchers in the ignoreRpcMethods list | ||
*/ | ||
ignoreRpcMethods?: IgnoreMatcher[]; |
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.
should this be called ignoreGrpcMethods
?
return false; | ||
} | ||
|
||
try { |
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.
please remove try catch, then function satisfiesPattern
should simply return false instead of throwing an error
* @param ignoredMethods a list of matching patterns | ||
* @param onException an error handler for matching exceptions | ||
*/ | ||
export const _methodIsIgnored = ( |
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 method should not throw anything, you can simply return boolean and make the same logic
@@ -72,6 +73,15 @@ export function patchServer( | |||
) { | |||
const self = this; | |||
|
|||
if (shouldNotTraceServerCall.call(plugin, call.metadata, name)) { |
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.
Use of call here is unnecessary and confusing. Making the function a private method of the class would be much better.
if (shouldNotTraceServerCall.call(plugin, call.metadata, name)) { | |
if (plugin.shouldNotTraceServerCall(call.metadata, name)) { |
* Returns true if the server call should not be traced. | ||
*/ | ||
function shouldNotTraceServerCall( | ||
this: GrpcJsPlugin, |
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.
Please make this function a private member of the class.
Signed-off-by: reggiemcdonald <[email protected]>
Signed-off-by: reggiemcdonald <[email protected]>
Signed-off-by: reggiemcdonald <[email protected]>
Signed-off-by: reggiemcdonald <[email protected]>
Signed-off-by: reggiemcdonald <[email protected]>
Signed-off-by: reggiemcdonald <[email protected]>
Signed-off-by: reggiemcdonald <[email protected]>
Signed-off-by: reggiemcdonald <[email protected]>
Signed-off-by: reggiemcdonald <[email protected]>
Signed-off-by: reggiemcdonald <[email protected]>
Signed-off-by: reggiemcdonald <[email protected]>
Signed-off-by: reggiemcdonald <[email protected]>
91d23df
to
d2c67ec
Compare
Are there any more changes needed for this PR? |
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.
Sorry this fell too far down my backlog and got a little lost. Looks good to me after the changes thanks
@obecny and @vmarchaud have your concerns been addressed? |
Which problem is this PR solving?
In brief, the current gRPC plugins have no ability to filter which methods are traced. This could lead to an infinite cycle if an exporter was to use gRPC. This PR addresses this problem.
Short description of the changes
The following changes were made for both
plugin-grpc
andplugin-grpc-js
:x-opentelemetry-outgoing-request
metadata are now filteredignoreMethods
plugin configTesting
@opentelemetry/plugin-grpc
on a live instance exported to GCP@opentelemetry/plugin-grpc-js
on a live instance exported to GCP