private async Task AggregatorLoopAsync() { while (_isDisposed == false) { try { // Wait for end end of the aggregation period: await Task.Delay(AggregationPeriod).ConfigureAwait(continueOnCapturedContext: false); if (_isDisposed) { break; } // Atomically snap the current aggregation: MetricAggregator nextAggregator = new MetricAggregator(DateTimeOffset.UtcNow); if (_aggregator == null) { _aggregator = nextAggregator; continue; } MetricAggregator prevAggregator = Interlocked.Exchange(ref _aggregator, nextAggregator); // Only send anything is at least one value was measured: if (prevAggregator != null && prevAggregator.Count > 0) { // Compute the actual aggregation period length: TimeSpan aggPeriod = nextAggregator.StartTimestamp - prevAggregator.StartTimestamp; if (aggPeriod.TotalMilliseconds < 1) { aggPeriod = TimeSpan.FromMilliseconds(1); } foreach (var sink in _sinks) { try { sink.TrackMetric( Name, prevAggregator.Count, prevAggregator.Sum, prevAggregator.Min, prevAggregator.Max, prevAggregator.StandardDeviation, aggPeriod, prevAggregator.StartTimestamp, _properties ); }catch (Exception ex) { } } } } catch (Exception ex) { } } }
public void TrackValue(double value) { MetricAggregator currAggregator = _aggregator; if (currAggregator != null) { currAggregator.TrackValue(value); } }
public Metric(string name, ITelemetrySink[] sinks, IDictionary <string, string> properties = null) { this.Name = name ?? "null"; this._aggregator = new MetricAggregator(DateTimeOffset.UtcNow); this._sinks = sinks ?? throw new ArgumentNullException(nameof(sinks)); _properties = properties; Task.Run(this.AggregatorLoopAsync); }
void IDisposable.Dispose() { _isDisposed = true; _aggregator = null; }