Description
Background and Motivation
Follow up after #42596
Currently, there is no way of updating or removing the existing values of Activity.Baggage
. The only method available to change Baggage
state is AddBaggage and calling it twice with the same key would add two items to the list. It's important to note that Baggage
should be kept as small as possible because it's intended to be serialized over the wire across the process/machine.
I could see a couple of cases when an update is needed:
-
Unintended calls of the same
AddBaggage
multiple times that won't add any useful information but will increase the size of theBaggage
. For example, your services have a middleware that adds some value toBaggage
, on each service in the call chain you would get one more identical item added, and eventually, it could surpass the allowed size of the header that used to transferBaggage
via web requests. This case could be avoided by checking that item already present (not very elegant with current API), but only if you have access to modify code that adds items. -
Third-party code adding unwanted items to
Baggage
that you would like to remove to avoid transferring them or if they control some logic. -
The most annoying case is when you need to update the value for an existing item. After calling
AddBaggage
with the same keyGetBaggageItem
would return the updated value, but your baggage size is doubled, add in addition to that during transition over the wire order of the baggage items could be changed (since they need to be added in reverse order to preserve it, for example reordering currently happening in asp .net core), that would result inGetBaggageItem
returning different values depending on the amount of transfers baggage had. So having items with identical keys in theBaggage
is a highly undesired state, but currently, there is no way to avoid it if you need a value update.
To add to that described behaviors easy to miss assuming dictionary-like structure behind AddBaggage/GetBaggageItem
since they mostly behave the same before you look inside Baggage
collection or will try to transfer it.
Proposed API
namespace System.Diagnostics
{
public partial class Activity : IDisposable
{
public Activity SetBaggage(string key, string? value)
}
}
All of the mentioned problems could be solved by adding SetBaggage
method analogous to Activity.SetTag method. Alternative naming could be SetBaggageItem
, but it's more important to make it consistent with AddBaggage
then with GetBaggageItem
, and it's shorter :)
It might be initially confusing for users to have both AddBaggage
and SetBaggage
methods, but it should motivate to look more attentively in the behavior of AddBaggage
to prevent them from having duplicate keys.
Similar to SetTag
, passing null
as value parameter into SetBaggage
would remove item. That is especially important since Baggage
should be kept as small as possible.
An interesting case here is that Baggage
allows you to have multiple items with the same key. So there are multiple possible behaviours in this case.
Removal/update of the first matched item makes the most sense. It would be the item that is returned by GetBaggageItem
, so we would have those two methods matched. Beside that, having multiple items with the same key should be a very rare case (especially with this API available), almost always it would be a single item so all approaches would have the same end result, and removing the first matched is the most straightforward from the implementation point of view plus it could be done without iterating through the whole list.
Alternative options could be removal/update of the last element that could lead to very confusing behavior when combined with GetBaggageItem
that returns first element. Or removal/update of all occurrences that whould add overhead on each call, to cover a really narrow use case plus setting all items to the same value does not have a lot of practical usage.
Usage Examples
SetBaggage
could be used instead of AddBaggage
in cases when it's possible that code might be executed twice in the call chain (for example middleware or some infrastructure code) to guaranty that Baggage
size won't be expanded unintentionally and contains a single entry for each key.
The ability to remove/update items in the Baggage
also would be used to remove unneeded items added by a third party and for quick hacks to check that baggage item presence/absence/spesial value provides the desired result or creates bug.
Method have similar API to existing Activity
methods and could be chained with others.
Risks
SetBaggage
would be slower than AddBaggage
(that it will replace in some scenarios) since instead of just adding an item it will need to iterate over the Baggage
list, but considering usually small size of Baggage
performance degradation should not be significant, and presence of both methods would allow users to chose the most appropriate for their scenario.