-
-
Save jsocol/1122957 to your computer and use it in GitHub Desktop.
StatsD for Client-Side Interactions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (!Date.now) { | |
Date.now = function() { | |
return (new Date()).getTime(); | |
}; | |
} | |
var StatsD = (function($, undefined) { | |
var activeTimers = { }; | |
var queuedData = [ ]; | |
var flushTimer = undefined; | |
var configOpts = { | |
url: '/statsd', | |
flushInterval: 1000 | |
}; | |
/** | |
* Update the client configuration of StatsD. | |
* @param opts an object containing new configuration values | |
*/ | |
function config(opts) { | |
$.extend(configOpts, opts); | |
} | |
/** | |
* Update a stat by an arbitrary amount. | |
* @param {String} stat the name of the stat to update | |
* @param {Number} delta the amount to update the stat by | |
* @param {Number} [sampleRate] a number between 0 and 1 indicating what percentage of this stat to sample | |
*/ | |
function update(stat, delta, sampleRate) { | |
queue(stat, delta+"|c", sampleRate); | |
} | |
/** | |
* Increment a stat by 1. | |
* @param {String} stat the name of the stat to update | |
* @param {Number} [sampleRate] a number between 0 and 1 indicating what percentage of this stat to sample | |
*/ | |
function increment(stat, sampleRate) { | |
update(stat, 1, sampleRate); | |
} | |
/** | |
* Decrement a stat by 1. | |
* @param {String} stat the name of the stat to update | |
* @param {Number} [sampleRate] a number between 0 and 1 indicating what percentage of this stat to sample | |
*/ | |
function decrement(stat, sampleRate) { | |
update(stat, -1, sampleRate); | |
} | |
/** | |
* Log timing information. | |
* @param {String} stat the name of the stat to update | |
* @param {Number} ms the time (in ms) to log | |
* @param {Number} [sampleRate] a number between 0 and 1 indicating what percentage of this stat to record | |
*/ | |
function timing(stat, ms, sampleRate) { | |
send(stat, ms+"|ms", sampleRate); | |
} | |
/** | |
* Start a timer that, when completed with stopTiming(), will log timing information. | |
* @param {String} stat the name of the stat to update | |
*/ | |
function startTiming(stat) { | |
activeTimers[stat] = Date.now(); | |
} | |
/** | |
* Stop a running timer and log the amount of time (in ms) since it was started. | |
* @param {String} stat the name of the stat to update | |
* @param {Number} [sampleRate] a number between 0 and 1 indicating what percentage of this stat to sample | |
*/ | |
function stopTiming(stat, sampleRate) { | |
var start = activeTimers[stat]; | |
delete activeTimers[stat]; | |
if (start) { | |
timing(stat, Date.now() - start); | |
} | |
} | |
/** | |
* Queues up a piece of StatsD data to be sent to the server. | |
* @param {String} method the type of data that is being queues | |
* @param {String} stat the name of the stat being queued | |
* @param {String} value the value of the stat being queued | |
* @param {Number} [sampleRate] a number between 0 and 1 indicating what percentage of this stat to sample | |
*/ | |
function queue(stat, value, sampleRate) { | |
var data = stat+":"+value; | |
if (sampleRate !== undefined && sampleRate != 1) { | |
if (sampleRate < Math.random()) { | |
return; | |
} | |
data = data+"|@"+sampleRate; | |
} | |
queuedData.push(data); | |
if (configOpts.flushInterval <= 0) { | |
flush(); | |
} else if (!flushTimer) { | |
flushTimer = setTimeout(flush, configOpts.flushInterval); | |
} | |
} | |
/** | |
* Send any queued StatsD data to the server. This data is | |
* automatically sent at a regular interval specificed by the | |
* flushInterval config setting. | |
*/ | |
function flush() { | |
clearTimeout(flushTimer); | |
flushTimer = 0; | |
var data = queuedData.join('\n'); | |
queuedData.splice(0, queuedData.length); | |
$.ajax({ | |
type: "POST", | |
url: configOpts.url, | |
contentType: 'text/plain', | |
data: data | |
}); | |
} | |
return { | |
config: config, | |
update: update, | |
increment: increment, | |
decrement: decrement, | |
timing: timing, | |
startTiming: startTiming, | |
stopTiming: stopTiming, | |
flush: flush | |
}; | |
})(jQuery); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.http import HttpResponse | |
import re, socket | |
VALID_STAT_RE = re.compile(r''' | |
^ # beginning of the string | |
\w+(\.\w+)*: # the name of the stat | |
-?\d+ # the stat's value | |
\|(c|ms) # the type of stat | |
(|@\d+(\.\d+)?)? # the sample rate | |
$ # end of the string | |
''') | |
# TODO: init from config | |
VALID_KEYS = set() | |
# TODO: init from config | |
STATSD_HOST = 'somehost' | |
STATSD_PORT = 9000 | |
STATSD_ADDR = (STATSD_HOST, STATSD_PORT) | |
def statsd_proxy(request): | |
for stat in request.read().split('\n'): | |
if not VALID_STAT_RE.match(stat): | |
continue | |
key, _, _ = stat.partition(':') | |
if key not in VALID_KEYS: | |
continue | |
try: | |
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
sock.sendto(stat, STATSD_ARRD) | |
except: | |
pass # Don't care |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment