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 using System.Diagnostics.Tracing;
6 
7 namespace System.Threading
8 {
9     [EventSource(Name = "Microsoft-Windows-DotNETRuntime", Guid = "{e13c0d23-ccbc-4e12-931b-d9cc2eee27e4}")]
10     public sealed class ClrThreadPoolEventSource : EventSource
11     {
12         private const string WorkerThreadMessage = "WorkerThreadCount=%1";
13         private const string WorkerThreadAdjustmentSampleMessage = "Throughput=%1";
14         private const string WorkerThreadAdjustmentAdjustmentEventMessage = "AverageThroughput=%1;%nNewWorkerThreadCount=%2;%nReason=%3";
15         private const string WorkerThreadAdjustmentStatsEventMessage = "Duration=%1;%nThroughput=%2;%nThreadWave=%3;%nThroughputWave=%4;%nThroughputErrorEstimate=%5;%nAverageThroughputErrorEstimate=%6;%nThroughputRatio=%7;%nConfidence=%8;%nNewControlSetting=%9;%nNewThreadWaveMagnitude=%10";
16 
17         // We have these constants here because EventTask, EventOpcode, and EventKeywords are public APIs, and we don't want to expose these values to the end user to use in their events.
18         private const EventTask WorkerThreadTask = (EventTask)16;
19         private const EventTask WorkerThreadAdjustmentTask = (EventTask)18;
20 
21         private const EventOpcode WaitOpcode = (EventOpcode)90;
22         private const EventOpcode SampleOpcode = (EventOpcode)100;
23         private const EventOpcode AdjustmentOpcode = (EventOpcode)101;
24         private const EventOpcode StatsOpcode = (EventOpcode)102;
25         private const EventKeywords ThreadingKeyword = (EventKeywords)0x10000;
26 
ClrThreadPoolEventSource()27         private ClrThreadPoolEventSource()
28         {
29         }
30 
31         [Event(1, Level = EventLevel.Informational, Message = WorkerThreadMessage, Task = WorkerThreadTask, Opcode = EventOpcode.Start, Version = 0, Keywords = ThreadingKeyword)]
WorkerThreadStart(short numExistingThreads)32         public void WorkerThreadStart(short numExistingThreads)
33         {
34             WriteEvent(1, numExistingThreads);
35         }
36 
37         [Event(2, Level = EventLevel.Informational, Message = WorkerThreadMessage, Task = WorkerThreadTask, Opcode = EventOpcode.Stop, Version = 0, Keywords = ThreadingKeyword)]
WorkerThreadStop(short numExistingThreads)38         public void WorkerThreadStop(short numExistingThreads)
39         {
40             WriteEvent(2, numExistingThreads);
41         }
42 
43         [Event(3, Level = EventLevel.Informational, Message = WorkerThreadMessage, Task = WorkerThreadTask, Opcode = WaitOpcode, Version = 0, Keywords = ThreadingKeyword)]
WorkerThreadWait(short numExistingThreads)44         public void WorkerThreadWait(short numExistingThreads)
45         {
46             WriteEvent(3, numExistingThreads);
47         }
48 
49         [Event(4, Level = EventLevel.Informational, Message = WorkerThreadAdjustmentSampleMessage, Opcode = SampleOpcode, Version = 0, Task = WorkerThreadAdjustmentTask, Keywords = ThreadingKeyword)]
WorkerThreadAdjustmentSample(double throughput)50         public unsafe void WorkerThreadAdjustmentSample(double throughput)
51         {
52             if (IsEnabled())
53             {
54                 EventData* data = stackalloc EventData[1];
55                 data[0].DataPointer = (IntPtr)(&throughput);
56                 data[0].Size = sizeof(double);
57                 WriteEventCore(4, 1, data);
58             }
59         }
60 
61         [Event(5, Level = EventLevel.Informational, Message = WorkerThreadAdjustmentSampleMessage, Opcode = AdjustmentOpcode, Version = 0, Task = WorkerThreadAdjustmentTask, Keywords = ThreadingKeyword)]
WorkerThreadAdjustmentAdjustment(double averageThroughput, int newWorkerThreadCount, int stateOrTransition)62         public unsafe void WorkerThreadAdjustmentAdjustment(double averageThroughput, int newWorkerThreadCount, int stateOrTransition)
63         {
64             if (IsEnabled())
65             {
66                 EventData* data = stackalloc EventData[3];
67                 data[0].DataPointer = (IntPtr)(&averageThroughput);
68                 data[0].Size = sizeof(double);
69                 data[1].DataPointer = (IntPtr)(&newWorkerThreadCount);
70                 data[1].Size = sizeof(int);
71                 data[2].DataPointer = (IntPtr)(&stateOrTransition);
72                 data[2].Size = sizeof(int);
73                 WriteEventCore(5, 3, data);
74             }
75         }
76 
77         [Event(6, Level = EventLevel.Verbose, Message = WorkerThreadAdjustmentSampleMessage, Opcode = StatsOpcode, Version = 0, Task = WorkerThreadAdjustmentTask, Keywords = ThreadingKeyword)]
78         [CLSCompliant(false)]
WorkerThreadAdjustmentStats(double duration, double throughput, double threadWave, double throughputWave, double throughputErrorEstimate, double averageThroughputNoise, double ratio, double confidence, double currentControlSetting, ushort newThreadWaveMagnitude)79         public unsafe void WorkerThreadAdjustmentStats(double duration, double throughput, double threadWave, double throughputWave, double throughputErrorEstimate,
80             double averageThroughputNoise, double ratio, double confidence, double currentControlSetting, ushort newThreadWaveMagnitude)
81         {
82             if (IsEnabled())
83             {
84                 EventData* data = stackalloc EventData[10];
85                 data[0].DataPointer = (IntPtr)(&duration);
86                 data[0].Size = sizeof(double);
87                 data[1].DataPointer = (IntPtr)(&throughput);
88                 data[1].Size = sizeof(double);
89                 data[2].DataPointer = (IntPtr)(&threadWave);
90                 data[2].Size = sizeof(double);
91                 data[3].DataPointer = (IntPtr)(&throughputWave);
92                 data[3].Size = sizeof(double);
93                 data[4].DataPointer = (IntPtr)(&throughputErrorEstimate);
94                 data[4].Size = sizeof(double);
95                 data[5].DataPointer = (IntPtr)(&averageThroughputNoise);
96                 data[5].Size = sizeof(double);
97                 data[6].DataPointer = (IntPtr)(&ratio);
98                 data[6].Size = sizeof(double);
99                 data[7].DataPointer = (IntPtr)(&confidence);
100                 data[7].Size = sizeof(double);
101                 data[8].DataPointer = (IntPtr)(&currentControlSetting);
102                 data[8].Size = sizeof(double);
103                 data[9].DataPointer = (IntPtr)(&newThreadWaveMagnitude);
104                 data[9].Size = sizeof(ushort);
105                 WriteEventCore(6, 10, data);
106             }
107         }
108 
109 #pragma warning disable IDE1006 // Naming Styles
110         public static readonly ClrThreadPoolEventSource Log = new ClrThreadPoolEventSource();
111 #pragma warning restore IDE1006 // Naming Styles
112     }
113 }
114