-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Child Activity outliving its parent corrupts Activity.Current
#101775
Comments
Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti |
I think you are mixing between Doing: b.Stop();
Console.WriteLine($"Current: {Activity.Current!.OperationName} ... b.Parent: {b.Parent!.OperationName}, b.Parent.IsStopped: {b.Parent!.IsStopped} ... c.IsStopped: {c.IsStopped}");
I can see we may improve the CC @noahfalk |
Tagging subscribers to this area: @dotnet/area-system-diagnostics-activity |
I didn't state that that stopping the parent stops the child. It's all about Actually, the same problem is present when there is no intention to create a parent-child relationship between the activities, ie. when creating Activity c = activitySource.CreateActivity("c", ActivityKind.Internal,
new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None)); This |
You were referring to the OTel specs that says: Anyway, I am not objecting we try to fix the |
I'd consider the current behavior a bug and I think it would be legitimate for us to fix it. I'd guess it has very low (but not zero) odds of breaking someone.
Activity.Current has a public setter which is one way it could be recovered. In your example calling a.Stop() would also recover it. In async code returning to the caller also restores the caller's async locals so thats another option.
.NET doesn't have an explicit API to create new root Activities, but you can set private async ValueTask<(Stream, TransportContext?, Activity?, IPEndPoint?)> ConnectAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken)
{
// assume Activity.Current is set to some arbitrary http request activity that should not
// be the parent of this activity
Activity.Current = null;
Activity connectionActivity = s_connectionActivitySource.StartActivity(
DiagnosticsHandlerLoggingStrings.ConnectionActivityName);
} If you weren't in an async function you'd probably want to save and restore the previous value of Activity.Current, but returning from an async function restores the parent's async locals automatically. |
This feels like an unintuative pattern. I would expect to have a parameter on the StartActivity call to de-parent the child or to explicitly call SetParentId. This looks like you're changing static state in order to disconnect the child and requires complex knowledge to understand that it will be restored at exit. |
Yep, no claim that it is easy or intuitive. Its just what is currently available to work with. |
According to https://github.com/open-telemetry/opentelemetry-specification/blob/v1.31.0/specification/trace/api.md#end, child spans are allowed to outlive their parents:
However in .NET such activities may lead to weird behavior resulting in
Activity.Current
becoming an activity that has been already stopped, leaving devs without an option to leave the corrupted state:The text was updated successfully, but these errors were encountered: