Added options to HttpWebRequest instrumentation.#741
Added options to HttpWebRequest instrumentation.#741cijothomas merged 21 commits intoopen-telemetry:masterfrom
Conversation
| /// <param name="carrier">Object to extract context from. Instance of this object will be passed to the getter.</param> | ||
| /// <param name="getter">Function that will return string value of a key with the specified name.</param> | ||
| /// <returns><see langword="true" /> if the carrier has been injected with an activity context.</returns> | ||
| bool IsInjected<T>(T carrier, Func<T, string, IEnumerable<string>> getter); |
There was a problem hiding this comment.
can Fields collection be used here? I'm fine having this method, I suggest to describe use case in a form of an issue on specification repo explaining the need for this.
There was a problem hiding this comment.
@SergeyKanzhelev I don't think Fields will work alone to determine if a request is instrumented or not. The TraceContextFormatActivity for example has 2 Fields defined: traceparent and tracestate. A request is instrumented if it has traceparent, tracestate is optional. So not enough information in Fields for me to know which ones are required to make the determination.
There was a problem hiding this comment.
Also, spec issue open: open-telemetry/opentelemetry-specification#674
| var traceparentCollection = getter(carrier, TraceParent); | ||
|
|
||
| // There must be a single traceparent | ||
| return traceparentCollection != null && traceparentCollection.Count() == 1; |
There was a problem hiding this comment.
so IsInjected will return false if there are two of them?
There was a problem hiding this comment.
I mirrored what is done in the Extract logic 🤷♂️ Easy enough to change it to return true if at least one is found. Let me know if you want to change it just here, in both spots, leave as-it, or whatever.
| activity.AddTag(SpanAttributeConstants.HttpUrlKey, request.RequestUri.OriginalString); | ||
| activity.AddTag(SpanAttributeConstants.HttpFlavorKey, HttpTagHelper.GetFlavorTagValueFromProtocolVersion(request.ProtocolVersion)); | ||
|
|
||
| if (Options.SetHttpFlavor == true) |
There was a problem hiding this comment.
Do we need a generic callback here to collect additional attributes?
There was a problem hiding this comment.
Seems like it would be useful. After this PR I want to extend the options. I was thinking I would do an issue first with the proposed API so we can discuss, I'll add that on there?
Codecov Report
@@ Coverage Diff @@
## master #741 +/- ##
==========================================
- Coverage 68.95% 68.85% -0.10%
==========================================
Files 226 226
Lines 6825 6852 +27
Branches 1129 1144 +15
==========================================
+ Hits 4706 4718 +12
- Misses 1818 1829 +11
- Partials 301 305 +4
|
|
Added this as agenda to next SIG meeting to discuss: Since this is exposing a new public API, i'd like to get opinions from others as well. Had offline discussions with @CodeBlanch as well. |
|
@cijothomas Thanks! I have a conflict for the SIG on 7/14 so I added some notes/thoughts on the agenda below what you added on there. |
…ove ahead with the other stuff while the API is reviewed.
…Blanch/opentelemetry-dotnet into httpinstrumentation-options
|
Update... Had a chat with @cijothomas on Gitter. This PR changes the options API to expose filtering publically but it also does some other stuff. Like bringing .NET Framework Http client instrumentation into parity with .NET Core Http client, as far as the other options (TextFormat, HttpFlavor, etc.). I switched the filter back to internal. If we decide to move forward with that API, we can make it public in another PR. But the rest of the changes, would everyone please review? |
…ceparent header directly.
…Blanch/opentelemetry-dotnet into httpinstrumentation-options
|
@cijothomas Put the filter back to |
| return false; | ||
| } | ||
| // applicationinsights | ||
| if (originalString.StartsWith("https://dc.services.visualstudio") || |
There was a problem hiding this comment.
I think we can remove this. Its leftover from old exporter
There was a problem hiding this comment.
Is the old exporter used at all or is it end-of-life? The reason I ask is if we remove this, and anyone uses it through NuGet or the contrib repo or wherever, we still need this to prevent an infinite export loop. We can only remove once we have a solve for the "terminal span" thing. I think? We could ask users to manually filter via the public API if they use the azure exporter?
| request.RequestUri != null && | ||
| request.Method == HttpMethod.Post) | ||
| Uri requestUri; | ||
| if (requestMessage.Method == HttpMethod.Post && (requestUri = requestMessage.RequestUri) != null) |
There was a problem hiding this comment.
do we have to filter only Post requests?
There was a problem hiding this comment.
That is only for the internal filter, which happens to be all POSTs. The user filter will fire for all methods.
There was a problem hiding this comment.
There were GET requests made by application insights exporter as well. (though only once at startup).
Now that we expose public api to filter, do we still need to have zipkin specific one?
There was a problem hiding this comment.
-
Interesting, didn't know about the Azure GETs. The "POST" rule has been part of the filter since I have been working on it, so I'm not sure why it was originally put in. You want me to open up to all methods? Are the GET URLs the same as the POST ones?
-
I think we still need the zipkin automatic filter unless you are thinking we can direct users to manually add that filter via the public API if they decide to use the ZipkinExporter?
The ZipkinExporter in-theory could use the same public API. But it would have to somehow find the instance of the options, which is in the Dependencies assembly it doesn't have a reference to. Then it would have to co-op the user's filter, if they added one. It could get messy. Prefer leaving as-is and solving in a generic way. The whole "terminal span" thing.
There was a problem hiding this comment.
Yes agree to leave this for now.
| public HttpClientInstrumentation(ActivitySourceAdapter activitySource, HttpClientInstrumentationOptions options) | ||
| { | ||
| this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpHandlerDiagnosticListener(options, activitySource), options.EventFilter); | ||
| this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpHandlerDiagnosticListener(options, activitySource), (activitySource, arg1, arg2) => options?.EventFilter(activitySource, arg1) ?? true); |
There was a problem hiding this comment.
I just double-checked, no can't be null. All the instrumentation classes are internal, only way to create them is through the builder which news up the options instance.
…Blanch/opentelemetry-dotnet into httpinstrumentation-options

I have OT deployed in a couple of test environments. Users are complaining there are a bunch of spans showing up that shouldn't be. I tracked this down to a product the IT department deploys. It is instrumenting the code at runtime and calling its local service over Http to spit out data. There is no way currently in OT to easily filter out requests like these. There is a TODO in HttpClientInstrumentationOptions noting the desire to expose a filtering API.
Changes
HttpClientInstrumentationOptionsto something more user friendly.Checklist