2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
4
using System . Diagnostics ;
5
+ using Microsoft . AspNetCore . Components . Infrastructure ;
5
6
6
7
namespace Microsoft . AspNetCore . Components ;
7
8
@@ -11,115 +12,66 @@ namespace Microsoft.AspNetCore.Components;
11
12
internal class ComponentsActivitySource
12
13
{
13
14
internal const string Name = "Microsoft.AspNetCore.Components" ;
14
- internal const string OnCircuitName = $ "{ Name } .CircuitStart";
15
15
internal const string OnRouteName = $ "{ Name } .RouteChange";
16
16
internal const string OnEventName = $ "{ Name } .HandleEvent";
17
17
18
- private ActivityContext _httpContext ;
19
- private ActivityContext _circuitContext ;
20
- private string ? _circuitId ;
21
- private ActivityContext _routeContext ;
22
-
23
18
private ActivitySource ActivitySource { get ; } = new ActivitySource ( Name ) ;
19
+ private ComponentsActivityLinkStore ? _componentsActivityLinkStore ;
24
20
25
- public static ActivityContext CaptureHttpContext ( )
21
+ public void Init ( ComponentsActivityLinkStore store )
26
22
{
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 ;
33
24
}
34
25
35
- public Activity ? StartCircuitActivity ( string circuitId , ActivityContext httpContext )
26
+ public ComponentsActivityHandle StartRouteActivity ( string componentType , string route )
36
27
{
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 ) ;
40
29
if ( activity is not null )
41
30
{
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
54
34
activity . Start ( ) ;
55
- _circuitContext = activity . Context ;
56
- }
57
- return activity ;
58
- }
59
35
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
- {
81
36
if ( activity . IsAllDataRequested )
82
37
{
83
- if ( _circuitId != null )
84
- {
85
- activity . SetTag ( "aspnetcore.components.circuit.id" , _circuitId ) ;
86
- }
87
38
if ( componentType != null )
88
39
{
89
40
activity . SetTag ( "aspnetcore.components.type" , componentType ) ;
90
41
}
91
42
if ( route != null )
92
43
{
93
44
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 ) ) ;
102
49
}
103
50
}
104
51
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 } ;
108
53
}
109
- return activity ;
54
+ return default ;
55
+ }
56
+
57
+ public void StopRouteActivity ( ComponentsActivityHandle activityHandle , Exception ? ex )
58
+ {
59
+ StopComponentActivity ( ComponentsActivityLinkStore . Route , activityHandle , ex ) ;
110
60
}
111
61
112
- public Activity ? StartEventActivity ( string ? componentType , string ? methodName , string ? attributeName )
62
+ public ComponentsActivityHandle StartEventActivity ( string ? componentType , string ? methodName , string ? attributeName )
113
63
{
114
64
var activity = ActivitySource . CreateActivity ( OnEventName , ActivityKind . Internal , parentId : null , null , null ) ;
65
+
115
66
if ( activity is not null )
116
67
{
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
+
117
73
if ( activity . IsAllDataRequested )
118
74
{
119
- if ( _circuitId != null )
120
- {
121
- activity . SetTag ( "aspnetcore.components.circuit.id" , _circuitId ) ;
122
- }
123
75
if ( componentType != null )
124
76
{
125
77
activity . SetTag ( "aspnetcore.components.type" , componentType ) ;
@@ -132,46 +84,60 @@ public void FailCircuitActivity(Activity? activity, Exception ex)
132
84
{
133
85
activity . SetTag ( "aspnetcore.components.attribute.name" , attributeName ) ;
134
86
}
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
- }
147
87
}
148
88
149
- activity . DisplayName = $ "Event { attributeName ?? "[unknown attribute]" } -> { componentType ?? "[unknown component]" } .{ methodName ?? "[unknown method]" } ";
150
- activity . Start ( ) ;
89
+ return new ComponentsActivityHandle { Activity = activity , Previous = previousActivity } ;
151
90
}
152
- return activity ;
91
+ return default ;
153
92
}
154
93
155
- public static void FailEventActivity ( Activity ? activity , Exception ex )
94
+ public void StopEventActivity ( ComponentsActivityHandle activityHandle , Exception ? ex )
156
95
{
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 ) ;
163
97
}
164
98
165
- public static async Task CaptureEventStopAsync ( Task task , Activity ? activity )
99
+ public async Task CaptureEventStopAsync ( Task task , ComponentsActivityHandle activityHandle )
166
100
{
167
101
try
168
102
{
169
103
await task ;
170
- activity ? . Stop ( ) ;
104
+ StopEventActivity ( activityHandle , null ) ;
171
105
}
172
106
catch ( Exception ex )
173
107
{
174
- FailEventActivity ( activity , ex ) ;
108
+ StopEventActivity ( activityHandle , ex ) ;
175
109
}
176
110
}
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 ;
177
143
}
0 commit comments