</ItemGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\ActivityTracker.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\BaseCounter.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\DiagnosticCounter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\CounterGroup.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\CounterPayload.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\EventActivityOptions.cs" />
internal class CounterGroup
{
private readonly EventSource _eventSource;
- private readonly List<BaseCounter> _counters;
+ private readonly List<DiagnosticCounter> _counters;
internal CounterGroup(EventSource eventSource)
{
_eventSource = eventSource;
- _counters = new List<BaseCounter>();
+ _counters = new List<DiagnosticCounter>();
RegisterCommandCallback();
}
- internal void Add(BaseCounter eventCounter)
+ internal void Add(DiagnosticCounter eventCounter)
{
lock (this) // Lock the CounterGroup
_counters.Add(eventCounter);
}
- internal void Remove(BaseCounter eventCounter)
+ internal void Remove(DiagnosticCounter eventCounter)
{
lock (this) // Lock the CounterGroup
_counters.Remove(eventCounter);
namespace System.Diagnostics.Tracing
#endif
{
- // TODO: This should be removed as we make the new payloads public
- [EventData]
- internal class EventCounterPayload : IEnumerable<KeyValuePair<string, object>>
- {
- public string Name { get; set; }
-
- public float Mean { get; set; }
-
- public float StandardDeviation { get; set; }
-
- public int Count { get; set; }
-
- public float Min { get; set; }
-
- public float Max { get; set; }
-
- public float IntervalSec { get; internal set; }
-
- #region Implementation of the IEnumerable interface
-
- public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
- {
- return ForEnumeration.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ForEnumeration.GetEnumerator();
- }
-
- private IEnumerable<KeyValuePair<string, object>> ForEnumeration
- {
- get
- {
- yield return new KeyValuePair<string, object>("Name", Name);
- yield return new KeyValuePair<string, object>("Mean", Mean);
- yield return new KeyValuePair<string, object>("StandardDeviation", StandardDeviation);
- yield return new KeyValuePair<string, object>("Count", Count);
- yield return new KeyValuePair<string, object>("Min", Min);
- yield return new KeyValuePair<string, object>("Max", Max);
- }
- }
-
- #endregion // Implementation of the IEnumerable interface
- }
-
[EventData]
internal class CounterPayload : IEnumerable<KeyValuePair<string, object>>
{
public string DisplayName { get; set; }
- public float Mean { get; set; }
+ public double Mean { get; set; }
- public float StandardDeviation { get; set; }
+ public double StandardDeviation { get; set; }
public int Count { get; set; }
- public float Min { get; set; }
+ public double Min { get; set; }
- public float Max { get; set; }
+ public double Max { get; set; }
public float IntervalSec { get; internal set; }
- public string MetaData { get; set; }
+ public string Metadata { get; set; }
#region Implementation of the IEnumerable interface
yield return new KeyValuePair<string, object>("IntervalSec", IntervalSec);
yield return new KeyValuePair<string, object>("Series", $"Interval={IntervalSec}");
yield return new KeyValuePair<string, object>("CounterType", "Mean");
- yield return new KeyValuePair<string, object>("MetaData", MetaData);
+ yield return new KeyValuePair<string, object>("Metadata", Metadata);
}
}
public string DisplayRateTimeScale { get; set; }
- public float Increment { get; set; }
+ public double Increment { get; set; }
public float IntervalSec { get; internal set; }
- public string MetaData { get; set; }
+ public string Metadata { get; set; }
#region Implementation of the IEnumerable interface
yield return new KeyValuePair<string, object>("IntervalSec", IntervalSec);
yield return new KeyValuePair<string, object>("Series", $"Interval={IntervalSec}");
yield return new KeyValuePair<string, object>("CounterType", "Sum");
- yield return new KeyValuePair<string, object>("MetaData", MetaData);
+ yield return new KeyValuePair<string, object>("Metadata", Metadata);
}
}
#endif
{
/// <summary>
- /// BaseCounter is an abstract class that serves as the parent class for various Counter* classes,
+ /// DiagnosticCounter is an abstract class that serves as the parent class for various Counter* classes,
/// namely EventCounter, PollingCounter, IncrementingEventCounter, and IncrementingPollingCounter.
/// </summary>
- public abstract class BaseCounter : IDisposable
+ public abstract class DiagnosticCounter : IDisposable
{
/// <summary>
/// All Counters live as long as the EventSource that they are attached to unless they are
/// </summary>
/// <param name="name">The name.</param>
/// <param name="eventSource">The event source.</param>
- public BaseCounter(string name, EventSource eventSource)
+ public DiagnosticCounter(string name, EventSource eventSource)
{
if (name == null)
{
- throw new ArgumentNullException(nameof(_name));
+ throw new ArgumentNullException(nameof(Name));
}
if (eventSource == null)
{
- throw new ArgumentNullException(nameof(eventSource));
+ throw new ArgumentNullException(nameof(EventSource));
}
_group = CounterGroup.GetCounterGroup(eventSource);
_group.Add(this);
- _eventSource = eventSource;
- _name = name;
- _metaData = new Dictionary<string, string>();
+ Name = name;
+ EventSource = eventSource;
}
/// <summary>
/// <summary>
/// Adds a key-value metadata to the EventCounter that will be included as a part of the payload
/// </summary>
- internal void AddMetaData(string key, string value)
+ public void AddMetadata(string key, string value)
{
lock (MyLock)
{
- _metaData.Add(key, value);
+ _metadata = _metadata ?? new Dictionary<string, string>();
+ _metadata.Add(key, value);
}
}
- internal string DisplayName { get; set; }
+ public string DisplayName { get; set; }
- #region private implementation
+ public string Name { get; }
+
+ public EventSource EventSource { get; }
- internal readonly string _name;
+ #region private implementation
private CounterGroup _group;
- private Dictionary<string, string> _metaData;
- internal EventSource _eventSource;
+ private Dictionary<string, string> _metadata;
internal abstract void WritePayload(float intervalSec);
// arbitrarily we use name as the lock object.
- internal object MyLock { get { return _name; } }
+ internal object MyLock { get { return Name; } }
internal void ReportOutOfBandMessage(string message)
{
- _eventSource.ReportOutOfBandMessage(message, true);
+ EventSource.ReportOutOfBandMessage(message, true);
}
- internal string GetMetaDataString()
+ internal string GetMetadataString()
{
+ if (_metadata == null)
+ {
+ return "";
+ }
+
StringBuilder sb = new StringBuilder("");
- foreach(KeyValuePair<string, string> kvPair in _metaData)
+ foreach(KeyValuePair<string, string> kvPair in _metadata)
{
sb.Append($"{kvPair.Key}:{kvPair.Value},");
}
/// See https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestEventCounter.cs
/// which shows tests, which are also useful in seeing actual use.
/// </summary>
- public partial class EventCounter : BaseCounter
+ public partial class EventCounter : DiagnosticCounter
{
/// <summary>
/// Initializes a new instance of the <see cref="EventCounter"/> class.
/// <param name="eventSource">The event source.</param>
public EventCounter(string name, EventSource eventSource) : base(name, eventSource)
{
- _min = float.PositiveInfinity;
- _max = float.NegativeInfinity;
+ _min = double.PositiveInfinity;
+ _max = double.NegativeInfinity;
InitializeBuffer();
}
/// <param name="value">The value.</param>
public void WriteMetric(float value)
{
+ Enqueue((double)value);
+ }
+
+ public void WriteMetric(double value)
+ {
Enqueue(value);
}
- public override string ToString() => $"EventCounter '{_name}' Count {_count} Mean {(((double)_sum) / _count).ToString("n3")}";
+ public override string ToString() => $"EventCounter '{Name}' Count {_count} Mean {(_sum / _count).ToString("n3")}";
#region Statistics Calculation
// Statistics
private int _count;
- private float _sum;
- private float _sumSquared;
- private float _min;
- private float _max;
+ private double _sum;
+ private double _sumSquared;
+ private double _min;
+ private double _max;
- internal void OnMetricWritten(float value)
+ internal void OnMetricWritten(double value)
{
Debug.Assert(Monitor.IsEntered(MyLock));
_sum += value;
lock (MyLock)
{
Flush();
- EventCounterPayload payload = new EventCounterPayload();
- payload.Name = _name;
+ CounterPayload payload = new CounterPayload();
payload.Count = _count;
payload.IntervalSec = intervalSec;
if (0 < _count)
{
payload.Mean = _sum / _count;
- payload.StandardDeviation = (float)Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
+ payload.StandardDeviation = Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
}
else
{
}
payload.Min = _min;
payload.Max = _max;
+
+ payload.Metadata = GetMetadataString();
+ payload.DisplayName = DisplayName;
+ payload.Name = Name;
ResetStatistics();
- _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new EventCounterPayloadType(payload));
+ EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new CounterPayloadType(payload));
}
}
private void ResetStatistics()
_count = 0;
_sum = 0;
_sumSquared = 0;
- _min = float.PositiveInfinity;
- _max = float.NegativeInfinity;
+ _min = double.PositiveInfinity;
+ _max = double.NegativeInfinity;
}
#endregion // Statistics Calculation
// Values buffering
private const int BufferedSize = 10;
- private const float UnusedBufferSlotValue = float.NegativeInfinity;
+ private const double UnusedBufferSlotValue = double.NegativeInfinity;
private const int UnsetIndex = -1;
- private volatile float[] _bufferedValues;
+ private volatile double[] _bufferedValues;
private volatile int _bufferedValuesIndex;
private void InitializeBuffer()
{
- _bufferedValues = new float[BufferedSize];
+ _bufferedValues = new double[BufferedSize];
for (int i = 0; i < _bufferedValues.Length; i++)
{
_bufferedValues[i] = UnusedBufferSlotValue;
}
}
- protected void Enqueue(float value)
+ private void Enqueue(double value)
{
// It is possible that two threads read the same bufferedValuesIndex, but only one will be able to write the slot, so that is okay.
int i = _bufferedValuesIndex;
while (true)
{
- float result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue);
+ double result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue);
i++;
if (_bufferedValues.Length <= i)
{
/// This is the payload that is sent in the with EventSource.Write
/// </summary>
[EventData]
- class EventCounterPayloadType
+ class CounterPayloadType
{
- public EventCounterPayloadType(EventCounterPayload payload) { Payload = payload; }
- public EventCounterPayload Payload { get; set; }
+ public CounterPayloadType(CounterPayload payload) { Payload = payload; }
+ public CounterPayload Payload { get; set; }
}
}
/// It does not calculate statistics like mean, standard deviation, etc. because it only accumulates
/// the counter value.
/// </summary>
- internal partial class IncrementingEventCounter : BaseCounter
+ public partial class IncrementingEventCounter : DiagnosticCounter
{
/// <summary>
/// Initializes a new instance of the <see cref="IncrementingEventCounter"/> class.
/// be logged on the next timer interval.
/// </summary>
/// <param name="increment">The value to increment by.</param>
- public void Increment(float increment = 1)
+ public void Increment(double increment = 1)
{
lock(MyLock)
{
}
}
- internal TimeSpan DisplayRateTimeScale { get; set; }
- private float _increment;
- private float _prevIncrement;
+ public TimeSpan DisplayRateTimeScale { get; set; }
+ private double _increment;
+ private double _prevIncrement;
- public override string ToString() => $"IncrementingEventCounter '{_name}' Increment {_increment}";
+ public override string ToString() => $"IncrementingEventCounter '{Name}' Increment {_increment}";
internal override void WritePayload(float intervalSec)
{
lock (MyLock) // Lock the counter
{
IncrementingCounterPayload payload = new IncrementingCounterPayload();
- payload.Name = _name;
+ payload.Name = Name;
payload.IntervalSec = intervalSec;
payload.DisplayName = DisplayName ?? "";
payload.DisplayRateTimeScale = (DisplayRateTimeScale == TimeSpan.Zero) ? "" : DisplayRateTimeScale.ToString("c");
- payload.MetaData = GetMetaDataString();
+ payload.Metadata = GetMetadataString();
payload.Increment = _increment - _prevIncrement;
_prevIncrement = _increment;
- _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingEventCounterPayloadType(payload));
+ EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingEventCounterPayloadType(payload));
}
}
}
/// Unlike IncrementingEventCounter, this takes in a polling callback that it can call to update
/// its own metric periodically.
/// </summary>
- internal partial class IncrementingPollingCounter : BaseCounter
+ public partial class IncrementingPollingCounter : DiagnosticCounter
{
/// <summary>
/// Initializes a new instance of the <see cref="IncrementingPollingCounter"/> class.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="eventSource">The event source.</param>
- public IncrementingPollingCounter(string name, EventSource eventSource, Func<float> getCountFunction) : base(name, eventSource)
+ public IncrementingPollingCounter(string name, EventSource eventSource, Func<double> totalValueProvider) : base(name, eventSource)
{
- _getCountFunction = getCountFunction;
+ _totalValueProvider = totalValueProvider;
}
- public override string ToString() => $"IncrementingPollingCounter '{_name}' Increment {_increment}";
+ public override string ToString() => $"IncrementingPollingCounter '{Name}' Increment {_increment}";
- internal TimeSpan DisplayRateTimeScale { get; set; }
- private float _increment;
- private float _prevIncrement;
- private Func<float> _getCountFunction;
+ public TimeSpan DisplayRateTimeScale { get; set; }
+ private double _increment;
+ private double _prevIncrement;
+ private Func<double> _totalValueProvider;
/// <summary>
- /// Calls "_getCountFunction" to enqueue the counter value to the queue.
+ /// Calls "_totalValueProvider" to enqueue the counter value to the queue.
/// </summary>
private void UpdateMetric()
{
{
lock(MyLock)
{
- _increment = _getCountFunction();
+ _increment = _totalValueProvider();
}
}
catch (Exception ex)
{
- ReportOutOfBandMessage($"ERROR: Exception during EventCounter {_name} getMetricFunction callback: " + ex.Message);
+ ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} getMetricFunction callback: " + ex.Message);
}
}
lock (MyLock) // Lock the counter
{
IncrementingCounterPayload payload = new IncrementingCounterPayload();
- payload.Name = _name;
+ payload.Name = Name;
payload.DisplayName = DisplayName ?? "";
payload.DisplayRateTimeScale = (DisplayRateTimeScale == TimeSpan.Zero) ? "" : DisplayRateTimeScale.ToString("c");
payload.IntervalSec = intervalSec;
- payload.MetaData = GetMetaDataString();
+ payload.Metadata = GetMetadataString();
payload.Increment = _increment - _prevIncrement;
_prevIncrement = _increment;
- _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingPollingCounterPayloadType(payload));
+ EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingPollingCounterPayloadType(payload));
}
}
}
/// function to collect metrics on its own rather than the user having to call WriteMetric()
/// every time.
/// </summary>
- internal partial class PollingCounter : BaseCounter
+ public partial class PollingCounter : DiagnosticCounter
{
/// <summary>
/// Initializes a new instance of the <see cref="PollingCounter"/> class.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="eventSource">The event source.</param>
- public PollingCounter(string name, EventSource eventSource, Func<float> getMetricFunction) : base(name, eventSource)
+ public PollingCounter(string name, EventSource eventSource, Func<double> metricProvider) : base(name, eventSource)
{
- _getMetricFunction = getMetricFunction;
+ _metricProvider = metricProvider;
}
- public override string ToString() => $"PollingCounter '{_name}' Count {1} Mean {_lastVal.ToString("n3")}";
+ public override string ToString() => $"PollingCounter '{Name}' Count {1} Mean {_lastVal.ToString("n3")}";
- private Func<float> _getMetricFunction;
- private float _lastVal;
+ private Func<double> _metricProvider;
+ private double _lastVal;
internal override void WritePayload(float intervalSec)
{
lock (MyLock)
{
- float value = 0;
+ double value = 0;
try
{
- value = _getMetricFunction();
+ value = _metricProvider();
}
catch (Exception ex)
{
- ReportOutOfBandMessage($"ERROR: Exception during EventCounter {_name} getMetricFunction callback: " + ex.Message);
+ ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} metricProvider callback: " + ex.Message);
}
CounterPayload payload = new CounterPayload();
- payload.Name = _name;
+ payload.Name = Name;
payload.DisplayName = DisplayName ?? "";
payload.Count = 1; // NOTE: These dumb-looking statistics is intentional
payload.IntervalSec = intervalSec;
payload.Mean = value;
payload.Max = value;
payload.Min = value;
+ payload.Metadata = GetMetadataString();
payload.StandardDeviation = 0;
_lastVal = value;
- _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new PollingPayloadType(payload));
+ EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new PollingPayloadType(payload));
}
}
}
{
private object _failureCounter;
- public SimpleEventSource(Func<float> getFailureCount, Type IncrementingPollingCounterType)
+ public SimpleEventSource(Func<double> getFailureCount, Type IncrementingPollingCounterType)
{
_failureCounter = Activator.CreateInstance(IncrementingPollingCounterType, "failureCount", this, getFailureCount);
}
public static int failureCountCalled = 0;
- public static float getFailureCount()
+ public static double getFailureCount()
{
failureCountCalled++;
return failureCountCalled;
private object _failureCounter;
private object _successCounter;
- public SimpleEventSource(Func<float> getFailureCount, Func<float> getSuccessCount, Type PollingCounterType)
+ public SimpleEventSource(Func<double> getFailureCount, Func<double> getSuccessCount, Type PollingCounterType)
{
_failureCounter = Activator.CreateInstance(PollingCounterType, "failureCount", this, getSuccessCount);
_successCounter = Activator.CreateInstance(PollingCounterType, "successCount", this, getFailureCount);
public static int failureCountCalled = 0;
public static int successCountCalled = 0;
- public static float getFailureCount()
+ public static double getFailureCount()
{
failureCountCalled++;
return failureCountCalled;
}
- public static float getSuccessCount()
+ public static double getSuccessCount()
{
successCountCalled++;
return successCountCalled;