public void Aggregate(ref MetricValue metricValue) { // If rates are not stored then there is nothing to aggregate if (!_storeRates) { return; } IList <DataSource> dsl = DataSetCollection.Instance.GetDataSource(metricValue.TypeName); if (dsl == null || metricValue.Values.Length != dsl.Count) { return; } double now = Util.GetNow(); lock (_cacheLock) { CacheEntry cEntry; string key = metricValue.Key(); if (!(_cache.TryGetValue(key, out cEntry))) { cEntry = new CacheEntry(metricValue.DeepCopy()); for (int i = 0; i < metricValue.Values.Length; i++) { if (dsl[i].Type == DsType.Derive || dsl[i].Type == DsType.Absolute || dsl[i].Type == DsType.Counter) { metricValue.Values[i] = double.NaN; cEntry.MetricRate.Values[i] = double.NaN; } } cEntry.MetricRate.Epoch = now; _cache[key] = cEntry; return; } for (int i = 0; i < metricValue.Values.Length; i++) { double rawValNew = metricValue.Values[i]; double rawValOld = cEntry.RawValues[i]; double rawValDiff = rawValNew - rawValOld; double timeDiff = cEntry.MetricRate.Epoch - now; double rateNew = rawValDiff / timeDiff; switch (dsl[i].Type) { case DsType.Gauge: // no rates calculations are done, values are stored as-is for gauge cEntry.RawValues[i] = rawValNew; cEntry.MetricRate.Values[i] = rawValNew; break; case DsType.Absolute: // similar to gauge, except value will be divided by time diff cEntry.MetricRate.Values[i] = metricValue.Values[i] / timeDiff; cEntry.RawValues[i] = rawValNew; metricValue.Values[i] = cEntry.MetricRate.Values[i]; break; case DsType.Derive: cEntry.RawValues[i] = rawValNew; cEntry.MetricRate.Values[i] = rateNew; metricValue.Values[i] = rateNew; break; case DsType.Counter: // Counters are very simlar to derive except when counter wraps around if (rawValNew < rawValOld) { // counter has wrapped around cEntry.MetricRate.Values[i] = metricValue.Values[i] / timeDiff; cEntry.RawValues[i] = rawValNew; metricValue.Values[i] = cEntry.MetricRate.Values[i]; } else { cEntry.MetricRate.Values[i] = rateNew; cEntry.RawValues[i] = rawValNew; metricValue.Values[i] = rateNew; } break; } // range checks if (metricValue.Values[i] < dsl[i].Min) { metricValue.Values[i] = dsl[i].Min; cEntry.RawValues[i] = metricValue.Values[i]; } if (metricValue.Values[i] > dsl[i].Max) { metricValue.Values[i] = dsl[i].Max; cEntry.RawValues[i] = metricValue.Values[i]; } cEntry.MetricRate.Epoch = now; _cache[key] = cEntry; } } }
public void Aggregate(ref MetricValue metricValue) { // If rates are not stored then there is nothing to aggregate if (!_storeRates) { return; } IList<DataSource> dsl = DataSetCollection.Instance.GetDataSource(metricValue.TypeName); if (dsl == null || metricValue.Values.Length != dsl.Count) { return; } double now = Util.GetNow(); lock (_cacheLock) { CacheEntry cEntry; string key = metricValue.Key(); if (!(_cache.TryGetValue(key, out cEntry))) { cEntry = new CacheEntry(metricValue.DeepCopy()); for (int i = 0; i < metricValue.Values.Length; i++) { if (dsl[i].Type == DsType.Derive || dsl[i].Type == DsType.Absolute || dsl[i].Type == DsType.Counter) { metricValue.Values[i] = double.NaN; cEntry.MetricRate.Values[i] = double.NaN; } } cEntry.MetricRate.Epoch = now; _cache[key] = cEntry; return; } for (int i = 0; i < metricValue.Values.Length; i++) { double rawValNew = metricValue.Values[i]; double rawValOld = cEntry.RawValues[i]; double rawValDiff = rawValNew - rawValOld; double timeDiff = cEntry.MetricRate.Epoch - now; double rateNew = rawValDiff/timeDiff; switch (dsl[i].Type) { case DsType.Gauge: // no rates calculations are done, values are stored as-is for gauge cEntry.RawValues[i] = rawValNew; cEntry.MetricRate.Values[i] = rawValNew; break; case DsType.Absolute: // similar to gauge, except value will be divided by time diff cEntry.MetricRate.Values[i] = metricValue.Values[i]/timeDiff; cEntry.RawValues[i] = rawValNew; metricValue.Values[i] = cEntry.MetricRate.Values[i]; break; case DsType.Derive: cEntry.RawValues[i] = rawValNew; cEntry.MetricRate.Values[i] = rateNew; metricValue.Values[i] = rateNew; break; case DsType.Counter: // Counters are very simlar to derive except when counter wraps around if (rawValNew < rawValOld) { // counter has wrapped around cEntry.MetricRate.Values[i] = metricValue.Values[i]/timeDiff; cEntry.RawValues[i] = rawValNew; metricValue.Values[i] = cEntry.MetricRate.Values[i]; } else { cEntry.MetricRate.Values[i] = rateNew; cEntry.RawValues[i] = rawValNew; metricValue.Values[i] = rateNew; } break; } // range checks if (metricValue.Values[i] < dsl[i].Min) { metricValue.Values[i] = dsl[i].Min; cEntry.RawValues[i] = metricValue.Values[i]; } if (metricValue.Values[i] > dsl[i].Max) { metricValue.Values[i] = dsl[i].Max; cEntry.RawValues[i] = metricValue.Values[i]; } cEntry.MetricRate.Epoch = now; _cache[key] = cEntry; } } }