public static ActionBlock<StatsdMessage> CreateBlock(ITargetBlock<CounterBucket> target, string rootNamespace, IIntervalService intervalService, ITimeWindowService timeWindowService, ILog log) { var windows = new ConcurrentDictionary<string, ConcurrentDictionary<string, double>>(); var root = rootNamespace; var ns = String.IsNullOrEmpty(rootNamespace) ? "" : rootNamespace + "."; var incoming = new ActionBlock<StatsdMessage>(p => { var calendargram = p as Calendargram; var metricName = calendargram.Name + METRIC_IDENTIFIER_SEPARATOR + calendargram.Value; var period = timeWindowService.GetTimeWindow().GetTimePeriod(calendargram.Period); windows.AddOrUpdate(period, (key) => { var window = new ConcurrentDictionary<string, double>(); window.AddOrUpdate(metricName, (key2) => 1, (key2, oldValue) => 1); return window; }, (key, window) => { window.AddOrUpdate(metricName, (key2) => 1, (key2, oldValue) => 1); return window; } ); }, new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded }); intervalService.Elapsed += (sender, e) => { if (windows.Count == 0) { return; } var currentTimeWindow = timeWindowService.GetTimeWindow(); var periodsNotPresent = windows .ToArray() .Where(p => !currentTimeWindow.AllPeriods.Contains(p.Key)) .Select(p => p.Key); CounterBucket bucket; foreach (var period in periodsNotPresent) { ConcurrentDictionary<String, double> window; if (windows.TryRemove(period, out window)) { var parts = period.Split(UNDERSCORE); var qualifier = "." + parts[0] + "." + parts[1]; var metricsAndValues = window.ToArray(); var metrics = new Dictionary<String, double>(); for (int index = 0; index < metricsAndValues.Length; index++) { var metricName = metricsAndValues[index].Key.Split( METRIC_IDENTIFIER_SEPARATOR_SPLITTER, StringSplitOptions.RemoveEmptyEntries )[0] + qualifier; if (metrics.ContainsKey(metricName)) { metrics[metricName] += 1; } else { metrics[metricName] = 1; } } var metricList = metrics.Select(metric => { return new KeyValuePair<string, double>( metric.Key, metric.Value ); }).ToArray(); bucket = new CounterBucket(metricList, e.Epoch, ns); target.Post(bucket); } } }; incoming.Completion.ContinueWith(p => { log.Info("TimedCounterAggregatorBlock completing."); // Tell the upstream block that we're done target.Complete(); }); return incoming; }
public TimeWindowController(ITimeWindowService timeWindowService, IFeatureService featureService) { _timeWindowService = timeWindowService ?? throw new ArgumentNullException(nameof(timeWindowService)); _featureService = featureService ?? throw new ArgumentNullException(nameof(featureService)); }
public static ActionBlock <StatsdMessage> CreateBlock(ITargetBlock <CounterBucket> target, string rootNamespace, IIntervalService intervalService, ITimeWindowService timeWindowService, ILog log) { var windows = new ConcurrentDictionary <string, ConcurrentDictionary <string, double> >(); var root = rootNamespace; var ns = String.IsNullOrEmpty(rootNamespace) ? "" : rootNamespace + "."; var incoming = new ActionBlock <StatsdMessage>(p => { var calendargram = p as Calendargram; var metricName = calendargram.Name + METRIC_IDENTIFIER_SEPARATOR + calendargram.Value; var period = timeWindowService.GetTimeWindow().GetTimePeriod(calendargram.Period); windows.AddOrUpdate(period, (key) => { var window = new ConcurrentDictionary <string, double>(); window.AddOrUpdate(metricName, (key2) => 1, (key2, oldValue) => 1); return(window); }, (key, window) => { window.AddOrUpdate(metricName, (key2) => 1, (key2, oldValue) => 1); return(window); } ); }, new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded }); intervalService.Elapsed += (sender, e) => { if (windows.Count == 0) { return; } var currentTimeWindow = timeWindowService.GetTimeWindow(); var periodsNotPresent = windows .ToArray() .Where(p => !currentTimeWindow.AllPeriods.Contains(p.Key)) .Select(p => p.Key); CounterBucket bucket; foreach (var period in periodsNotPresent) { ConcurrentDictionary <String, double> window; if (windows.TryRemove(period, out window)) { var parts = period.Split(UNDERSCORE); var qualifier = "." + parts[0] + "." + parts[1]; var metricsAndValues = window.ToArray(); var metrics = new Dictionary <String, double>(); for (int index = 0; index < metricsAndValues.Length; index++) { var metricName = metricsAndValues[index].Key.Split( METRIC_IDENTIFIER_SEPARATOR_SPLITTER, StringSplitOptions.RemoveEmptyEntries )[0] + qualifier; if (metrics.ContainsKey(metricName)) { metrics[metricName] += 1; } else { metrics[metricName] = 1; } } var metricList = metrics.Select(metric => { return(new KeyValuePair <string, double>( metric.Key, metric.Value )); }).ToArray(); bucket = new CounterBucket(metricList, e.Epoch, ns); target.Post(bucket); } } }; incoming.Completion.ContinueWith(p => { log.Info("TimedCounterAggregatorBlock completing."); // Tell the upstream block that we're done target.Complete(); }); return(incoming); }