22// The .NET Foundation licenses this file to you under the MIT license.
33
44using System . Diagnostics ;
5+ using Microsoft . AspNetCore . Components . Infrastructure ;
56
67namespace Microsoft . AspNetCore . Components ;
78
@@ -11,115 +12,66 @@ namespace Microsoft.AspNetCore.Components;
1112internal class ComponentsActivitySource
1213{
1314 internal const string Name = "Microsoft.AspNetCore.Components" ;
14- internal const string OnCircuitName = $ "{ Name } .CircuitStart";
1515 internal const string OnRouteName = $ "{ Name } .RouteChange";
1616 internal const string OnEventName = $ "{ Name } .HandleEvent";
1717
18- private ActivityContext _httpContext ;
19- private ActivityContext _circuitContext ;
20- private string ? _circuitId ;
21- private ActivityContext _routeContext ;
22-
2318 private ActivitySource ActivitySource { get ; } = new ActivitySource ( Name ) ;
19+ private ComponentsActivityLinkStore ? _componentsActivityLinkStore ;
2420
25- public static ActivityContext CaptureHttpContext ( )
21+ public void Init ( ComponentsActivityLinkStore store )
2622 {
27- var parentActivity = Activity . Current ;
28- if ( parentActivity is not null && parentActivity . OperationName == "Microsoft.AspNetCore.Hosting.HttpRequestIn" && parentActivity . Recorded )
29- {
30- return parentActivity . Context ;
31- }
32- return default ;
23+ _componentsActivityLinkStore = store ;
3324 }
3425
35- public Activity ? StartCircuitActivity ( string circuitId , ActivityContext httpContext )
26+ public ComponentsActivityHandle StartRouteActivity ( string componentType , string route )
3627 {
37- _circuitId = circuitId ;
38-
39- var activity = ActivitySource . CreateActivity ( OnCircuitName , ActivityKind . Internal , parentId : null , null , null ) ;
28+ var activity = ActivitySource . CreateActivity ( OnRouteName , ActivityKind . Internal , parentId : null , null , null ) ;
4029 if ( activity is not null )
4130 {
42- if ( activity . IsAllDataRequested )
43- {
44- if ( _circuitId != null )
45- {
46- activity . SetTag ( "aspnetcore.components.circuit.id" , _circuitId ) ;
47- }
48- if ( httpContext != default )
49- {
50- activity . AddLink ( new ActivityLink ( httpContext ) ) ;
51- }
52- }
53- activity . DisplayName = $ "Circuit { circuitId ?? "" } ";
31+ var httpActivity = Activity . Current ;
32+ activity . DisplayName = $ "Route { route ?? "[unknown path]" } -> { componentType ?? "[unknown component]" } ";
33+ Activity . Current = null ; // do not inherit the parent activity
5434 activity . Start ( ) ;
55- _circuitContext = activity . Context ;
56- }
57- return activity ;
58- }
5935
60- public void FailCircuitActivity ( Activity ? activity , Exception ex )
61- {
62- _circuitContext = default ;
63- if ( activity != null && ! activity . IsStopped )
64- {
65- activity . SetTag ( "error.type" , ex . GetType ( ) . FullName ) ;
66- activity . SetStatus ( ActivityStatusCode . Error ) ;
67- activity . Stop ( ) ;
68- }
69- }
70-
71- public Activity ? StartRouteActivity ( string componentType , string route )
72- {
73- if ( _httpContext == default )
74- {
75- _httpContext = CaptureHttpContext ( ) ;
76- }
77-
78- var activity = ActivitySource . CreateActivity ( OnRouteName , ActivityKind . Internal , parentId : null , null , null ) ;
79- if ( activity is not null )
80- {
8136 if ( activity . IsAllDataRequested )
8237 {
83- if ( _circuitId != null )
84- {
85- activity . SetTag ( "aspnetcore.components.circuit.id" , _circuitId ) ;
86- }
8738 if ( componentType != null )
8839 {
8940 activity . SetTag ( "aspnetcore.components.type" , componentType ) ;
9041 }
9142 if ( route != null )
9243 {
9344 activity . SetTag ( "aspnetcore.components.route" , route ) ;
94- }
95- if ( _httpContext != default )
96- {
97- activity . AddLink ( new ActivityLink ( _httpContext ) ) ;
98- }
99- if ( _circuitContext != default )
100- {
101- activity . AddLink ( new ActivityLink ( _circuitContext ) ) ;
45+
46+ // store self link
47+ _componentsActivityLinkStore ! . SetActivityContext ( ComponentsActivityLinkStore . Route , activity . Context ,
48+ new KeyValuePair < string , object ? > ( "aspnetcore.components.route" , route ) ) ;
10249 }
10350 }
10451
105- activity . DisplayName = $ "Route { route ?? "[unknown path]" } -> { componentType ?? "[unknown component]" } ";
106- activity . Start ( ) ;
107- _routeContext = activity . Context ;
52+ return new ComponentsActivityHandle { Activity = activity , Previous = httpActivity } ;
10853 }
109- return activity ;
54+ return default ;
55+ }
56+
57+ public void StopRouteActivity ( ComponentsActivityHandle activityHandle , Exception ? ex )
58+ {
59+ StopComponentActivity ( ComponentsActivityLinkStore . Route , activityHandle , ex ) ;
11060 }
11161
112- public Activity ? StartEventActivity ( string ? componentType , string ? methodName , string ? attributeName )
62+ public ComponentsActivityHandle StartEventActivity ( string ? componentType , string ? methodName , string ? attributeName )
11363 {
11464 var activity = ActivitySource . CreateActivity ( OnEventName , ActivityKind . Internal , parentId : null , null , null ) ;
65+
11566 if ( activity is not null )
11667 {
68+ var previousActivity = Activity . Current ;
69+ activity . DisplayName = $ "Event { attributeName ?? "[unknown attribute]" } -> { componentType ?? "[unknown component]" } .{ methodName ?? "[unknown method]" } ";
70+ Activity . Current = null ; // do not inherit the parent activity
71+ activity . Start ( ) ;
72+
11773 if ( activity . IsAllDataRequested )
11874 {
119- if ( _circuitId != null )
120- {
121- activity . SetTag ( "aspnetcore.components.circuit.id" , _circuitId ) ;
122- }
12375 if ( componentType != null )
12476 {
12577 activity . SetTag ( "aspnetcore.components.type" , componentType ) ;
@@ -132,46 +84,60 @@ public void FailCircuitActivity(Activity? activity, Exception ex)
13284 {
13385 activity . SetTag ( "aspnetcore.components.attribute.name" , attributeName ) ;
13486 }
135- if ( _httpContext != default )
136- {
137- activity . AddLink ( new ActivityLink ( _httpContext ) ) ;
138- }
139- if ( _circuitContext != default )
140- {
141- activity . AddLink ( new ActivityLink ( _circuitContext ) ) ;
142- }
143- if ( _routeContext != default )
144- {
145- activity . AddLink ( new ActivityLink ( _routeContext ) ) ;
146- }
14787 }
14888
149- activity . DisplayName = $ "Event { attributeName ?? "[unknown attribute]" } -> { componentType ?? "[unknown component]" } .{ methodName ?? "[unknown method]" } ";
150- activity . Start ( ) ;
89+ return new ComponentsActivityHandle { Activity = activity , Previous = previousActivity } ;
15190 }
152- return activity ;
91+ return default ;
15392 }
15493
155- public static void FailEventActivity ( Activity ? activity , Exception ex )
94+ public void StopEventActivity ( ComponentsActivityHandle activityHandle , Exception ? ex )
15695 {
157- if ( activity != null && ! activity . IsStopped )
158- {
159- activity . SetTag ( "error.type" , ex . GetType ( ) . FullName ) ;
160- activity . SetStatus ( ActivityStatusCode . Error ) ;
161- activity . Stop ( ) ;
162- }
96+ StopComponentActivity ( ComponentsActivityLinkStore . Event , activityHandle , ex ) ;
16397 }
16498
165- public static async Task CaptureEventStopAsync ( Task task , Activity ? activity )
99+ public async Task CaptureEventStopAsync ( Task task , ComponentsActivityHandle activityHandle )
166100 {
167101 try
168102 {
169103 await task ;
170- activity ? . Stop ( ) ;
104+ StopEventActivity ( activityHandle , null ) ;
171105 }
172106 catch ( Exception ex )
173107 {
174- FailEventActivity ( activity , ex ) ;
108+ StopEventActivity ( activityHandle , ex ) ;
175109 }
176110 }
111+
112+ private void StopComponentActivity ( string category , ComponentsActivityHandle activityHandle , Exception ? ex )
113+ {
114+ var activity = activityHandle . Activity ;
115+ if ( activity != null && ! activity . IsStopped )
116+ {
117+ if ( ex != null )
118+ {
119+ activity . SetTag ( "error.type" , ex . GetType ( ) . FullName ) ;
120+ activity . SetStatus ( ActivityStatusCode . Error ) ;
121+ }
122+ if ( activity . IsAllDataRequested )
123+ {
124+ _componentsActivityLinkStore ! . AddActivityContexts ( category , activity ) ;
125+ }
126+ activity . Stop ( ) ;
127+
128+ if ( Activity . Current == null && activityHandle . Previous != null && ! activityHandle . Previous . IsStopped )
129+ {
130+ Activity . Current = activityHandle . Previous ;
131+ }
132+ }
133+ }
134+ }
135+
136+ /// <summary>
137+ /// Named tuple for restoring the previous activity after stopping the current one.
138+ /// </summary>
139+ internal struct ComponentsActivityHandle
140+ {
141+ public Activity ? Previous ;
142+ public Activity ? Activity ;
177143}
0 commit comments