diff --git a/backends/graphite.js b/backends/graphite.js index bd73c84..420e548 100644 --- a/backends/graphite.js +++ b/backends/graphite.js @@ -19,11 +19,20 @@ var debug; var flushInterval; var graphiteHost; var graphitePort; + +// prefix configuration +var globalPrefix; var prefixPersecond; -var prefixCount; +var prefixCounter; var prefixTimer; var prefixGauge; +// set up namespaces +var globalNamespace = []; +var counterNamespace = []; +var timerNamespace = []; +var gaugesNamespace = []; + var graphiteStats = {}; var post_stats = function graphite_post_stats(statString) { @@ -39,8 +48,9 @@ var post_stats = function graphite_post_stats(statString) { }); graphite.on('connect', function() { var ts = Math.round(new Date().getTime() / 1000); - statString += 'stats.statsd.graphiteStats.last_exception ' + last_exception + ' ' + ts + "\n"; - statString += 'stats.statsd.graphiteStats.last_flush ' + last_flush + ' ' + ts + "\n"; + var namespace = globalNamespace.concat('statsd'); + statString += namespace.join(".") + '.graphiteStats.last_exception ' + last_exception + ' ' + ts + "\n"; + statString += namespace.join(".") + '.graphiteStats.last_flush ' + last_flush + ' ' + ts + "\n"; this.write(statString); this.end(); graphiteStats.last_flush = Math.round(new Date().getTime() / 1000); @@ -66,11 +76,13 @@ var flush_stats = function graphite_flush(ts, metrics) { var pctThreshold = metrics.pctThreshold; for (key in counters) { + var namespace = counterNamespace.concat(key); + var namespace_num = counterNamespace.concat('stats_counts', key); var value = counters[key]; var valuePerSecond = value / (flushInterval / 1000); // calculate "per second" rate - statString += prefixPersecond + key + ' ' + valuePerSecond + ' ' + ts + "\n"; - statString += prefixCount + key + ' ' + value + ' ' + ts + "\n"; + statString += namespace.join(".") + ' ' + valuePerSecond + ' ' + ts + "\n"; + statString += namespace_num.join(".") + ' ' + value + ' ' + ts + "\n"; numStats += 1; } @@ -82,6 +94,9 @@ var flush_stats = function graphite_flush(ts, metrics) { var min = values[0]; var max = values[count - 1]; + var namespace = timerNamespace.concat(key); + var the_key = namespace.join("."); + var cumulativeValues = [min]; for (var i = 1; i < count; i++) { cumulativeValues.push(values[i] + cumulativeValues[i-1]); @@ -108,9 +123,9 @@ var flush_stats = function graphite_flush(ts, metrics) { var clean_pct = '' + pct; clean_pct.replace('.', '_'); - message += prefixTimer + key + '.mean_' + clean_pct + ' ' + mean + ' ' + ts + "\n"; - message += prefixTimer + key + '.upper_' + clean_pct + ' ' + maxAtThreshold + ' ' + ts + "\n"; - message += prefixTimer + key + '.sum_' + clean_pct + ' ' + sum + ' ' + ts + "\n"; + message += the_key + '.mean_' + clean_pct + ' ' + mean + ' ' + ts + "\n"; + message += the_key + '.upper_' + clean_pct + ' ' + maxAtThreshold + ' ' + ts + "\n"; + message += the_key + '.sum_' + clean_pct + ' ' + sum + ' ' + ts + "\n"; } sum = cumulativeValues[count-1]; @@ -122,12 +137,12 @@ var flush_stats = function graphite_flush(ts, metrics) { } var stddev = Math.sqrt(sumOfDiffs / count); - message += prefixTimer + key + '.std ' + stddev + ' ' + ts + "\n"; - message += prefixTimer + key + '.upper ' + max + ' ' + ts + "\n"; - message += prefixTimer + key + '.lower ' + min + ' ' + ts + "\n"; - message += prefixTimer + key + '.count ' + count + ' ' + ts + "\n"; - message += prefixTimer + key + '.sum ' + sum + ' ' + ts + "\n"; - message += prefixTimer + key + '.mean ' + mean + ' ' + ts + "\n"; + message += the_key + '.std ' + stddev + ' ' + ts + "\n"; + message += the_key + '.upper ' + max + ' ' + ts + "\n"; + message += the_key + '.lower ' + min + ' ' + ts + "\n"; + message += the_key + '.count ' + count + ' ' + ts + "\n"; + message += the_key + '.sum ' + sum + ' ' + ts + "\n"; + message += the_key + '.mean ' + mean + ' ' + ts + "\n"; statString += message; @@ -136,12 +151,14 @@ var flush_stats = function graphite_flush(ts, metrics) { } for (key in gauges) { - statString += prefixGauge + key + ' ' + gauges[key] + ' ' + ts + "\n"; + var namespace = gaugesNamespace.concat(key); + statString += namespace.join(".") + ' ' + gauges[key] + ' ' + ts + "\n"; numStats += 1; } - statString += 'statsd.numStats ' + numStats + ' ' + ts + "\n"; - statString += 'stats.statsd.graphiteStats.calculationtime ' + (Date.now() - starttime) + ' ' + ts + "\n"; + var namespace = globalNamespace.concat('statsd'); + statString += namespace.join(".") + '.numStats ' + numStats + ' ' + ts + "\n"; + statString += namespace.join(".") + '.graphiteStats.calculationtime ' + (Date.now() - starttime) + ' ' + ts + "\n"; post_stats(statString); }; @@ -155,10 +172,28 @@ exports.init = function graphite_init(startup_time, config, events) { debug = config.debug; graphiteHost = config.graphiteHost; graphitePort = config.graphitePort; - prefixPersecond = config.prefixPersecond || "statsd."; - prefixCount = config.prefixCount || "stats_counts."; - prefixTimer = config.prefixTimer || "stats.timers."; - prefixGauge = config.prefixGauge || "stats.gauges."; + config.graphite = config.graphite || {}; + globalPrefix = config.graphite.globalPrefix || "stats"; + prefixCounter = config.graphite.prefixCounter || "counters"; + prefixTimer = config.graphite.prefixTimer || "timers"; + prefixGauge = config.graphite.prefixGauge || "gauges"; + + if (globalPrefix !== "") { + globalNamespace.push(globalPrefix); + counterNamespace.push(globalPrefix); + timerNamespace.push(globalPrefix); + gaugesNamespace.push(globalPrefix); + } + + if (prefixCounter !== "") { + counterNamespace.push(prefixCounter); + } + if (prefixTimer !== "") { + timerNamespace.push(prefixTimer); + } + if (prefixGauge !== "") { + gaugesNamespace.push(prefixGauge); + } graphiteStats.last_flush = startup_time; graphiteStats.last_exception = startup_time; diff --git a/exampleConfig.js b/exampleConfig.js index 41ec12a..871e9a0 100644 --- a/exampleConfig.js +++ b/exampleConfig.js @@ -44,10 +44,11 @@ Optional Variables: application: name of the application for syslog [string, default: statsd] level: log level for [node-]syslog [string, default: LOG_INFO] - prefixPersecond: graphite prefix for counter per second metrics [default: "statsd."] - prefixCount: graphite prefix for count metrics [default: "stats_counts."] - prefixTimer: graphite prefix for timer metrics [default: "stats.timers."] - prefixGauge: graphite prefix for gauge metrics [default: "stats.gauges."] + graphite: + globalPrefix: global prefix to use for sending stats to graphite [default: "stats"] + prefixCounter: graphite prefix for counter metrics [default: "counters"] + prefixTimer: graphite prefix for timer metrics [default: "timers"] + prefixGauge: graphite prefix for gauge metrics [default: "gauges"] */ { graphitePort: 2003