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.
5 #if ES_BUILD_STANDALONE
9 #if ES_BUILD_STANDALONE
10 namespace Microsoft
.Diagnostics
.Tracing
12 namespace System
.Diagnostics
.Tracing
16 /// IncrementingPollingCounter is a variant of EventCounter for variables that are ever-increasing.
17 /// Ex) # of exceptions in the runtime.
18 /// It does not calculate statistics like mean, standard deviation, etc. because it only accumulates
19 /// the counter value.
20 /// Unlike IncrementingEventCounter, this takes in a polling callback that it can call to update
21 /// its own metric periodically.
23 public partial class IncrementingPollingCounter
: DiagnosticCounter
26 /// Initializes a new instance of the <see cref="IncrementingPollingCounter"/> class.
27 /// IncrementingPollingCounter live as long as the EventSource that they are attached to unless they are
28 /// explicitly Disposed.
30 /// <param name="name">The name.</param>
31 /// <param name="eventSource">The event source.</param>
32 public IncrementingPollingCounter(string name
, EventSource eventSource
, Func
<double> totalValueProvider
) : base(name
, eventSource
)
34 if (totalValueProvider
== null)
35 throw new ArgumentNullException(nameof(totalValueProvider
));
37 _totalValueProvider
= totalValueProvider
;
41 public override string ToString() => $"IncrementingPollingCounter '{Name}' Increment {_increment}";
43 public TimeSpan DisplayRateTimeScale { get; set; }
44 private double _increment
;
45 private double _prevIncrement
;
46 private readonly Func
<double> _totalValueProvider
;
49 /// Calls "_totalValueProvider" to enqueue the counter value to the queue.
51 internal void UpdateMetric()
57 _prevIncrement
= _increment
;
58 _increment
= _totalValueProvider();
63 ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} getMetricFunction callback: " + ex
.Message
);
67 internal override void WritePayload(float intervalSec
, int pollingIntervalMillisec
)
70 lock (this) // Lock the counter
72 IncrementingCounterPayload payload
= new IncrementingCounterPayload();
74 payload
.DisplayName
= DisplayName
?? "";
75 payload
.DisplayRateTimeScale
= (DisplayRateTimeScale
== TimeSpan
.Zero
) ? "" : DisplayRateTimeScale
.ToString("c");
76 payload
.IntervalSec
= intervalSec
;
77 payload
.Series
= $"Interval={pollingIntervalMillisec}"; // TODO: This may need to change when we support multi-session
78 payload
.CounterType
= "Sum";
79 payload
.Metadata
= GetMetadataString();
80 payload
.Increment
= _increment
- _prevIncrement
;
81 payload
.DisplayUnits
= DisplayUnits
?? "";
82 EventSource
.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }
, new IncrementingPollingCounterPayloadType(payload
));
88 /// This is the payload that is sent in the with EventSource.Write
91 internal class IncrementingPollingCounterPayloadType
93 public IncrementingPollingCounterPayloadType(IncrementingCounterPayload payload
) { Payload = payload; }
94 public IncrementingCounterPayload Payload { get; set; }