Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 95d37e0

Browse files
authored
Expose new EventCounter APIs (#23808)
* rename BaseCounter to DiagnosticCounter * Change MetaData->Metadata * Make EventSource and Name a property for counter classes * Make the counter APIs public * fix build errors * Change float to double * Few cleanups, fix test * fix GetMetadataString * PR feedback * More PR feedback
1 parent 448e39d commit 95d37e0

File tree

10 files changed

+110
-141
lines changed

10 files changed

+110
-141
lines changed

src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,7 @@
908908
</ItemGroup>
909909
<ItemGroup>
910910
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\ActivityTracker.cs" />
911-
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\BaseCounter.cs" />
911+
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\DiagnosticCounter.cs" />
912912
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\CounterGroup.cs" />
913913
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\CounterPayload.cs" />
914914
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\EventActivityOptions.cs" />

src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,22 @@ namespace System.Diagnostics.Tracing
2020
internal class CounterGroup
2121
{
2222
private readonly EventSource _eventSource;
23-
private readonly List<BaseCounter> _counters;
23+
private readonly List<DiagnosticCounter> _counters;
2424

2525
internal CounterGroup(EventSource eventSource)
2626
{
2727
_eventSource = eventSource;
28-
_counters = new List<BaseCounter>();
28+
_counters = new List<DiagnosticCounter>();
2929
RegisterCommandCallback();
3030
}
3131

32-
internal void Add(BaseCounter eventCounter)
32+
internal void Add(DiagnosticCounter eventCounter)
3333
{
3434
lock (this) // Lock the CounterGroup
3535
_counters.Add(eventCounter);
3636
}
3737

38-
internal void Remove(BaseCounter eventCounter)
38+
internal void Remove(DiagnosticCounter eventCounter)
3939
{
4040
lock (this) // Lock the CounterGroup
4141
_counters.Remove(eventCounter);

src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterPayload.cs

Lines changed: 9 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -17,72 +17,26 @@ namespace Microsoft.Diagnostics.Tracing
1717
namespace System.Diagnostics.Tracing
1818
#endif
1919
{
20-
// TODO: This should be removed as we make the new payloads public
21-
[EventData]
22-
internal class EventCounterPayload : IEnumerable<KeyValuePair<string, object>>
23-
{
24-
public string Name { get; set; }
25-
26-
public float Mean { get; set; }
27-
28-
public float StandardDeviation { get; set; }
29-
30-
public int Count { get; set; }
31-
32-
public float Min { get; set; }
33-
34-
public float Max { get; set; }
35-
36-
public float IntervalSec { get; internal set; }
37-
38-
#region Implementation of the IEnumerable interface
39-
40-
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
41-
{
42-
return ForEnumeration.GetEnumerator();
43-
}
44-
45-
IEnumerator IEnumerable.GetEnumerator()
46-
{
47-
return ForEnumeration.GetEnumerator();
48-
}
49-
50-
private IEnumerable<KeyValuePair<string, object>> ForEnumeration
51-
{
52-
get
53-
{
54-
yield return new KeyValuePair<string, object>("Name", Name);
55-
yield return new KeyValuePair<string, object>("Mean", Mean);
56-
yield return new KeyValuePair<string, object>("StandardDeviation", StandardDeviation);
57-
yield return new KeyValuePair<string, object>("Count", Count);
58-
yield return new KeyValuePair<string, object>("Min", Min);
59-
yield return new KeyValuePair<string, object>("Max", Max);
60-
}
61-
}
62-
63-
#endregion // Implementation of the IEnumerable interface
64-
}
65-
6620
[EventData]
6721
internal class CounterPayload : IEnumerable<KeyValuePair<string, object>>
6822
{
6923
public string Name { get; set; }
7024

7125
public string DisplayName { get; set; }
7226

73-
public float Mean { get; set; }
27+
public double Mean { get; set; }
7428

75-
public float StandardDeviation { get; set; }
29+
public double StandardDeviation { get; set; }
7630

7731
public int Count { get; set; }
7832

79-
public float Min { get; set; }
33+
public double Min { get; set; }
8034

81-
public float Max { get; set; }
35+
public double Max { get; set; }
8236

8337
public float IntervalSec { get; internal set; }
8438

85-
public string MetaData { get; set; }
39+
public string Metadata { get; set; }
8640

8741
#region Implementation of the IEnumerable interface
8842

@@ -110,7 +64,7 @@ private IEnumerable<KeyValuePair<string, object>> ForEnumeration
11064
yield return new KeyValuePair<string, object>("IntervalSec", IntervalSec);
11165
yield return new KeyValuePair<string, object>("Series", $"Interval={IntervalSec}");
11266
yield return new KeyValuePair<string, object>("CounterType", "Mean");
113-
yield return new KeyValuePair<string, object>("MetaData", MetaData);
67+
yield return new KeyValuePair<string, object>("Metadata", Metadata);
11468
}
11569
}
11670

@@ -126,11 +80,11 @@ internal class IncrementingCounterPayload : IEnumerable<KeyValuePair<string, obj
12680

12781
public string DisplayRateTimeScale { get; set; }
12882

129-
public float Increment { get; set; }
83+
public double Increment { get; set; }
13084

13185
public float IntervalSec { get; internal set; }
13286

133-
public string MetaData { get; set; }
87+
public string Metadata { get; set; }
13488

13589
#region Implementation of the IEnumerable interface
13690

@@ -155,7 +109,7 @@ private IEnumerable<KeyValuePair<string, object>> ForEnumeration
155109
yield return new KeyValuePair<string, object>("IntervalSec", IntervalSec);
156110
yield return new KeyValuePair<string, object>("Series", $"Interval={IntervalSec}");
157111
yield return new KeyValuePair<string, object>("CounterType", "Sum");
158-
yield return new KeyValuePair<string, object>("MetaData", MetaData);
112+
yield return new KeyValuePair<string, object>("Metadata", Metadata);
159113
}
160114
}
161115

src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/BaseCounter.cs renamed to src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/DiagnosticCounter.cs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,34 +19,33 @@ namespace System.Diagnostics.Tracing
1919
#endif
2020
{
2121
/// <summary>
22-
/// BaseCounter is an abstract class that serves as the parent class for various Counter* classes,
22+
/// DiagnosticCounter is an abstract class that serves as the parent class for various Counter* classes,
2323
/// namely EventCounter, PollingCounter, IncrementingEventCounter, and IncrementingPollingCounter.
2424
/// </summary>
25-
public abstract class BaseCounter : IDisposable
25+
public abstract class DiagnosticCounter : IDisposable
2626
{
2727
/// <summary>
2828
/// All Counters live as long as the EventSource that they are attached to unless they are
2929
/// explicitly Disposed.
3030
/// </summary>
3131
/// <param name="name">The name.</param>
3232
/// <param name="eventSource">The event source.</param>
33-
public BaseCounter(string name, EventSource eventSource)
33+
public DiagnosticCounter(string name, EventSource eventSource)
3434
{
3535
if (name == null)
3636
{
37-
throw new ArgumentNullException(nameof(_name));
37+
throw new ArgumentNullException(nameof(Name));
3838
}
3939

4040
if (eventSource == null)
4141
{
42-
throw new ArgumentNullException(nameof(eventSource));
42+
throw new ArgumentNullException(nameof(EventSource));
4343
}
4444

4545
_group = CounterGroup.GetCounterGroup(eventSource);
4646
_group.Add(this);
47-
_eventSource = eventSource;
48-
_name = name;
49-
_metaData = new Dictionary<string, string>();
47+
Name = name;
48+
EventSource = eventSource;
5049
}
5150

5251
/// <summary>
@@ -67,38 +66,45 @@ public void Dispose()
6766
/// <summary>
6867
/// Adds a key-value metadata to the EventCounter that will be included as a part of the payload
6968
/// </summary>
70-
internal void AddMetaData(string key, string value)
69+
public void AddMetadata(string key, string value)
7170
{
7271
lock (MyLock)
7372
{
74-
_metaData.Add(key, value);
73+
_metadata = _metadata ?? new Dictionary<string, string>();
74+
_metadata.Add(key, value);
7575
}
7676
}
7777

78-
internal string DisplayName { get; set; }
78+
public string DisplayName { get; set; }
7979

80-
#region private implementation
80+
public string Name { get; }
81+
82+
public EventSource EventSource { get; }
8183

82-
internal readonly string _name;
84+
#region private implementation
8385

8486
private CounterGroup _group;
85-
private Dictionary<string, string> _metaData;
86-
internal EventSource _eventSource;
87+
private Dictionary<string, string> _metadata;
8788

8889
internal abstract void WritePayload(float intervalSec);
8990

9091
// arbitrarily we use name as the lock object.
91-
internal object MyLock { get { return _name; } }
92+
internal object MyLock { get { return Name; } }
9293

9394
internal void ReportOutOfBandMessage(string message)
9495
{
95-
_eventSource.ReportOutOfBandMessage(message, true);
96+
EventSource.ReportOutOfBandMessage(message, true);
9697
}
9798

98-
internal string GetMetaDataString()
99+
internal string GetMetadataString()
99100
{
101+
if (_metadata == null)
102+
{
103+
return "";
104+
}
105+
100106
StringBuilder sb = new StringBuilder("");
101-
foreach(KeyValuePair<string, string> kvPair in _metaData)
107+
foreach(KeyValuePair<string, string> kvPair in _metadata)
102108
{
103109
sb.Append($"{kvPair.Key}:{kvPair.Value},");
104110
}

src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventCounter.cs

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace System.Diagnostics.Tracing
2626
/// See https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestEventCounter.cs
2727
/// which shows tests, which are also useful in seeing actual use.
2828
/// </summary>
29-
public partial class EventCounter : BaseCounter
29+
public partial class EventCounter : DiagnosticCounter
3030
{
3131
/// <summary>
3232
/// Initializes a new instance of the <see cref="EventCounter"/> class.
@@ -37,8 +37,8 @@ public partial class EventCounter : BaseCounter
3737
/// <param name="eventSource">The event source.</param>
3838
public EventCounter(string name, EventSource eventSource) : base(name, eventSource)
3939
{
40-
_min = float.PositiveInfinity;
41-
_max = float.NegativeInfinity;
40+
_min = double.PositiveInfinity;
41+
_max = double.NegativeInfinity;
4242

4343
InitializeBuffer();
4444
}
@@ -49,22 +49,27 @@ public EventCounter(string name, EventSource eventSource) : base(name, eventSour
4949
/// </summary>
5050
/// <param name="value">The value.</param>
5151
public void WriteMetric(float value)
52+
{
53+
Enqueue((double)value);
54+
}
55+
56+
public void WriteMetric(double value)
5257
{
5358
Enqueue(value);
5459
}
5560

56-
public override string ToString() => $"EventCounter '{_name}' Count {_count} Mean {(((double)_sum) / _count).ToString("n3")}";
61+
public override string ToString() => $"EventCounter '{Name}' Count {_count} Mean {(_sum / _count).ToString("n3")}";
5762

5863
#region Statistics Calculation
5964

6065
// Statistics
6166
private int _count;
62-
private float _sum;
63-
private float _sumSquared;
64-
private float _min;
65-
private float _max;
67+
private double _sum;
68+
private double _sumSquared;
69+
private double _min;
70+
private double _max;
6671

67-
internal void OnMetricWritten(float value)
72+
internal void OnMetricWritten(double value)
6873
{
6974
Debug.Assert(Monitor.IsEntered(MyLock));
7075
_sum += value;
@@ -83,14 +88,13 @@ internal override void WritePayload(float intervalSec)
8388
lock (MyLock)
8489
{
8590
Flush();
86-
EventCounterPayload payload = new EventCounterPayload();
87-
payload.Name = _name;
91+
CounterPayload payload = new CounterPayload();
8892
payload.Count = _count;
8993
payload.IntervalSec = intervalSec;
9094
if (0 < _count)
9195
{
9296
payload.Mean = _sum / _count;
93-
payload.StandardDeviation = (float)Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
97+
payload.StandardDeviation = Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
9498
}
9599
else
96100
{
@@ -99,8 +103,12 @@ internal override void WritePayload(float intervalSec)
99103
}
100104
payload.Min = _min;
101105
payload.Max = _max;
106+
107+
payload.Metadata = GetMetadataString();
108+
payload.DisplayName = DisplayName;
109+
payload.Name = Name;
102110
ResetStatistics();
103-
_eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new EventCounterPayloadType(payload));
111+
EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new CounterPayloadType(payload));
104112
}
105113
}
106114
private void ResetStatistics()
@@ -109,35 +117,35 @@ private void ResetStatistics()
109117
_count = 0;
110118
_sum = 0;
111119
_sumSquared = 0;
112-
_min = float.PositiveInfinity;
113-
_max = float.NegativeInfinity;
120+
_min = double.PositiveInfinity;
121+
_max = double.NegativeInfinity;
114122
}
115123

116124
#endregion // Statistics Calculation
117125

118126
// Values buffering
119127
private const int BufferedSize = 10;
120-
private const float UnusedBufferSlotValue = float.NegativeInfinity;
128+
private const double UnusedBufferSlotValue = double.NegativeInfinity;
121129
private const int UnsetIndex = -1;
122-
private volatile float[] _bufferedValues;
130+
private volatile double[] _bufferedValues;
123131
private volatile int _bufferedValuesIndex;
124132

125133
private void InitializeBuffer()
126134
{
127-
_bufferedValues = new float[BufferedSize];
135+
_bufferedValues = new double[BufferedSize];
128136
for (int i = 0; i < _bufferedValues.Length; i++)
129137
{
130138
_bufferedValues[i] = UnusedBufferSlotValue;
131139
}
132140
}
133141

134-
protected void Enqueue(float value)
142+
private void Enqueue(double value)
135143
{
136144
// It is possible that two threads read the same bufferedValuesIndex, but only one will be able to write the slot, so that is okay.
137145
int i = _bufferedValuesIndex;
138146
while (true)
139147
{
140-
float result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue);
148+
double result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue);
141149
i++;
142150
if (_bufferedValues.Length <= i)
143151
{
@@ -178,10 +186,10 @@ protected void Flush()
178186
/// This is the payload that is sent in the with EventSource.Write
179187
/// </summary>
180188
[EventData]
181-
class EventCounterPayloadType
189+
class CounterPayloadType
182190
{
183-
public EventCounterPayloadType(EventCounterPayload payload) { Payload = payload; }
184-
public EventCounterPayload Payload { get; set; }
191+
public CounterPayloadType(CounterPayload payload) { Payload = payload; }
192+
public CounterPayload Payload { get; set; }
185193
}
186194

187195
}

0 commit comments

Comments
 (0)