statsd-client
Advanced tools
Comparing version 0.0.4 to 0.0.5
var dgram = require('dgram'); | ||
/*global console*/ | ||
function ephemeralSocket(options) { | ||
@@ -59,9 +61,32 @@ this.options = options || {}; | ||
/* | ||
* Send data. | ||
* Enqueue data to be sent when the socket is created | ||
*/ | ||
ephemeralSocket.prototype.send = function (data) { | ||
// Create socket if it isn't there | ||
ephemeralSocket.prototype._enqueue_data = function (data) { | ||
// Make sure our array exists | ||
this._enqueued_data = (this._enqueued_data || []); | ||
this._enqueued_data.push(data); | ||
}; | ||
/* | ||
* Callback called when socket is created. | ||
* When socket is ready, send all enqueued data, and mark as ready. | ||
*/ | ||
ephemeralSocket.prototype._on_socket_ready = function () { | ||
var self = this; | ||
this._socket_ready = true; | ||
// Exit early if we have no data enqueued | ||
if (!this._enqueued_data || this._enqueued_data.length === 0) { | ||
return; | ||
} | ||
this._enqueued_data.forEach(function (datum) { | ||
self.send(datum); | ||
}); | ||
this._enqueued_data = []; | ||
}; | ||
ephemeralSocket.prototype._create_socket = function () { | ||
if (!this._socket) { | ||
this._socket = dgram.createSocket('udp4'); | ||
this._socket = dgram.createSocket('udp4', this._on_socket_ready); | ||
// Start timer, if we have a positive timeout | ||
@@ -72,2 +97,18 @@ if (this.options.socket_timeout > 0) { | ||
} | ||
}; | ||
/* | ||
* Send data. | ||
*/ | ||
ephemeralSocket.prototype.send = function (data) { | ||
// If we don't have a socket, or we have created one but it isn't | ||
// ready yet, we need to enqueue data to send once the socket is ready. | ||
if (!this._socket || !this._socket_ready) { | ||
this._enqueue_data(data); | ||
if (!this._socket) { | ||
this._create_socket(); | ||
} | ||
return; | ||
} | ||
this._socket_used = true; | ||
@@ -82,2 +123,3 @@ | ||
this._socket.send(message, 0, message.length, this.options.port, this.options.host); | ||
@@ -84,0 +126,0 @@ }; |
@@ -12,2 +12,3 @@ var EphemeralSocket = require('./EphemeralSocket'), | ||
this.options = options || {}; | ||
this._helpers = undefined; | ||
@@ -21,3 +22,3 @@ // Set defaults | ||
var p = this.options.prefix; | ||
this.options.prefix = p[p.length] === '.' ? p : p + "."; | ||
this.options.prefix = p[p.length - 1] === '.' ? p : p + "."; | ||
} | ||
@@ -47,2 +48,9 @@ | ||
/* | ||
* set(name, value) | ||
*/ | ||
StatsDClient.prototype.set = function (name, value) { | ||
this._ephemeralSocket.send(this.options.prefix + name + ":" + value + "|s"); | ||
}; | ||
/* | ||
* counter(name, delta) | ||
@@ -86,66 +94,22 @@ */ | ||
/* | ||
* Hook the given listeners into `stream`. If no stream is given, an empty | ||
* proxy-stream with listeners implemented is returned, so that can be piped | ||
* from/to. | ||
* Return an object with available helpers. | ||
*/ | ||
StatsDClient.prototype._hookIntoStream = function (listeners, stream) { | ||
stream = stream || new ProxyStream(); | ||
StatsDClient.prototype.__defineGetter__('helpers', function () { | ||
if (!(this._helpers)) { | ||
var helpers = {}, | ||
that = this, | ||
files = require('fs').readdirSync(__dirname + '/helpers'); | ||
// Mount known listeners on the stream. | ||
['data', 'end', 'error', 'close'] | ||
.filter(function (listener) { | ||
return listener in listeners; | ||
}) | ||
.forEach(function (listener) { | ||
stream.on(listener, function (arg) { | ||
listeners[listener](arg); | ||
}); | ||
files.forEach(function (filename) { | ||
if (/\.js$/.test(filename) && filename !== 'index.js') { | ||
var name = filename.replace(/\.js$/, ''); | ||
helpers[name] = require('./helpers/' + filename)(that); | ||
} | ||
}); | ||
this._helpers = helpers; | ||
} | ||
return stream; | ||
}; | ||
return this._helpers; | ||
}); | ||
StatsDClient.prototype.measureStreamSize = function (key, stream) { | ||
var that = this; | ||
return this._hookIntoStream({ | ||
data: function (data) { | ||
that.increment(key, data.length); | ||
} | ||
}, stream); | ||
}; | ||
StatsDClient.prototype.measureStreamLatency = function (key, stream) { | ||
var startTime, | ||
that = this; | ||
return this._hookIntoStream({ | ||
data: function (data) { | ||
startTime = startTime || new Date(); | ||
}, | ||
end: function () { | ||
if (startTime) { | ||
that.timing(key, startTime); | ||
} | ||
} | ||
}, stream); | ||
}; | ||
StatsDClient.prototype.measureStreamBandwidth = function (key, stream) { | ||
var startTime, | ||
that = this, | ||
size = 0; | ||
return this._hookIntoStream({ | ||
data: function (data) { | ||
startTime = startTime || new Date(); | ||
size = size + data.length; | ||
}, | ||
end: function () { | ||
if (startTime) { | ||
var time = (new Date() - startTime) || 1; | ||
that.timing(key, size/time); | ||
} | ||
} | ||
}, stream); | ||
}; | ||
module.exports = StatsDClient; |
@@ -6,3 +6,3 @@ { | ||
"keywords": ["statsd", "client", "metrics", "udp"], | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"homepage": "https://github.com/msiebuhr/node-statsd-client", | ||
@@ -16,7 +16,11 @@ "bugs": "https://github.com/msiebuhr/node-statsd-client/issues", | ||
"dependencies": {}, | ||
"devDependencies": {}, | ||
"optionalDependencies": {}, | ||
"engines": { | ||
"node": "*" | ||
} | ||
"devDependencies": { | ||
"jshint": "*", | ||
"vows": "v0.6.2" | ||
}, | ||
"scripts": { | ||
"prepublish": "vows; jshint lib/ test/", | ||
"test": "vows --spec; jshint lib/ test/" | ||
}, | ||
"optionalDependencies": {} | ||
} |
@@ -6,2 +6,4 @@ node-statsd-client | ||
[![Build Status](https://secure.travis-ci.org/msiebuhr/node-statsd-client.png?branch=master)](http://travis-ci.org/msiebuhr/node-statsd-client) | ||
Quick tour | ||
@@ -51,2 +53,8 @@ ---------- | ||
### Sets | ||
Send unique occurences of events between flushes to the back-end: | ||
sdc.set('your.set', 200); | ||
### Delays | ||
@@ -78,14 +86,33 @@ | ||
// Option 1: Attach hooks directly to a stream (most effeicient) | ||
sdc.measureStreamSize('key_for_counter', source); | ||
sdc.helpers.streamSize('key_for_counter', source); | ||
// Option 2: Pipe through proxy-stream with hooks attached | ||
source | ||
.pipe(sdc.measureStreamLatency('key_for_timer')) | ||
.pipe(sdc.helpers.streamLatency('key_for_timer')) | ||
.pipe(dest); | ||
This will both measure the amount of data sent through the system | ||
(`.measureStreamSize(key, [stream])`) and how long it takes to get i through | ||
(`.measureStreamLatency(key, [stream])`). It is also possible to measure the | ||
total bandwith of the stream using `.measureStreamBandwidth(key, [stream])`. | ||
(`.streamSize(key, [stream])`) and how long it takes to get i through | ||
(`.streamLatency(key, [stream])`). It is also possible to measure the total | ||
bandwith of the stream using `.streamBandwidth(key, [stream])`. | ||
### Express helper | ||
There's also a helper for measuring stuff in [Express.js](http://expressjs.com) | ||
via middleware: | ||
var app = express(); | ||
sdc = new StatsDClient({...}); | ||
app.use(sdc.helpers.getExpressMiddleware('somePrefix')); | ||
// or | ||
app.get('/', | ||
sdc.helpers.getExpressMiddleware('otherPrefix'), | ||
function (req, res, next) { req.pipe(res); }); | ||
app.listen(3000); | ||
This will count responses by status-code (`prefix.<statuscode>`) and the | ||
overall response-times. | ||
### Stopping gracefully | ||
@@ -138,2 +165,2 @@ | ||
ISC - see | ||
[LICENSE.txt](https://github.com/msiebuhr/node-statsd-client/blob/master/LICENSE.txt). | ||
[LICENSE](https://github.com/msiebuhr/node-statsd-client/blob/master/LICENSE). |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18
514
163
23448
2
2
2