| File: src\runtime\src\libraries\System.Private.CoreLib\src\System\Diagnostics\Tracing\PollingCounter.cs | Web Access |
| Project: System.Private.CoreLib.csproj (System.Private.CoreLib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; using System.Runtime.Versioning; namespace System.Diagnostics.Tracing { /// <summary> /// PollingCounter is a variant of EventCounter - it collects and calculates similar statistics /// as EventCounter. PollingCounter differs from EventCounter in that it takes in a callback /// function to collect metrics on its own rather than the user having to call WriteMetric() /// every time. /// </summary> #if !ES_BUILD_STANDALONE [UnsupportedOSPlatform("browser")] #endif public partial class PollingCounter : DiagnosticCounter { /// <summary> /// Initializes a new instance of the <see cref="PollingCounter"/> class. /// PollingCounter live as long as the EventSource that they are attached to unless they are /// explicitly Disposed. /// </summary> /// <param name="name">The name.</param> /// <param name="eventSource">The event source.</param> /// <param name="metricProvider">The delegate to invoke to get the current metric value.</param> public PollingCounter(string name, EventSource eventSource, Func<double> metricProvider) : base(name, eventSource) { ArgumentNullException.ThrowIfNull(metricProvider); _metricProvider = metricProvider; Publish(); } public override string ToString() => $"PollingCounter '{Name}' Count 1 Mean {_lastVal:n3}"; private readonly Func<double> _metricProvider; private double _lastVal; [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The DynamicDependency will preserve the properties of CounterPayload")] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(CounterPayload))] internal override void WritePayload(float intervalSec, int pollingIntervalMillisec) { lock (this) { double value = 0; try { value = _metricProvider(); } catch (Exception ex) { ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} metricProvider callback: " + ex.Message); } CounterPayload payload = new CounterPayload(); payload.Name = Name; payload.DisplayName = DisplayName ?? ""; payload.Count = 1; // NOTE: These dumb-looking statistics is intentional payload.IntervalSec = intervalSec; payload.Series = $"Interval={pollingIntervalMillisec}"; // TODO: This may need to change when we support multi-session payload.CounterType = "Mean"; payload.Mean = value; payload.Max = value; payload.Min = value; payload.Metadata = GetMetadataString(); payload.StandardDeviation = 0; payload.DisplayUnits = DisplayUnits ?? ""; _lastVal = value; EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new PollingPayloadType(payload)); } } } /// <summary> /// This is the payload that is sent in the with EventSource.Write /// </summary> [EventData] internal sealed class PollingPayloadType { public PollingPayloadType(CounterPayload payload) { Payload = payload; } public CounterPayload Payload { get; set; } } }