Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ public GaugePayload(string providerName, string name, string displayName, string
}
}

internal class UpDownCounterPayload : CounterPayload
{
public UpDownCounterPayload(string providerName, string name, string displayName, string displayUnits, string metadata, double value, DateTime timestamp) :
base(providerName, name, metadata, value, timestamp, "Metric", EventType.UpDownCounter)
{
// In case these properties are not provided, set them to appropriate values.
string counterName = string.IsNullOrEmpty(displayName) ? name : displayName;
DisplayName = !string.IsNullOrEmpty(displayUnits) ? $"{counterName} ({displayUnits})" : counterName;
}
}

internal class CounterEndedPayload : CounterPayload
{
public CounterEndedPayload(string providerName, string name, DateTime timestamp)
Expand Down Expand Up @@ -144,6 +155,7 @@ internal enum EventType : int
Rate,
Gauge,
Histogram,
UpDownCounter,
Error,
CounterEnded
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ public static bool TryGetCounterPayload(this TraceEvent traceEvent, CounterFilte
{
HandleCounterRate(traceEvent, filter, sessionId, out payload);
}
else if (traceEvent.EventName == "UpDownCounterRateValuePublished")
{
HandleUpDownCounterValue(traceEvent, filter, sessionId, out payload);
}
else if (traceEvent.EventName == "TimeSeriesLimitReached")
{
HandleTimeSeriesLimitReached(traceEvent, sessionId, out payload);
Expand Down Expand Up @@ -188,6 +192,44 @@ private static void HandleCounterRate(TraceEvent traceEvent, CounterFilter filte
}
}

private static void HandleUpDownCounterValue(TraceEvent traceEvent, CounterFilter filter, string sessionId, out ICounterPayload payload)
{
payload = null;

string payloadSessionId = (string)traceEvent.PayloadValue(0);

if (payloadSessionId != sessionId || traceEvent.Version < 1) // Version 1 added the value field.
{
return;
}

string meterName = (string)traceEvent.PayloadValue(1);
//string meterVersion = (string)obj.PayloadValue(2);
string instrumentName = (string)traceEvent.PayloadValue(3);
string unit = (string)traceEvent.PayloadValue(4);
string tags = (string)traceEvent.PayloadValue(5);
_ = (string)traceEvent.PayloadValue(6); // Not currently using rate for UpDownCounters.
string valueText = (string)traceEvent.PayloadValue(7);

if (!filter.IsIncluded(meterName, instrumentName))
{
return;
}

if (double.TryParse(valueText, NumberStyles.Number | NumberStyles.Float, CultureInfo.InvariantCulture, out double value))
{
// UpDownCounter reports the value, not the rate - this is different than how Counter behaves.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you think dotnet-monitor would be improved by reporting the value rather than rate for Counter I'd say go for it (in a different PR). There might be compat issues to contend with, but over time my perspective has been shifting towards rate being useful for Counter UI visualization for users, but at every stage prior to that point the absolute counter value appears easier to work with.

payload = new UpDownCounterPayload(meterName, instrumentName, null, unit, tags, value, traceEvent.TimeStamp);

}
else
{
// for observable instruments we assume the lack of data is meaningful and remove it from the UI
// this happens when the ObservableUpDownCounter callback function throws an exception.
payload = new CounterEndedPayload(meterName, instrumentName, traceEvent.TimeStamp);
}
}

private static void HandleHistogram(TraceEvent obj, CounterFilter filter, string sessionId, out ICounterPayload payload)
{
payload = null;
Expand Down
40 changes: 40 additions & 0 deletions src/Tools/dotnet-counters/CounterMonitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ private void DynamicAllMonitor(TraceEvent obj)
{
HandleCounterRate(obj);
}
else if (obj.EventName == "UpDownCounterRateValuePublished")
{
HandleUpDownCounterValue(obj);
}
else if (obj.EventName == "TimeSeriesLimitReached")
{
HandleTimeSeriesLimitReached(obj);
Expand Down Expand Up @@ -198,6 +202,42 @@ private void HandleGauge(TraceEvent obj)
}
}

private void HandleUpDownCounterValue(TraceEvent obj)
{
if (obj.Version < 1) // Version 1 added the value field.
{
return;
}

string sessionId = (string)obj.PayloadValue(0);
string meterName = (string)obj.PayloadValue(1);
//string meterVersion = (string)obj.PayloadValue(2);
string instrumentName = (string)obj.PayloadValue(3);
string unit = (string)obj.PayloadValue(4);
string tags = (string)obj.PayloadValue(5);
_ = (string)obj.PayloadValue(6); // Not currently using rate for UpDownCounters.
string valueText = (string)obj.PayloadValue(7);
if (sessionId != _metricsEventSourceSessionId)
{
return;
}
MeterInstrumentEventObserved(meterName, obj.TimeStamp);

// the value might be an empty string indicating no measurement was provided this collection interval
if (double.TryParse(valueText, NumberStyles.Number | NumberStyles.Float, CultureInfo.InvariantCulture, out double value))
{
// UpDownCounter reports the value, not the rate - this is different than how Counter behaves, and is thus treated as a gauge.
CounterPayload payload = new GaugePayload(meterName, instrumentName, null, unit, tags, value, obj.TimeStamp);
_renderer.CounterPayloadReceived(payload, _pauseCmdSet);
}
else
{
// for observable instruments we assume the lack of data is meaningful and remove it from the UI
CounterPayload payload = new RatePayload(meterName, instrumentName, null, unit, tags, 0, _interval, obj.TimeStamp);
_renderer.CounterStopped(payload);
}
}

private void HandleHistogram(TraceEvent obj)
{
string sessionId = (string)obj.PayloadValue(0);
Expand Down