Skip to content
This repository
Browse code

Support gathering "top" percentile statistics

Adds support for collecting statistics on top percentiles, instead of
the default bottom percentiles. You specify a top percentile by
using a negative number - so -10 will collect the top 10% of data. It
will emit: mean_top10, lower_top10, and sum_top10.

Using a negative number may seem hacky, but it's convenient and there
is a precedent - referencing an array from the end in some languages
can be done with negative indexes.
  • Loading branch information...
commit f369dfade2882d41896a7f2e6c364188a9b3bef8 1 parent 2ccde82
Zach Wily zwily authored
1  exampleConfig.js
@@ -29,6 +29,7 @@ Optional Variables:
29 29 flushInterval: interval (in ms) to flush to Graphite
30 30 percentThreshold: for time information, calculate the Nth percentile(s)
31 31 (can be a single value or list of floating-point values)
  32 + negative values mean to use "top" Nth percentile(s) values
32 33 [%, default: 90]
33 34 keyFlush: log the most frequently sent keys [object, default: undefined]
34 35 interval: how often to log frequent keys [ms, default: 0]
20 lib/process_metrics.js
@@ -34,24 +34,32 @@ var process_metrics = function (metrics, flushInterval, ts, flushCallback) {
34 34
35 35 var sum = min;
36 36 var mean = min;
37   - var maxAtThreshold = max;
  37 + var thresholdBoundary = max;
38 38
39 39 var key2;
40 40
41 41 for (key2 in pctThreshold) {
42 42 var pct = pctThreshold[key2];
43 43 if (count > 1) {
44   - var numInThreshold = Math.round(pct / 100 * count);
  44 + var numInThreshold = Math.round(Math.abs(pct) / 100 * count);
  45 + if (numInThreshold === 0) {
  46 + continue;
  47 + }
45 48
46   - maxAtThreshold = values[numInThreshold - 1];
47   - sum = cumulativeValues[numInThreshold - 1];
  49 + if (pct > 0) {
  50 + thresholdBoundary = values[numInThreshold - 1];
  51 + sum = cumulativeValues[numInThreshold - 1];
  52 + } else {
  53 + thresholdBoundary = values[count - numInThreshold];
  54 + sum = cumulativeValues[count - 1] - cumulativeValues[count - numInThreshold - 1];
  55 + }
48 56 mean = sum / numInThreshold;
49 57 }
50 58
51 59 var clean_pct = '' + pct;
52   - clean_pct = clean_pct.replace('.', '_');
  60 + clean_pct = clean_pct.replace('.', '_').replace('-', 'top');
53 61 current_timer_data["mean_" + clean_pct] = mean;
54   - current_timer_data["upper_" + clean_pct] = maxAtThreshold;
  62 + current_timer_data[(pct > 0 ? "upper_" : "lower_") + clean_pct] = thresholdBoundary;
55 63 current_timer_data["sum_" + clean_pct] = sum;
56 64
57 65 }
22 test/process_metrics_tests.js
@@ -184,6 +184,28 @@ module.exports = {
184 184
185 185 test.done();
186 186 },
  187 + timers_single_time_single_top_percentile: function(test) {
  188 + test.expect(3);
  189 + this.metrics.timers['a'] = [100];
  190 + this.metrics.pctThreshold = [-10];
  191 + pm.process_metrics(this.metrics, 100, this.time_stamp, function(){});
  192 + timer_data = this.metrics.timer_data['a'];
  193 + test.equal(100, timer_data.mean_top10);
  194 + test.equal(100, timer_data.lower_top10);
  195 + test.equal(100, timer_data.sum_top10);
  196 + test.done();
  197 + },
  198 + timers_multiple_times_single_top_percentile: function(test) {
  199 + test.expect(3);
  200 + this.metrics.timers['a'] = [10, 10, 10, 10, 10, 10, 10, 10, 100, 200];
  201 + this.metrics.pctThreshold = [-20];
  202 + pm.process_metrics(this.metrics, 100, this.time_stamp, function(){});
  203 + timer_data = this.metrics.timer_data['a'];
  204 + test.equal(150, timer_data.mean_top20);
  205 + test.equal(100, timer_data.lower_top20);
  206 + test.equal(300, timer_data.sum_top20);
  207 + test.done();
  208 + },
187 209 statsd_metrics_exist: function(test) {
188 210 test.expect(1);
189 211 pm.process_metrics(this.metrics, 100, this.time_stamp, function(){});

0 comments on commit f369dfa

Please sign in to comment.
Something went wrong with that request. Please try again.