private AggregationPeriodSummary CycleAggregators( ref AggregatorCollection aggregators, DateTimeOffset tactTimestamp, IMetricSeriesFilter futureFilter, bool stopAggregators) { if (aggregators == _aggregatorsForPersistent) { throw new InvalidOperationException("Invernal SDK bug. Please report. Cannot cycle persistent aggregators."); } tactTimestamp = Util.RoundDownToSecond(tactTimestamp); // For non-persistent aggregators: create empty holder for the next aggregation period and swap for the previous holder: AggregatorCollection prevAggregators; if (stopAggregators) { prevAggregators = Interlocked.Exchange(ref aggregators, null); } else { AggregatorCollection nextAggregators = new AggregatorCollection(tactTimestamp, futureFilter); prevAggregators = Interlocked.Exchange(ref aggregators, nextAggregators); } List <MetricAggregate> persistentValsAggregations = GetPersistentAggregations(tactTimestamp, prevAggregators?.Filter); List <MetricAggregate> nonpersistentAggregations = GetNonpersistentAggregations(tactTimestamp, prevAggregators); var summary = new AggregationPeriodSummary(persistentValsAggregations, nonpersistentAggregations); return(summary); }
/// <summary> /// /// </summary> /// <param name="metricManager"></param> /// <param name="aggregationCycleKind"></param> /// <param name="tactTimestamp"></param> /// <param name="futureFilter"></param> /// <returns></returns> public static AggregationPeriodSummary StartOrCycleAggregators( this MetricManager metricManager, MetricAggregationCycleKind aggregationCycleKind, DateTimeOffset tactTimestamp, IMetricSeriesFilter futureFilter) { Util.ValidateNotNull(metricManager, nameof(metricManager)); return(metricManager.AggregationManager.StartOrCycleAggregators(aggregationCycleKind, tactTimestamp, futureFilter)); }
public static bool FilterWillConsume(IMetricSeriesFilter seriesFilter, MetricSeries series, out IMetricValueFilter valueFilter) { valueFilter = null; try { return((seriesFilter == null) || seriesFilter.WillConsume(series, out valueFilter)); } catch { // Protect against errors in user's implementation of IMetricSeriesFilter.WillConsume(..). // If it throws, assume that the filter is not functional and accept all values. return(true); } }
internal bool IsCycleActive(MetricAggregationCycleKind aggregationCycleKind, out IMetricSeriesFilter filter) { switch (aggregationCycleKind) { case CycleKind.Default: filter = null; return(true); case CycleKind.QuickPulse: case CycleKind.Custom: AggregatorCollection aggs = (aggregationCycleKind == CycleKind.QuickPulse) ? _aggregatorsForQuickPulse : _aggregatorsForCustom; filter = aggs?.Filter; return(aggs != null); default: throw new ArgumentException($"Unexpected value of {nameof(aggregationCycleKind)}: {aggregationCycleKind}."); } }
private static bool AddAggregator(IMetricSeriesAggregator aggregator, AggregatorCollection aggregatorCollection) { if (aggregatorCollection == null) { return(false); } IMetricSeriesFilter seriesFilter = aggregatorCollection.Filter; IMetricValueFilter valueFilter = null; if (seriesFilter != null && !seriesFilter.WillConsume(aggregator.DataSeries, out valueFilter)) { return(false); } aggregator.Reset(aggregatorCollection.PeriodStart, valueFilter); aggregatorCollection.Aggregators.Add(aggregator); return(true); }
private static bool AddAggregator(IMetricSeriesAggregator aggregator, AggregatorCollection aggregatorCollection) { if (aggregatorCollection == null) { return(false); } IMetricSeriesFilter seriesFilter = aggregatorCollection.Filter; IMetricValueFilter valueFilter; if (false == Util.FilterWillConsume(seriesFilter, aggregator.DataSeries, out valueFilter)) { return(false); } // @ToDo // @PublicExposureCandidate // aggregator.Reset(aggregatorCollection.PeriodStart, valueFilter); aggregator.Reset(aggregatorCollection.PeriodStart); aggregatorCollection.Aggregators.Add(aggregator); return(true); }
public AggregationPeriodSummary StartOrCycleAggregators(MetricAggregationCycleKind aggregationCycleKind, DateTimeOffset tactTimestamp, IMetricSeriesFilter futureFilter) { switch (aggregationCycleKind) { case CycleKind.Default: if (futureFilter != null) { throw new ArgumentException($"Cannot specify non-null {nameof(futureFilter)} when {nameof(aggregationCycleKind)} is {aggregationCycleKind}."); } return(CycleAggregators(ref _aggregatorsForDefault, tactTimestamp, futureFilter, stopAggregators: false)); case CycleKind.QuickPulse: return(CycleAggregators(ref _aggregatorsForQuickPulse, tactTimestamp, futureFilter, stopAggregators: false)); case CycleKind.Custom: return(CycleAggregators(ref _aggregatorsForCustom, tactTimestamp, futureFilter, stopAggregators: false)); default: throw new ArgumentException($"Unexpected value of {nameof(aggregationCycleKind)}: {aggregationCycleKind}."); } }
public AggregatorCollection(DateTimeOffset periodStart, IMetricSeriesFilter filter) { this.PeriodStart = periodStart; this.Aggregators = new GrowingCollection <IMetricSeriesAggregator>(); this.Filter = filter; }
private List <MetricAggregate> GetPersistentAggregations(DateTimeOffset tactTimestamp, IMetricSeriesFilter previousFilter) { // Complete each persistent aggregator: // The Enumerator of GrowingCollection is a thread-safe lock-free implementation that operates on a "snapshot" of a collection taken at the // time when the enumerator is created. We expand the foreach statement (like the compiler normally does) so that we can use the typed // enumerator's Count property which is constsent with the data in the snapshot. GrowingCollection <IMetricSeriesAggregator> .Enumerator persistentValsAggregators = _aggregatorsForPersistent.Aggregators.GetEnumerator(); List <MetricAggregate> persistentValsAggregations = new List <MetricAggregate>(capacity: persistentValsAggregators.Count); try { while (persistentValsAggregators.MoveNext()) { IMetricSeriesAggregator aggregator = persistentValsAggregators.Current; if (aggregator != null) { // Persistent aggregators are always active, regardless of filters for a particular cycle. // But we can apply the cycle's filters to determine whether or not to pull the aggregator // for a aggregate at this time. Of course, only series filters, not value filters, can be considered. IMetricValueFilter unusedValueFilter; bool satisfiesFilter = (previousFilter == null) || (previousFilter.WillConsume(aggregator.DataSeries, out unusedValueFilter)); if (satisfiesFilter) { MetricAggregate aggregate = aggregator.CompleteAggregation(tactTimestamp); if (aggregate != null) { persistentValsAggregations.Add(aggregate); } } } } } finally { persistentValsAggregators.Dispose(); } return(persistentValsAggregations); }