public static bool TryGetCounterPayload(this TraceEvent traceEvent, CounterFilter filter, out ICounterPayload payload) { payload = null; if ("EventCounters".Equals(traceEvent.EventName)) { IDictionary <string, object> payloadVal = (IDictionary <string, object>)(traceEvent.PayloadValue(0)); IDictionary <string, object> payloadFields = (IDictionary <string, object>)(payloadVal["Payload"]); //Make sure we are part of the requested series. If multiple clients request metrics, all of them get the metrics. string series = payloadFields["Series"].ToString(); string counterName = payloadFields["Name"].ToString(); //CONSIDER //Concurrent counter sessions do not each get a separate interval. Instead the payload //for _all_ the counters changes the Series to be the lowest specified interval, on a per provider basis. //Currently the CounterFilter will remove any data whose Series doesn't match the requested interval. if (!filter.IsIncluded(traceEvent.ProviderName, counterName, GetInterval(series))) { return(false); } float intervalSec = (float)payloadFields["IntervalSec"]; string displayName = payloadFields["DisplayName"].ToString(); string displayUnits = payloadFields["DisplayUnits"].ToString(); double value = 0; CounterType counterType = CounterType.Metric; if (payloadFields["CounterType"].Equals("Mean")) { value = (double)payloadFields["Mean"]; } else if (payloadFields["CounterType"].Equals("Sum")) { counterType = CounterType.Rate; value = (double)payloadFields["Increment"]; if (string.IsNullOrEmpty(displayUnits)) { displayUnits = "count"; } //TODO Should we make these /sec like the dotnet-counters tool? } // Note that dimensional data such as pod and namespace are automatically added in prometheus and azure monitor scenarios. // We no longer added it here. payload = new CounterPayload( traceEvent.TimeStamp, traceEvent.ProviderName, counterName, displayName, displayUnits, value, counterType, intervalSec); return(true); } return(false); }
private void HandleEventCounters(EventPipeEventSource source) { ExecuteCounterLoggerAction((metricLogger) => metricLogger.PipelineStarted()); source.Dynamic.All += traceEvent => { try { // Metrics if (traceEvent.EventName.Equals("EventCounters")) { IDictionary <string, object> payloadVal = (IDictionary <string, object>)(traceEvent.PayloadValue(0)); IDictionary <string, object> payloadFields = (IDictionary <string, object>)(payloadVal["Payload"]); //Make sure we are part of the requested series. If multiple clients request metrics, all of them get the metrics. string series = payloadFields["Series"].ToString(); if (GetInterval(series) != _metricIntervalSeconds * 1000) { return; } string counterName = payloadFields["Name"].ToString(); if (!_counterFilter.IsIncluded(traceEvent.ProviderName, counterName)) { return; } float intervalSec = (float)payloadFields["IntervalSec"]; string displayName = payloadFields["DisplayName"].ToString(); string displayUnits = payloadFields["DisplayUnits"].ToString(); double value = 0; CounterType counterType = CounterType.Metric; if (payloadFields["CounterType"].Equals("Mean")) { value = (double)payloadFields["Mean"]; } else if (payloadFields["CounterType"].Equals("Sum")) { counterType = CounterType.Rate; value = (double)payloadFields["Increment"]; if (string.IsNullOrEmpty(displayUnits)) { displayUnits = "count"; } //TODO Should we make these /sec like the dotnet-counters tool? } // Note that dimensional data such as pod and namespace are automatically added in prometheus and azure monitor scenarios. // We no longer added it here. var counterPayload = new CounterPayload(traceEvent.TimeStamp, traceEvent.ProviderName, counterName, displayName, displayUnits, value, counterType, intervalSec); ExecuteCounterLoggerAction((metricLogger) => metricLogger.Log(counterPayload)); } } catch (Exception) { } }; }
protected override async Task OnEventSourceAvailable(EventPipeEventSource eventSource, Func <Task> stopSessionAsync, CancellationToken token) { ExecuteCounterLoggerAction((metricLogger) => metricLogger.PipelineStarted()); eventSource.Dynamic.All += traceEvent => { try { // Metrics if (traceEvent.EventName.Equals("EventCounters")) { IDictionary <string, object> payloadVal = (IDictionary <string, object>)(traceEvent.PayloadValue(0)); IDictionary <string, object> payloadFields = (IDictionary <string, object>)(payloadVal["Payload"]); //Make sure we are part of the requested series. If multiple clients request metrics, all of them get the metrics. string series = payloadFields["Series"].ToString(); if (GetInterval(series) != CounterIntervalSeconds * 1000) { return; } string counterName = payloadFields["Name"].ToString(); if (!_filter.IsIncluded(traceEvent.ProviderName, counterName)) { return; } float intervalSec = (float)payloadFields["IntervalSec"]; string displayName = payloadFields["DisplayName"].ToString(); string displayUnits = payloadFields["DisplayUnits"].ToString(); double value = 0; CounterType counterType = CounterType.Metric; if (payloadFields["CounterType"].Equals("Mean")) { value = (double)payloadFields["Mean"]; } else if (payloadFields["CounterType"].Equals("Sum")) { counterType = CounterType.Rate; value = (double)payloadFields["Increment"]; if (string.IsNullOrEmpty(displayUnits)) { displayUnits = "count"; } //TODO Should we make these /sec like the dotnet-counters tool? } // Note that dimensional data such as pod and namespace are automatically added in prometheus and azure monitor scenarios. // We no longer added it here. var counterPayload = new CounterPayload(traceEvent.TimeStamp, traceEvent.ProviderName, counterName, displayName, displayUnits, value, counterType, intervalSec); ExecuteCounterLoggerAction((metricLogger) => metricLogger.Log(counterPayload)); } } catch (Exception) { } }; using var sourceCompletedTaskSource = new EventTaskSource <Action>( taskComplete => taskComplete, handler => eventSource.Completed += handler, handler => eventSource.Completed -= handler, token); await sourceCompletedTaskSource.Task; ExecuteCounterLoggerAction((metricLogger) => metricLogger.PipelineStopped()); }