Delete FriendAccessAllowedAttribute and associated dead code (#15101)
[platform/upstream/coreclr.git] / src / mscorlib / src / System / Threading / Tasks / AsyncCausalityTracer.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 //
6 //
7
8 using System;
9 using System.Security;
10 using System.Diagnostics;
11 using System.Runtime.CompilerServices;
12 using System.Runtime.InteropServices;
13
14 #if FEATURE_COMINTEROP
15 using System.Runtime.InteropServices.WindowsRuntime;
16
17 using WFD = Windows.Foundation.Diagnostics;
18 #endif
19
20
21 namespace System.Threading.Tasks
22 {
23     // [FriendAccessAllowed]
24     internal enum CausalityTraceLevel
25     {
26 #if FEATURE_COMINTEROP
27         Required = WFD.CausalityTraceLevel.Required,
28         Important = WFD.CausalityTraceLevel.Important,
29         Verbose = WFD.CausalityTraceLevel.Verbose
30 #else
31         Required,
32         Important,
33         Verbose
34 #endif
35     }
36
37     // [FriendAccessAllowed]
38     internal enum AsyncCausalityStatus
39     {
40 #if FEATURE_COMINTEROP
41         Canceled = WFD.AsyncCausalityStatus.Canceled,
42         Completed = WFD.AsyncCausalityStatus.Completed,
43         Error = WFD.AsyncCausalityStatus.Error,
44         Started = WFD.AsyncCausalityStatus.Started
45 #else
46         Started,
47         Completed,
48         Canceled,
49         Error
50 #endif
51     }
52
53     internal enum CausalityRelation
54     {
55 #if FEATURE_COMINTEROP
56         AssignDelegate = WFD.CausalityRelation.AssignDelegate,
57         Join = WFD.CausalityRelation.Join,
58         Choice = WFD.CausalityRelation.Choice,
59         Cancel = WFD.CausalityRelation.Cancel,
60         Error = WFD.CausalityRelation.Error
61 #else
62         AssignDelegate,
63         Join,
64         Choice,
65         Cancel,
66         Error
67 #endif
68     }
69
70     internal enum CausalitySynchronousWork
71     {
72 #if FEATURE_COMINTEROP
73         CompletionNotification = WFD.CausalitySynchronousWork.CompletionNotification,
74         ProgressNotification = WFD.CausalitySynchronousWork.ProgressNotification,
75         Execution = WFD.CausalitySynchronousWork.Execution
76 #else
77         CompletionNotification,
78         ProgressNotification,
79         Execution
80 #endif
81     }
82
83     // [FriendAccessAllowed]
84     internal static class AsyncCausalityTracer
85     {
86         static internal void EnableToETW(bool enabled)
87         {
88 #if FEATURE_COMINTEROP
89             if (enabled)
90                 f_LoggingOn |= Loggers.ETW;
91             else
92                 f_LoggingOn &= ~Loggers.ETW;
93 #endif
94         }
95
96         internal static bool LoggingOn
97         {
98             // [FriendAccessAllowed]
99             get
100             {
101 #if FEATURE_COMINTEROP
102                 return f_LoggingOn != 0;
103 #else
104                 return false;
105 #endif
106             }
107         }
108
109 #if FEATURE_COMINTEROP
110         //s_PlatformId = {4B0171A6-F3D0-41A0-9B33-02550652B995}
111         private static readonly Guid s_PlatformId = new Guid(0x4B0171A6, 0xF3D0, 0x41A0, 0x9B, 0x33, 0x02, 0x55, 0x06, 0x52, 0xB9, 0x95);
112
113         //Indicates this information comes from the BCL Library
114         private const WFD.CausalitySource s_CausalitySource = WFD.CausalitySource.Library;
115
116         //Lazy initialize the actual factory
117         private static WFD.IAsyncCausalityTracerStatics s_TracerFactory;
118
119         // The loggers that this Tracer knows about. 
120         [Flags]
121         private enum Loggers : byte
122         {
123             CausalityTracer = 1,
124             ETW = 2
125         }
126
127
128         //We receive the actual value for these as a callback
129         private static Loggers f_LoggingOn; //assumes false by default
130
131         // The precise static constructor will run first time somebody attempts to access this class
132         static AsyncCausalityTracer()
133         {
134             if (!Environment.IsWinRTSupported) return;
135
136             //COM Class Id
137             string ClassId = "Windows.Foundation.Diagnostics.AsyncCausalityTracer";
138
139             //COM Interface GUID  {50850B26-267E-451B-A890-AB6A370245EE}
140             Guid guid = new Guid(0x50850B26, 0x267E, 0x451B, 0xA8, 0x90, 0XAB, 0x6A, 0x37, 0x02, 0x45, 0xEE);
141
142             Object factory = null;
143
144             try
145             {
146                 int hresult = Microsoft.Win32.UnsafeNativeMethods.RoGetActivationFactory(ClassId, ref guid, out factory);
147
148                 if (hresult < 0 || factory == null) return; //This prevents having an exception thrown in case IAsyncCausalityTracerStatics isn't registered.
149
150                 s_TracerFactory = (WFD.IAsyncCausalityTracerStatics)factory;
151
152                 EventRegistrationToken token = s_TracerFactory.add_TracingStatusChanged(new EventHandler<WFD.TracingStatusChangedEventArgs>(TracingStatusChangedHandler));
153                 Debug.Assert(token != default(EventRegistrationToken), "EventRegistrationToken is null");
154             }
155             catch (Exception ex)
156             {
157                 // Although catching generic Exception is not recommended, this file is one exception
158                 // since we don't want to propagate any kind of exception to the user since all we are
159                 // doing here depends on internal state.
160                 LogAndDisable(ex);
161             }
162         }
163
164         private static void TracingStatusChangedHandler(Object sender, WFD.TracingStatusChangedEventArgs args)
165         {
166             if (args.Enabled)
167                 f_LoggingOn |= Loggers.CausalityTracer;
168             else
169                 f_LoggingOn &= ~Loggers.CausalityTracer;
170         }
171 #endif
172
173         //
174         // The TraceXXX methods should be called only if LoggingOn property returned true
175         //
176
177         // [FriendAccessAllowed]
178         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Tracking is slow path. Disable inlining for it.
179         internal static void TraceOperationCreation(CausalityTraceLevel traceLevel, int taskId, string operationName, ulong relatedContext)
180         {
181 #if FEATURE_COMINTEROP
182             try
183             {
184                 if ((f_LoggingOn & Loggers.ETW) != 0)
185                     TplEtwProvider.Log.TraceOperationBegin(taskId, operationName, (long)relatedContext);
186                 if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
187                     s_TracerFactory.TraceOperationCreation((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), operationName, relatedContext);
188             }
189             catch (Exception ex)
190             {
191                 //view function comment
192                 LogAndDisable(ex);
193             }
194 #endif
195         }
196
197         // [FriendAccessAllowed]
198         [MethodImplAttribute(MethodImplOptions.NoInlining)]
199         internal static void TraceOperationCompletion(CausalityTraceLevel traceLevel, int taskId, AsyncCausalityStatus status)
200         {
201 #if FEATURE_COMINTEROP
202             try
203             {
204                 if ((f_LoggingOn & Loggers.ETW) != 0)
205                     TplEtwProvider.Log.TraceOperationEnd(taskId, status);
206                 if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
207                     s_TracerFactory.TraceOperationCompletion((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.AsyncCausalityStatus)status);
208             }
209             catch (Exception ex)
210             {
211                 //view function comment
212                 LogAndDisable(ex);
213             }
214 #endif
215         }
216
217         [MethodImplAttribute(MethodImplOptions.NoInlining)]
218         internal static void TraceOperationRelation(CausalityTraceLevel traceLevel, int taskId, CausalityRelation relation)
219         {
220 #if FEATURE_COMINTEROP
221             try
222             {
223                 if ((f_LoggingOn & Loggers.ETW) != 0)
224                     TplEtwProvider.Log.TraceOperationRelation(taskId, relation);
225                 if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
226                     s_TracerFactory.TraceOperationRelation((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.CausalityRelation)relation);
227             }
228             catch (Exception ex)
229             {
230                 //view function comment
231                 LogAndDisable(ex);
232             }
233 #endif
234         }
235
236         [MethodImplAttribute(MethodImplOptions.NoInlining)]
237         internal static void TraceSynchronousWorkStart(CausalityTraceLevel traceLevel, int taskId, CausalitySynchronousWork work)
238         {
239 #if FEATURE_COMINTEROP
240             try
241             {
242                 if ((f_LoggingOn & Loggers.ETW) != 0)
243                     TplEtwProvider.Log.TraceSynchronousWorkBegin(taskId, work);
244                 if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
245                     s_TracerFactory.TraceSynchronousWorkStart((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.CausalitySynchronousWork)work);
246             }
247             catch (Exception ex)
248             {
249                 //view function comment
250                 LogAndDisable(ex);
251             }
252 #endif
253         }
254
255         [MethodImplAttribute(MethodImplOptions.NoInlining)]
256         internal static void TraceSynchronousWorkCompletion(CausalityTraceLevel traceLevel, CausalitySynchronousWork work)
257         {
258 #if FEATURE_COMINTEROP
259             try
260             {
261                 if ((f_LoggingOn & Loggers.ETW) != 0)
262                     TplEtwProvider.Log.TraceSynchronousWorkEnd(work);
263                 if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
264                     s_TracerFactory.TraceSynchronousWorkCompletion((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, (WFD.CausalitySynchronousWork)work);
265             }
266             catch (Exception ex)
267             {
268                 //view function comment
269                 LogAndDisable(ex);
270             }
271 #endif
272         }
273
274 #if FEATURE_COMINTEROP
275         //fix for 796185: leaking internal exceptions to customers,
276         //we should catch and log exceptions but never propagate them.
277         private static void LogAndDisable(Exception ex)
278         {
279             f_LoggingOn = 0;
280             Debugger.Log(0, "AsyncCausalityTracer", ex.ToString());
281         }
282 #endif
283
284         private static ulong GetOperationId(uint taskId)
285         {
286             return (((ulong)AppDomain.CurrentDomain.Id) << 32) + taskId;
287         }
288     }
289 }