-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Propagators Support #54465
Propagators Support #54465
Conversation
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti Issue Details
|
Tagging subscribers to this area: @tarekgh Issue Details
|
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 a few questions/suggestions around the API shape, thanks!
...aries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs
Outdated
Show resolved
Hide resolved
...aries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs
Outdated
Show resolved
Hide resolved
public abstract bool Inject(System.Diagnostics.Activity activity, object carrier, Action<object, string, string> setter); | ||
public abstract bool Inject(System.Diagnostics.ActivityContext context, object carrier, Action<object, string, string> setter); | ||
public abstract bool Inject(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string?>> baggage, object carrier, Action<object, string, string> setter); | ||
public abstract bool Extract(object carrier, string fieldName, PropagatorGetterCallback getter, out string? value); | ||
public abstract bool Extract(object carrier, PropagatorGetterCallback getter, out System.Diagnostics.ActivityContext context); | ||
public abstract bool Extract(object carrier, PropagatorGetterCallback getter, out System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string?>>? baggage); |
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.
Overriding 6 methods seems like a lot if a simple use case might be
public sealed class SkipOneActivityLayerPropagator : TextMapPropagator
{
public override bool Inject(Activity activity, object carrier, Action<object, string, string> setter) =>
TextMapPropagator.CreateW3CPropagator().Inject(activity.Parent, carrier, setter);
}
Maybe this isn't a problem if it won't be common for users to implement these?
As a side note, such a propagator is how one could solve #41072.
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 am not sure if we need to force the default implementation here as whoever subclass TextMapPropagator should be aware about this implementation to decide if need to override it or not.
public abstract bool Inject(System.Diagnostics.Activity activity, object carrier, Action<object, string, string> setter); | ||
public abstract bool Inject(System.Diagnostics.ActivityContext context, object carrier, Action<object, string, string> setter); | ||
public abstract bool Inject(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string?>> baggage, object carrier, Action<object, string, string> setter); | ||
public abstract bool Extract(object carrier, string fieldName, PropagatorGetterCallback getter, out string? value); |
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 would this overload be used?
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 is needed for asp.net when reading hierarchical ids with the header name Request-Id
. The other Extract overloads will not be able to read such Id.
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. I assume it's not needed for the inject since it can be represented by the Activity?
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.
That is right. I am trying to discourage the usage of the hierarchical ids so I wouldn't expose Inject overload for that. I expose the overload that takes Activity object only to support the usage in http client so you don't need to carry any logic there and can just use the propagator as a black box.
public static TextMapPropagator DefaultPropagator { get; set; } | ||
public static TextMapPropagator CreateLegacyPropagator() { throw null; } | ||
public static TextMapPropagator CreatePassThroughPropagator() { throw null; } | ||
public static TextMapPropagator CreateOutputSuppressionPropagator() { throw null; } | ||
public static TextMapPropagator CreateW3CPropagator() { throw null; } |
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.
As an implementation detail, these should be caching a single instance IMO (each is allocating a HashSet internally so it's not just an empty object)
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, this is implementation details. We can cache the instances we return if needed. I didn't bother in the protype to go to that level.
public static TextMapPropagator CreateLegacyPropagator() => new LegacyTextMapPropagator(); | ||
|
||
// Suppress context propagation. | ||
public static TextMapPropagator CreateOutputSuppressionPropagator() => new OutputSuppressionPropagator(); |
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 was chatting a bit with @shirhatti about locking down what kind of customization is in scope and what isn't. For example this propagator has legacy behavior for ingress and no egress. If someone wanted to only support TraceParent on ingress + no egress presumably they would need to write their own propagator. Likewise if someone wanted to egress TraceParent but not baggage they would also need their own propagator. I am fine with those customizations being out of scope, I just want to make sure everyone is in agreement and it aligns with what we've heard from customers.
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 there will be some scenarios users may need to write their own customized propagators. I would like to see first what these scenarios would be. If such scenarios truly little tweaks from what we are exposing, we still have the option to introduce more overloads to the static methods which can easily achieve such scenarios. something like CreateOutputSuppressionPropagator(bool forceW3C)
.
public static TextMapPropagator CreateOutputSuppressionPropagator() => new OutputSuppressionPropagator(); | ||
|
||
// propagate only root parent context and ignore any intermediate created context. | ||
public static TextMapPropagator CreatePassThroughPropagator() => new PassThroughPropagator(); |
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.
Similar to the above, this PassThroughPropagator is implemented to always emit baggage using the Correlation-Context header (even if it was received via the W3C baggage header). If someone wanted a different behavior such as always emitting with the W3C baggage header or using different baggage headers in different circumstances they would need to author their own propagator. No objection from me, but I want to highlight which customizations are supported and which aren't to make sure everyone is in agreement.
public abstract bool Extract(object carrier, PropagatorGetterCallback getter, out string? id, out string? state); | ||
public abstract bool Extract(object carrier, PropagatorGetterCallback getter, out ActivityContext context); | ||
public abstract bool Extract(object carrier, PropagatorGetterCallback getter, out IEnumerable<KeyValuePair<string, string?>>? baggage); | ||
|
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'm trying to avoid digging into the details of the API as long as it appears to satisfy the goals we wanted to achieve. I think this API can achieve it, but I have more faith in the practical demonstration than in my mental model : )
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 already trying the prototype with http client and asp.net to ensure no gaps or issues with that design.
Closing the as we already have official PR #55419. |
No description provided.