Skip to content
This repository

Socket.io backend #102

Closed
wants to merge 5 commits into from

4 participants

Swizec Teller Don't Add Me To Your Organization a.k.a The Travis Bot Mike Heffner Daniel Schauenberg
Swizec Teller
Swizec commented June 14, 2012

Hey,

I implemented a socket.io backend so browser-side javascript can connect to a statsd server and receive stat dumps when they happen.

Cheers,
~Swizec

Don't Add Me To Your Organization a.k.a The Travis Bot

This pull request passes (merged 2a72ad6 into 4e4ed79).

Mike Heffner

@Swizec Very cool. My recommendation would be to implement this as a separate StatsD backend packaged as an NPM module. This separates your backend development and required dependencies from the main statsd daemon. Checkout this link for some backend module examples: https://github.com/etsy/statsd/wiki/Backends

Daniel Schauenberg
Owner
mrtazz commented June 18, 2012

Awesome idea! And yeah what @mheffner said :).

Swizec Teller
Swizec commented June 20, 2012

Turns out there's already a socket.io backend implemented as a module.

https://github.com/Chatham/statsd-socket.io

I should take better care to read the docs :)

Swizec Teller Swizec closed this June 20, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
128  backends/socket.io.js
... ...
@@ -0,0 +1,128 @@
  1
+
  2
+/*
  3
+ * Flush stats to socket.io sockets (http://socket.io/).
  4
+ *
  5
+ * To enable this backend, include 'socket.io' in the backends
  6
+ * configuration array:
  7
+ *
  8
+ *   backends: ['./backends/socket.io.js'']
  9
+ *
  10
+ * This backend supports the following config options:
  11
+ *
  12
+ *   socketioPort: Port to listen on.
  13
+ */
  14
+
  15
+var flushInterval;
  16
+
  17
+var socketioStats = {};
  18
+
  19
+var io = require('socket.io');
  20
+
  21
+
  22
+var flush_stats = function graphite_flush(ts, metrics) {
  23
+    var numStats = 0;
  24
+    var key;
  25
+    var stats = {perSecond: {},
  26
+                 counts: {},
  27
+                 timers: {},
  28
+                 gauges: {},
  29
+                 statsd: {},
  30
+                 timestamp: ts};
  31
+
  32
+    var counters = metrics.counters;
  33
+    var gauges = metrics.gauges;
  34
+    var timers = metrics.timers;
  35
+    var pctThreshold = metrics.pctThreshold;
  36
+
  37
+    for (key in counters) {
  38
+        var value = counters[key];
  39
+        var valuePerSecond = value / (flushInterval / 1000); // calculate "per second" rate
  40
+        stats.perSecond[key] = valuePerSecond;
  41
+        stats.counts[key] = value;
  42
+
  43
+        numStats += 1;
  44
+    }
  45
+
  46
+    for (key in timers) {
  47
+        if (timers[key].length > 0) {
  48
+            var values = timers[key].sort(function (a,b) { return a-b; });
  49
+            var count = values.length;
  50
+            var min = values[0];
  51
+            var max = values[count - 1];
  52
+
  53
+            var mean = min;
  54
+            var maxAtThreshold = max;
  55
+
  56
+            var message = "";
  57
+
  58
+            var key2;
  59
+
  60
+            stats.timers[key] = {};
  61
+
  62
+            for (key2 in pctThreshold) {
  63
+                var pct = pctThreshold[key2];
  64
+                if (count > 1) {
  65
+                    var thresholdIndex = Math.round(((100 - pct) / 100) * count);
  66
+                    var numInThreshold = count - thresholdIndex;
  67
+                    var pctValues = values.slice(0, numInThreshold);
  68
+                    maxAtThreshold = pctValues[numInThreshold - 1];
  69
+
  70
+                    // average the remaining timings
  71
+                    var sum = 0;
  72
+                    for (var i = 0; i < numInThreshold; i++) {
  73
+                        sum += pctValues[i];
  74
+                    }
  75
+
  76
+                    mean = sum / numInThreshold;
  77
+                }
  78
+
  79
+                var clean_pct = '' + pct;
  80
+                clean_pct.replace('.', '_');
  81
+
  82
+                stats.timers[key]['mean_'+clean_pct] = mean;
  83
+                stats.timers[key]['upper_'+clean_pct] = maxAtThreshold;
  84
+            }
  85
+
  86
+            stats.timers[key].upper = max;
  87
+            stats.timers[key].lower = min;
  88
+            stats.timers[key].count = count;
  89
+
  90
+            numStats += 1;
  91
+        }
  92
+    }
  93
+
  94
+    for (key in gauges) {
  95
+        stats.gauges[key] = gauges[key];
  96
+
  97
+        numStats += 1;
  98
+    }
  99
+
  100
+    stats.statsd.numStats = numStats;
  101
+
  102
+
  103
+    io.sockets.volatile.emit('statsd', stats);
  104
+    socketioStats.last_flush = Math.round(new Date().getTime() / 1000);
  105
+};
  106
+
  107
+var backend_status = function socketio_status(writeCb) {
  108
+    for (var stat in socketioStats) {
  109
+        writeCb(null, 'socketio', stat, socketioStats[stat]);
  110
+    }
  111
+
  112
+    writeCb(null, 'socketio', 'sockets', io.sockets.length);
  113
+};
  114
+
  115
+
  116
+exports.init = function socketio_init(startup_time, config, events) {
  117
+
  118
+    io = io.listen(config.socketioPort);
  119
+
  120
+    socketioStats.last_flush = startup_time;
  121
+
  122
+    flushInterval = config.flushInterval;
  123
+
  124
+    events.on('flush', flush_stats);
  125
+    events.on('status', backend_status);
  126
+
  127
+    return true;
  128
+};
3  package.json
@@ -16,7 +16,8 @@
16 16
     "nodeunit": "0.6.x",
17 17
     "async": "0.1.x",
18 18
     "underscore": "1.2.x",
19  
-    "temp": "0.4.x"
  19
+    "temp": "0.4.x",
  20
+    "socket.io": "0.9.x"
20 21
   },
21 22
   "engine": {
22 23
     "node" : ">=0.4"
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.