-
Notifications
You must be signed in to change notification settings - Fork 774
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
[api] Add Baggage.Attach API #5218
[api] Add Baggage.Attach API #5218
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #5218 +/- ##
==========================================
- Coverage 83.38% 83.20% -0.19%
==========================================
Files 297 271 -26
Lines 12531 11983 -548
==========================================
- Hits 10449 9970 -479
+ Misses 2082 2013 -69
Flags with carried forward coverage won't be shown. Click here to find out more.
|
RE: #5208 (comment) @alanwest's proposed API is this: void Main() {
using (var scope1 = ContextBuilder.NewContext().WithBaggage("key1", "key1").StartScope()) {
// Baggage.Current contains key1/value1
using (var scope2 = ContextBuilder.NewContext().WithBaggage({"key2", "value2"}).StartScope()) {
// Baggage.Current only contains key2/value2 here.
// If you also wanted key1/value1 in baggage here, then it would need to be explicit.
// Something like:
// var scope2 = ContextBuilder.FromContext(scope1).WithBaggage({"key2", "value2"})
// The context of scope2 would be derived from scope1 and key2/value2 would be additive
}
// scope2 has been disposed and scope1 has been restored, and
// Baggage.Current contains key1/value1
}
} The API being proposed here is similar: void Main() {
using (Baggage.Attach(Baggage.Create().SetBaggage("key1", "key1")) {
// Baggage.Current contains key1/value1
using (Baggage.Attach(Baggage.Create().SetBaggage("key2", "key2")) {
// Baggage.Current only contains key2/value2 here.
// If you also wanted key1/value1 in baggage here, then it would need to be explicit.
// Something like:
// var scope2 = ContextBuilder.FromContext(scope1).WithBaggage({"key2", "value2"})
// The context of scope2 would be derived from scope1 and key2/value2 would be additive
}
// scope2 has been disposed and scope1 has been restored, and
// Baggage.Current contains key1/value1
}
} But with less new artifacts / smaller public API. I think it would be great to have a fully spec-compliant "Context" API. However, we couldn't do it strictly in OTel .NET because we don't own My thinking is we work with .NET on what that API should be. Once .NET has that API available, we can The changes here are good IMO to make the current OTel Baggage API more safe / spec-complaint in the meantime until that is available. |
The spec requires several operations (e.g. Set Value, Remove Value), how to achieve these with the proposal from this PR? |
Those APIs are still there on Here are the untouched APIs which I think are pretty spec-compliant at the moment: public readonly struct Baggage : IEquatable<Baggage>
{
public int Count { get; }
public IReadOnlyDictionary<string, string> GetBaggage() {}
public string? GetBaggage(string name) {}
public Baggage SetBaggage(string name, string? value) {}
public Baggage SetBaggage(params KeyValuePair<string, string?>[] baggageItems) {}
public Baggage SetBaggage(IEnumerable<KeyValuePair<string, string?>> baggageItems) {}
public Baggage RemoveBaggage(string name) {}
public Baggage ClearBaggage() {}
// Helper for creating Baggage instances but new Baggage() or default(Baggage) work equally well
public static Baggage Create(Dictionary<string, string>? baggageItems = null) {}
// Ceremony stuff
public Dictionary<string, string>.Enumerator GetEnumerator() {}
public bool Equals(Baggage other) {}
public override bool Equals(object? obj) {}
public override int GetHashCode() {}
public static bool operator ==(Baggage left, Baggage right) {}
public static bool operator !=(Baggage left, Baggage right) {}
} When it comes to working with a var b1 = Baggage.Create().SetBaggage("k1, "v1");
var b2 = b1.SetBaggage("k2", "v2");
var b3 = b2.RemoveBaggage("k2").SetBaggage("k3, "v3");
// b1 has k1
// b2 has k1 & k2
// b3 has k1 & k3 How those work with the new API is you build up some var newBaggage = Baggage.Create().SetBaggage("k1", "v1");
using var scope = Baggage.Attach(newBaggage);
// Everything running under scope has Baggage.Current with "k1" If you want to work off the existing var newBaggage = Baggage.Current.RemoveBaggage("k1").SetBaggage("newThing", "v1");
using var scope = Baggage.Attach(newBaggage);
// Everything running under scope has whatever was in Baggage.Current without "k1" and with "newThing" |
I still don't understand, for example, how to use this in the following situation: Line 62 in dfd27c5
|
You wouldn't use the If you are writing outgoing instrumentation you use Lines 108 to 112 in dfd27c5
Users who want to send some private async Task CallService()
{
using var scope = Baggage.Attach(Baggage.Create().SetBaggage("MyKey", "MyValue"));
await client.SayHelloAsync(
new HelloRequest { Name = "World" });
} Incoming instrumentation is more interesting (probably what you meant to link to 😄). If I'm catching your drift, you are looking for a way to do this that doesn't involve holding onto something which must be disposed. I just updated the AspNetCore instrumentation on this PR. What I did there is if we detect We could possibly make a different API but I'm a bit hesistant to do that because the spec has a MUST for the Detach:
I took a look at some of the other instrumentation in contrib (Owin, AspNet, WCF, etc.) and it won't take much effort to fix them up becuase they already have container things to track the If you have any ideas though I'm happy to explore them. |
This PR was marked stale due to lack of activity and will be closed in 7 days. Commenting or Pushing will instruct the bot to automatically remove the label. This bot runs once per day. |
This PR was marked stale due to lack of activity and will be closed in 7 days. Commenting or Pushing will instruct the bot to automatically remove the label. This bot runs once per day. |
Closed as inactive. Feel free to reopen if this PR is still being worked on. |
Any updates on that one? |
Fixes #3257
Alternative design #5208
[Note: The "attach" name is taken from Otel Specification > Context > Optional Global operations]
Goals
The goal here is to introduce an API which makes the
Baggage
ambient context flow behavior explicit. The current APIs are marked as obsolete to encourage users to migrate to the new safe API but nothing has changed and nothing will break.Changes
Baggage.Attach
API which can be used to establish a newBaggage
context which will flow on the current thread and across tasks until detached/disposed (AsyncLocal
behavior).Baggage
which interact withBaggage.Current
.Public API Changes
Obsoletions
Usage of Baggage.Attach
Simple case where user doesn't want to pass the current baggage on a specific call
More complex case where the user wants to fork the current baggage and add something for each call
How to migrate to the new API
Setting
Baggage
for an AspNetCore request via middlewarePrevent
Baggage.Current
from flowing on a specific downstream callMerge requirement checklist
CHANGELOG.md
files updated for non-trivial changes