forked from statsd/statsd
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
do timer and counter calculations prior to sending to backends
- Loading branch information
Showing
6 changed files
with
224 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
var ProcessedMetrics = function (metrics, flushInterval) { | ||
var starttime = Date.now(); | ||
var key; | ||
var counter_rates = {}; | ||
var timer_data = {}; | ||
|
||
var counters = metrics.counters; | ||
var timers = metrics.timers; | ||
var pctThreshold = metrics.pctThreshold; | ||
|
||
for (key in counters) { | ||
var value = counters[key]; | ||
|
||
// calculate "per second" rate | ||
var valuePerSecond = value / (flushInterval / 1000); | ||
counter_rates[key] = valuePerSecond; | ||
} | ||
|
||
for (key in timers) { | ||
if (timers[key].length > 0) { | ||
timer_data[key] = {}; | ||
var current_timer_data = {}; | ||
|
||
var values = timers[key].sort(function (a,b) { return a-b; }); | ||
var count = values.length; | ||
var min = values[0]; | ||
var max = values[count - 1]; | ||
|
||
var cumulativeValues = [min]; | ||
for (var i = 1; i < count; i++) { | ||
cumulativeValues.push(values[i] + cumulativeValues[i-1]); | ||
} | ||
|
||
var sum = min; | ||
var mean = min; | ||
var maxAtThreshold = max; | ||
|
||
var message = ""; | ||
|
||
var key2; | ||
|
||
for (key2 in pctThreshold) { | ||
var pct = pctThreshold[key2]; | ||
if (count > 1) { | ||
var thresholdIndex = Math.round(((100 - pct) / 100) * count); | ||
var numInThreshold = count - thresholdIndex; | ||
|
||
maxAtThreshold = values[numInThreshold - 1]; | ||
sum = cumulativeValues[numInThreshold - 1]; | ||
mean = sum / numInThreshold; | ||
} | ||
|
||
var clean_pct = '' + pct; | ||
clean_pct.replace('.', '_'); | ||
current_timer_data["mean_" + clean_pct] = mean; | ||
current_timer_data["upper_" + clean_pct] = maxAtThreshold; | ||
current_timer_data["sum_" + clean_pct] = sum; | ||
|
||
} | ||
|
||
sum = cumulativeValues[count-1]; | ||
mean = sum / count; | ||
|
||
var sumOfDiffs = 0; | ||
for (var i = 0; i < count; i++) { | ||
sumOfDiffs += (values[i] - mean) * (values[i] - mean); | ||
} | ||
var stddev = Math.sqrt(sumOfDiffs / count); | ||
current_timer_data["std"] = stddev; | ||
current_timer_data["upper"] = max; | ||
current_timer_data["lower"] = min; | ||
current_timer_data["count"] = count; | ||
current_timer_data["sum"] = sum; | ||
current_timer_data["mean"] = mean; | ||
|
||
timer_data[key] = current_timer_data; | ||
|
||
} | ||
} | ||
|
||
//add processed metrics to the metrics_hash | ||
metrics.counter_rates = counter_rates; | ||
metrics.timer_data = timer_data; | ||
|
||
return metrics; | ||
} | ||
|
||
exports.ProcessedMetrics = ProcessedMetrics |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
var pm = require('../lib/processedmetrics') | ||
var time_stamp = Math.round(new Date().getTime() / 1000); | ||
|
||
var counters = {}; | ||
var gauges = {}; | ||
var timers = {}; | ||
var sets = {}; | ||
var pctThreshold = null; | ||
|
||
var metrics = { | ||
counters: counters, | ||
gauges: gauges, | ||
timers: timers, | ||
sets: sets, | ||
pctThreshold: pctThreshold | ||
} | ||
|
||
module.exports = { | ||
counters_has_stats_count: function(test) { | ||
test.expect(1); | ||
metrics.counters['a'] = 2; | ||
var processed_metrics = new pm.ProcessedMetrics(metrics, 1000); | ||
test.equal(2, processed_metrics.counters['a']); | ||
test.done(); | ||
}, | ||
counters_has_correct_rate: function(test) { | ||
test.expect(1); | ||
metrics.counters['a'] = 2; | ||
var processed_metrics = new pm.ProcessedMetrics(metrics, 100); | ||
test.equal(20, processed_metrics.counter_rates['a']); | ||
test.done(); | ||
}, | ||
timers_handle_empty: function(test) { | ||
test.expect(1); | ||
metrics.timers['a'] = []; | ||
var processed_metrics = new pm.ProcessedMetrics(metrics, 100); | ||
test.equal(20, processed_metrics.counter_rates['a']); | ||
test.done(); | ||
}, | ||
timers_single_time: function(test) { | ||
test.expect(6); | ||
metrics.timers['a'] = [100]; | ||
var processed_metrics = new pm.ProcessedMetrics(metrics, 100); | ||
timer_data = processed_metrics.timer_data['a']; | ||
test.equal(0, timer_data.std); | ||
test.equal(100, timer_data.upper); | ||
test.equal(100, timer_data.lower); | ||
test.equal(1, timer_data.count); | ||
test.equal(100, timer_data.sum); | ||
test.equal(100, timer_data.mean); | ||
test.done(); | ||
}, | ||
timers_multiple_times: function(test) { | ||
test.expect(6); | ||
metrics.timers['a'] = [100, 200, 300]; | ||
var processed_metrics = new pm.ProcessedMetrics(metrics, 100); | ||
timer_data = processed_metrics.timer_data['a']; | ||
test.equal(81.64965809277261, timer_data.std); | ||
test.equal(300, timer_data.upper); | ||
test.equal(100, timer_data.lower); | ||
test.equal(3, timer_data.count); | ||
test.equal(600, timer_data.sum); | ||
test.equal(200, timer_data.mean); | ||
test.done(); | ||
}, | ||
timers_single_time_single_percentile: function(test) { | ||
test.expect(3); | ||
metrics.timers['a'] = [100]; | ||
metrics.pctThreshold = [90]; | ||
var processed_metrics = new pm.ProcessedMetrics(metrics, 100); | ||
timer_data = processed_metrics.timer_data['a']; | ||
test.equal(100, timer_data.mean_90); | ||
test.equal(100, timer_data.upper_90); | ||
test.equal(100, timer_data.sum_90); | ||
test.done(); | ||
}, | ||
timers_single_time_multiple_percentiles: function(test) { | ||
test.expect(6); | ||
metrics.timers['a'] = [100]; | ||
metrics.pctThreshold = [90, 80]; | ||
var processed_metrics = new pm.ProcessedMetrics(metrics, 100); | ||
timer_data = processed_metrics.timer_data['a']; | ||
test.equal(100, timer_data.mean_90); | ||
test.equal(100, timer_data.upper_90); | ||
test.equal(100, timer_data.sum_90); | ||
test.equal(100, timer_data.mean_80); | ||
test.equal(100, timer_data.upper_80); | ||
test.equal(100, timer_data.sum_80); | ||
test.done(); | ||
}, | ||
timers_multiple_times_single_percentiles: function(test) { | ||
test.expect(3); | ||
metrics.timers['a'] = [100, 200, 300]; | ||
metrics.pctThreshold = [90]; | ||
var processed_metrics = new pm.ProcessedMetrics(metrics, 100); | ||
timer_data = processed_metrics.timer_data['a']; | ||
test.equal(200, timer_data.mean_90); | ||
test.equal(300, timer_data.upper_90); | ||
test.equal(600, timer_data.sum_90); | ||
test.done(); | ||
}, | ||
timers_multiple_times_multiple_percentiles: function(test) { | ||
test.expect(6); | ||
metrics.timers['a'] = [100, 200, 300]; | ||
metrics.pctThreshold = [90, 80]; | ||
var processed_metrics = new pm.ProcessedMetrics(metrics, 100); | ||
timer_data = processed_metrics.timer_data['a']; | ||
test.equal(200, timer_data.mean_90); | ||
test.equal(300, timer_data.upper_90); | ||
test.equal(600, timer_data.sum_90); | ||
test.equal(150, timer_data.mean_80); | ||
test.equal(200, timer_data.upper_80); | ||
test.equal(300, timer_data.sum_80); | ||
test.done(); | ||
} | ||
} |