|
5 | 5 |
|
6 | 6 | namespace Microsoft.AspNetCore.Components; |
7 | 7 |
|
| 8 | +internal struct ComponentsActivityWrapper |
| 9 | +{ |
| 10 | + public Activity? Previous; |
| 11 | + public Activity? Activity; |
| 12 | +} |
| 13 | + |
8 | 14 | /// <summary> |
9 | 15 | /// This is instance scoped per renderer |
10 | 16 | /// </summary> |
11 | 17 | internal class ComponentsActivitySource |
12 | 18 | { |
13 | 19 | internal const string Name = "Microsoft.AspNetCore.Components"; |
14 | | - internal const string OnCircuitName = $"{Name}.CircuitStart"; |
15 | 20 | internal const string OnRouteName = $"{Name}.RouteChange"; |
16 | 21 | internal const string OnEventName = $"{Name}.HandleEvent"; |
17 | 22 |
|
18 | | - private ActivityContext _httpContext; |
19 | | - private ActivityContext _circuitContext; |
20 | | - private string? _circuitId; |
| 23 | + internal ActivityContext _httpContext; |
| 24 | + internal ActivityContext _circuitContext; |
| 25 | + internal string? _circuitId; |
| 26 | + |
21 | 27 | private ActivityContext _routeContext; |
22 | 28 |
|
23 | 29 | private ActivitySource ActivitySource { get; } = new ActivitySource(Name); |
24 | 30 |
|
25 | | - public static ActivityContext CaptureHttpContext() |
26 | | - { |
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; |
33 | | - } |
34 | | - |
35 | | - public Activity? StartCircuitActivity(string circuitId, ActivityContext httpContext) |
36 | | - { |
37 | | - _circuitId = circuitId; |
38 | | - |
39 | | - var activity = ActivitySource.CreateActivity(OnCircuitName, ActivityKind.Internal, parentId: null, null, null); |
40 | | - if (activity is not null) |
41 | | - { |
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 ?? ""}"; |
54 | | - activity.Start(); |
55 | | - _circuitContext = activity.Context; |
56 | | - } |
57 | | - return activity; |
58 | | - } |
59 | | - |
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) |
| 31 | + public ComponentsActivityWrapper StartRouteActivity(string componentType, string route) |
72 | 32 | { |
73 | | - if (_httpContext == default) |
74 | | - { |
75 | | - _httpContext = CaptureHttpContext(); |
76 | | - } |
77 | | - |
78 | 33 | var activity = ActivitySource.CreateActivity(OnRouteName, ActivityKind.Internal, parentId: null, null, null); |
79 | 34 | if (activity is not null) |
80 | 35 | { |
@@ -103,13 +58,16 @@ public void FailCircuitActivity(Activity? activity, Exception ex) |
103 | 58 | } |
104 | 59 |
|
105 | 60 | activity.DisplayName = $"Route {route ?? "[unknown path]"} -> {componentType ?? "[unknown component]"}"; |
| 61 | + var previousActivity = Activity.Current; |
| 62 | + Activity.Current = null; // do not inherit the parent activity |
106 | 63 | activity.Start(); |
107 | 64 | _routeContext = activity.Context; |
| 65 | + return new ComponentsActivityWrapper { Activity = activity, Previous = previousActivity }; |
108 | 66 | } |
109 | | - return activity; |
| 67 | + return default; |
110 | 68 | } |
111 | 69 |
|
112 | | - public Activity? StartEventActivity(string? componentType, string? methodName, string? attributeName) |
| 70 | + public ComponentsActivityWrapper StartEventActivity(string? componentType, string? methodName, string? attributeName) |
113 | 71 | { |
114 | 72 | var activity = ActivitySource.CreateActivity(OnEventName, ActivityKind.Internal, parentId: null, null, null); |
115 | 73 | if (activity is not null) |
@@ -147,31 +105,42 @@ public void FailCircuitActivity(Activity? activity, Exception ex) |
147 | 105 | } |
148 | 106 |
|
149 | 107 | activity.DisplayName = $"Event {attributeName ?? "[unknown attribute]"} -> {componentType ?? "[unknown component]"}.{methodName ?? "[unknown method]"}"; |
| 108 | + var previousActivity = Activity.Current; |
| 109 | + Activity.Current = null; // do not inherit the parent activity |
150 | 110 | activity.Start(); |
| 111 | + return new ComponentsActivityWrapper { Activity = activity, Previous = previousActivity }; |
151 | 112 | } |
152 | | - return activity; |
| 113 | + return default; |
153 | 114 | } |
154 | 115 |
|
155 | | - public static void FailEventActivity(Activity? activity, Exception ex) |
| 116 | + public static void StopComponentActivity(ComponentsActivityWrapper wrapper, Exception? ex) |
156 | 117 | { |
157 | | - if (activity != null && !activity.IsStopped) |
| 118 | + if (wrapper.Activity != null && !wrapper.Activity.IsStopped) |
158 | 119 | { |
159 | | - activity.SetTag("error.type", ex.GetType().FullName); |
160 | | - activity.SetStatus(ActivityStatusCode.Error); |
161 | | - activity.Stop(); |
| 120 | + if (ex != null) |
| 121 | + { |
| 122 | + wrapper.Activity.SetTag("error.type", ex.GetType().FullName); |
| 123 | + wrapper.Activity.SetStatus(ActivityStatusCode.Error); |
| 124 | + } |
| 125 | + wrapper.Activity.Stop(); |
| 126 | + |
| 127 | + if (Activity.Current == null && wrapper.Previous != null && !wrapper.Previous.IsStopped) |
| 128 | + { |
| 129 | + Activity.Current = wrapper.Previous; |
| 130 | + } |
162 | 131 | } |
163 | 132 | } |
164 | 133 |
|
165 | | - public static async Task CaptureEventStopAsync(Task task, Activity? activity) |
| 134 | + public static async Task CaptureEventStopAsync(Task task, ComponentsActivityWrapper wrapper) |
166 | 135 | { |
167 | 136 | try |
168 | 137 | { |
169 | 138 | await task; |
170 | | - activity?.Stop(); |
| 139 | + StopComponentActivity(wrapper, null); |
171 | 140 | } |
172 | 141 | catch (Exception ex) |
173 | 142 | { |
174 | | - FailEventActivity(activity, ex); |
| 143 | + StopComponentActivity(wrapper, ex); |
175 | 144 | } |
176 | 145 | } |
177 | 146 | } |
0 commit comments