-
Notifications
You must be signed in to change notification settings - Fork 721
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
gRPC client instrumentation #687
gRPC client instrumentation #687
Conversation
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.
Hi @alanwest - just an initial quick pass, it will be interesting to put this together with some gRPC client and tests (I assume this comes when it is not draft anymore).
src/OpenTelemetry.Adapter.Dependencies/Implementation/GrpcClientDiagnosticListener.cs
Outdated
Show resolved
Hide resolved
var rx = new Regex(@"(?<package>\w+).(?<service>\w+)/(?<method>\w+)", RegexOptions.Compiled); | ||
var rpcService = rx.Match(path).Groups["service"].Value; | ||
|
||
span.SetAttribute("rpc.service", rpcService); |
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.
Nice!
@cijothomas we probably should create a package with the OTel semantic tags.
src/OpenTelemetry.Adapter.Dependencies/Implementation/GrpcClientDiagnosticListener.cs
Outdated
Show resolved
Hide resolved
BTW @alanwest you will need to sign the CLA :) |
Done.
Yes, I will plan to include something. I've been testing locally with some of the example applications from the grpc-dotnet repository. There's an example setup to work with Open Telemetry: https://github.com/grpc/grpc-dotnet/tree/master/examples#aggregator. |
span.SetAttribute("net.peer.port", request.RequestUri.Port); | ||
} | ||
|
||
// Do we want to propagate trace context here? GrpcClient is built on top of HttpClient. |
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'd like to understand this better. Do we end up with 2 spans, one from httpclient, and another from grpcclient, both essentially representing the same thing?
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.
Correct, two spans are generated. First the one from the grpcclient and then one from httpclient as a child.
I think it makes sense to only produce the span from the grpcclient. HttpClient instrumentation checks for the traceparent header which seems to suggest this kind of scenario was anticipated? Though traceparent
assumes W3C format, so it seems like there needs to be a more general check here if we want to prevent both spans from being generated.
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 actual order of events would be like Grpc.Start, HttpClient.Start, HttpClient.Stop, Grpc.Stop right? The httpclient span would be the child of grpc one.
This is essentially same as a user making a httpclient call inside a using(span=startactivespan()) block, which result in 2 span, 1 from customer created, and other from httpclient. In this case, we'd want to see both spans. customer span as parent, httpclient span as child.
Applying this principle to Grpc->HttpClient, it looks okay to see both spans. But if both are essentially same information then its redundant. Maybe let user decide if they want to suppress the child.?
Instead of looking at traceparent presence, we can check the activity.Parent inside httpclient, which would be that of Grpc.
(Just my initial thoughts, we need to discuss this 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.
The actual order of events would be like Grpc.Start, HttpClient.Start, HttpClient.Stop, Grpc.Stop right? The httpclient span would be the child of grpc one.
Correct.
My initial impression was that the information was redundant, though I can understand why it may be desirable to show both since it is an accurate representation of what's really happening.
I've seen similar cases from some database drivers that use HttpClient or HttpWebRequest behind the scenes. I've found it intuitive to show only a span for the database operation but not the underlying http request.
I'll share some screenshots of some traces in the gitter channel tomorrow, so we can discuss further.
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.
Okay.
Adding @shirhatti to this discussion :)
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.
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 agree and I think having both HTTP and gRPC spans is a little untidy, however I do think it's important to indicate the gPRC call was made over HTTP (it is theoretically possible to use other transports than HTTP).
It may also help identify an issue with the HTTP client when trying to help diagnose an issue by highlighting extra latency / errors.
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 is theoretically possible to use other transports than HTTP
Ah yes, interesting. I had not thought about this use case. Agreed it would be useful to note that the call was over HTTP in this case. As far as I know, the library currently only supports HTTP/2 at the moment (perhaps I'm wrong about 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.
@cijothomas and I spoke briefly regarding this issue. His thoughts:
my take would be this - lets not make any assumptions about what user wants - make it configurable to user. let user decide if they want to see grpc only or httpclient only or both. we can discuss the default behavior later.
I think this stance makes sense for now. My thought for this PR is to move forward without any attempt to suppress the spans generated from the HttpClient instrumentation. Then perhaps follow up as a separate effort with the idea of making this configurable and deciding on defaults.
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 agree and think we should show everything as you are now. If we need to tighten up later, we can, maybe though configuration.
8d0f366
to
0f45daa
Compare
src/OpenTelemetry.Instrumentation.Dependencies/Implementation/GrpcClientDiagnosticListener.cs
Outdated
Show resolved
Hide resolved
src/OpenTelemetry.Instrumentation.Dependencies/Implementation/GrpcClientDiagnosticListener.cs
Outdated
Show resolved
Hide resolved
I signed it |
src/OpenTelemetry.Instrumentation.Dependencies/Implementation/GrpcClientDiagnosticListener.cs
Outdated
Show resolved
Hide resolved
@alanwest, do you need any help on this PR? My team is moving a ton of high-use protocols to GRPC, so this is very interesting to me :) |
…ying HttpClient instrumentation
test/OpenTelemetry.Instrumentation.GrpcClient.Tests/GrpcClientTests.cs
Outdated
Show resolved
Hide resolved
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> | ||
|
||
<PackageReference Include="Google.Protobuf" Version="3.12.3" /> | ||
<PackageReference Include="Grpc.AspNetCore" Version="2.25.0" /> |
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 you should update to 2.30.0. It resolves race conditions between the response task being completed and the listener being written to.
Otherwise looks good to go.
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 did the trick. I updated to 2.30.0-pre1 since it appears that 2.30.0 has not been published for all the dependencies yet. I can come back and update this again when they have been published.
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.
Uh oh. Hehe, seems we're back to the same build error I was experiencing a few days back. You mentioned there may be other ways to resolve 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.
I think, we can ignore the Azure pipeline. i think we will just use Github Actions for now...
@cijothomas , what do you think?
...metry.Instrumentation.GrpcClient.Tests/OpenTelemetry.Instrumentation.GrpcClient.Tests.csproj
Outdated
Show resolved
Hide resolved
…nwest/opentelemetry-dotnet into alanwest/grpc-dotnet-instrumentation
🍰 🎉 🎈 |
This PR partially addresses issue #482 adding client-side instrumentation for grpc-dotnet.