Permalink
Browse files

Merge remote branch 'upstream/master'

Conflicts:
	backends/graphite.js
Merge with etsy/master
  • Loading branch information...
2 parents 00c0c1f + 7873e97 commit 953063a2c6008480a5b4a4f7c8a814006f50bfc5 @draco2003 committed with root Oct 31, 2012
Showing with 105 additions and 35 deletions.
  1. +5 −7 README.md
  2. +1 −1 backends/repeater.js
  3. +2 −1 debian/statsd.init
  4. +1 −1 debian/statsd.install
  5. +1 −2 debian/statsd.upstart
  6. +1 −1 exampleConfig.js
  7. +40 −12 examples/php-example.php
  8. +1 −1 { → lib}/config.js
  9. +2 −2 lib/logger.js
  10. +18 −7 stats.js
  11. +33 −0 test/graphite_tests.js
View
12 README.md
@@ -33,6 +33,11 @@ Counting
This is a simple counter. Add 1 to the "gorets" bucket. It stays in memory
until the flush interval `config.flushInterval`.
+### Sampling
+
+ gorets:1|c|@0.1
+
+Tells StatsD that this counter is being sent sampled every 1/10th of the time.
Timing
------
@@ -51,13 +56,6 @@ generate the following list of stats for each threshold:
Where `$KEY` is the key you stats key you specify when sending to statsd, and
`$PCT` is the percentile threshold.
-Sampling
---------
-
- gorets:1|c|@0.1
-
-Tells StatsD that this counter is being sent sampled every 1/10th of the time.
-
Gauges
------
StatsD now also supports gauges, arbitrary values, which can be recorded.
View
2 backends/repeater.js
@@ -4,7 +4,7 @@ var util = require('util'),
function RepeaterBackend(startupTime, config, emitter){
var self = this;
this.config = config.repeater || [];
- this.sock = dgram.createSocket('udp4');
+ this.sock = dgram.createSocket('udp6');
// attach
emitter.on('packet', function(packet, rinfo) { self.process(packet, rinfo); });
View
3 debian/statsd.init
@@ -25,6 +25,7 @@ DAEMON=$NODE_BIN
DAEMON_ARGS="/usr/share/statsd/stats.js /etc/statsd/localConfig.js 2>&1 >> /var/log/statsd/statsd.log "
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
+CHDIR="/usr/share/statsd"
# Exit if the package is not installed
# [ -x "$DAEMON" ] || exit 0
@@ -50,7 +51,7 @@ do_start()
# 2 if daemon could not be started
start-stop-daemon --start --quiet -m --pidfile $PIDFILE --startas $DAEMON --background --test > /dev/null \
|| return 1
- start-stop-daemon --start --quiet -m --pidfile $PIDFILE --startas $DAEMON --background -- \
+ start-stop-daemon --start --quiet -m --pidfile $PIDFILE --startas $DAEMON --background --chdir $CHDIR -- \
$DAEMON_ARGS > /dev/null 2> /var/log/$NAME-stderr.log \
|| return 2
# Add code here, if necessary, that waits for the process to be ready
View
2 debian/statsd.install
@@ -1,6 +1,6 @@
stats.js /usr/share/statsd
-config.js /usr/share/statsd
lib/*.js /usr/share/statsd/lib
backends/*.js /usr/share/statsd/backends
+lib/*.js /usr/share/statsd/lib
debian/localConfig.js /etc/statsd
debian/scripts/start /usr/share/statsd/scripts
View
3 debian/statsd.upstart
@@ -5,8 +5,7 @@ start on startup
stop on shutdown
script
- # We found $HOME is needed. Without it, we ran into problems
- export HOME="/root"
+ chdir /usr/share/statsd
exec sudo -u nobody /usr/share/statsd/scripts/start
end script
View
2 exampleConfig.js
@@ -54,6 +54,6 @@ Optional Variables:
graphitePort: 2003
, graphiteHost: "graphite.host.com"
, port: 8125
-, backends: [ "./backends/repeater" ]
+, backends: [ "./backends/graphite" ]
, repeater: [ { host: "10.8.3.214", port: 8125 } ]
}
View
52 examples/php-example.php
@@ -8,14 +8,41 @@
class StatsD {
/**
- * Log timing information
+ * Sets one or more timing values
*
- * @param string $stats The metric to in log timing info for.
- * @param float $time The ellapsed time (ms) to log
- * @param float|1 $sampleRate the rate (0-1) for sampling.
+ * @param string|array $stats The metric(s) to set.
+ * @param float $time The elapsed time (ms) to log
+ **/
+ public static function timing($stats, $time) {
+ StatsD::updateStats($stats, $time, 1, 'ms');
+ }
+
+ /**
+ * Sets one or more gauges to a value
+ *
+ * @param string|array $stats The metric(s) to set.
+ * @param float $value The value for the stats.
+ **/
+ public static function gauge($stats, $value) {
+ StatsD::updateStats($stats, $value, 1, 'g');
+ }
+
+ /**
+ * A "Set" is a count of unique events.
+ * This data type acts like a counter, but supports counting
+ * of unique occurences of values between flushes. The backend
+ * receives the number of unique events that happened since
+ * the last flush.
+ *
+ * The reference use case involved tracking the number of active
+ * and logged in users by sending the current userId of a user
+ * with each request with a key of "uniques" (or similar).
+ *
+ * @param string|array $stats The metric(s) to set.
+ * @param float $value The value for the stats.
**/
- public static function timing($stat, $time, $sampleRate=1) {
- StatsD::send(array($stat => "$time|ms"), $sampleRate);
+ public static function set($stats, $value) {
+ StatsD::updateStats($stats, $value, 1, 's');
}
/**
@@ -26,7 +53,7 @@ public static function timing($stat, $time, $sampleRate=1) {
* @return boolean
**/
public static function increment($stats, $sampleRate=1) {
- StatsD::updateStats($stats, 1, $sampleRate);
+ StatsD::updateStats($stats, 1, $sampleRate, 'c');
}
/**
@@ -37,22 +64,23 @@ public static function increment($stats, $sampleRate=1) {
* @return boolean
**/
public static function decrement($stats, $sampleRate=1) {
- StatsD::updateStats($stats, -1, $sampleRate);
+ StatsD::updateStats($stats, -1, $sampleRate, 'c');
}
/**
- * Updates one or more stats counters by arbitrary amounts.
+ * Updates one or more stats.
*
* @param string|array $stats The metric(s) to update. Should be either a string or array of metrics.
* @param int|1 $delta The amount to increment/decrement each metric by.
* @param float|1 $sampleRate the rate (0-1) for sampling.
+ * @param string|c $metric The metric type ("c" for count, "ms" for timing, "g" for gauge, "s" for set)
* @return boolean
**/
- public static function updateStats($stats, $delta=1, $sampleRate=1) {
+ public static function updateStats($stats, $delta=1, $sampleRate=1, $metric='c') {
if (!is_array($stats)) { $stats = array($stats); }
$data = array();
foreach($stats as $stat) {
- $data[$stat] = "$delta|c";
+ $data[$stat] = "$delta|$metric";
}
StatsD::send($data, $sampleRate);
@@ -137,4 +165,4 @@ public function getConfig($name)
host = yourhost
port = 8125
-*/
+*/
View
2 config.js → lib/config.js
@@ -21,7 +21,7 @@ var Configurator = function (file) {
this.updateConfig();
- fs.watchFile(file, function (curr, prev) {
+ fs.watch(file, function (curr, prev) {
if (curr.ino != prev.ino) { self.updateConfig(); }
});
};
View
4 lib/logger.js
@@ -18,9 +18,9 @@ Logger.prototype = {
log: function (msg, type) {
if (this.backend == 'stdout') {
if (!type) {
- type = 'DEBUG: ';
+ type = 'DEBUG';
}
- this.util.log(type + msg);
+ this.util.log(type + ": " + msg);
} else {
if (!type) {
type = this.level
View
25 stats.js
@@ -1,7 +1,7 @@
var dgram = require('dgram')
, util = require('util')
, net = require('net')
- , config = require('./config')
+ , config = require('./lib/config')
, fs = require('fs')
, events = require('events')
, logger = require('./lib/logger')
@@ -160,8 +160,15 @@ config.configFile(process.argv[2], function (config, oldConfig) {
}
sets[key].insert(fields[0] || '0');
} else {
- if (fields[2] && fields[2].match(/^@([\d\.]+)/)) {
- sampleRate = Number(fields[2].match(/^@([\d\.]+)/)[1]);
+ if (fields[2]) {
+ if (fields[2].match(/^@([\d\.]+)/)) {
+ sampleRate = Number(fields[2].match(/^@([\d\.]+)/)[1]);
+ } else {
+ l.log('Bad line: ' + fields + ' in msg "' + metrics[midx] +'"; has invalid sample rate');
+ counters["statsd.bad_lines_seen"]++;
+ stats['messages']['bad_lines_seen']++;
+ continue;
+ }
}
if (! counters[key]) {
counters[key] = 0;
@@ -306,7 +313,7 @@ config.configFile(process.argv[2], function (config, oldConfig) {
if (keyFlushInterval > 0) {
var keyFlushPercent = Number((config.keyFlush && config.keyFlush.percent) || 100);
- var keyFlushLog = (config.keyFlush && config.keyFlush.log) || "stdout";
+ var keyFlushLog = config.keyFlush && config.keyFlush.log;
keyFlushInt = setInterval(function () {
var key;
@@ -326,9 +333,13 @@ config.configFile(process.argv[2], function (config, oldConfig) {
logMessage += timeString + " count=" + sortedKeys[i][1] + " key=" + sortedKeys[i][0] + "\n";
}
- var logFile = fs.createWriteStream(keyFlushLog, {flags: 'a+'});
- logFile.write(logMessage);
- logFile.end();
+ if (keyFlushLog) {
+ var logFile = fs.createWriteStream(keyFlushLog, {flags: 'a+'});
+ logFile.write(logMessage);
+ logFile.end();
+ } else {
+ process.stdout.write(logMessage);
+ }
// clear the counter
keyCounter = {};
View
33 test/graphite_tests.js
@@ -155,6 +155,39 @@ module.exports = {
});
},
+ send_malformed_post: function (test) {
+ test.expect(3);
+
+ var testvalue = 1;
+ var me = this;
+ this.acceptor.once('connection',function(c){
+ statsd_send('a_bad_test_value|z',me.sock,'127.0.0.1',8125,function(){
+ collect_for(me.acceptor,me.myflush*2,function(strings){
+ test.ok(strings.length > 0,'should receive some data');
+ var hashes = _.map(strings, function(x) {
+ var chunks = x.split(' ');
+ var data = {};
+ data[chunks[0]] = chunks[1];
+ return data;
+ });
+ var numstat_test = function(post){
+ var mykey = 'statsd.numStats';
+ return _.include(_.keys(post),mykey) && (post[mykey] == 2);
+ };
+ test.ok(_.any(hashes,numstat_test), 'statsd.numStats should be 0');
+
+ var bad_lines_seen_value_test = function(post){
+ var mykey = 'stats_counts.statsd.bad_lines_seen';
+ return _.include(_.keys(post),mykey) && (post[mykey] == testvalue);
+ };
+ test.ok(_.any(hashes,bad_lines_seen_value_test), 'stats_counts.statsd.bad_lines_seen should be ' + testvalue);
+
+ test.done();
+ });
+ });
+ });
+ },
+
timers_are_valid: function (test) {
test.expect(3);

0 comments on commit 953063a

Please sign in to comment.