Skip to content

Instantly share code, notes, and snippets.

@jsocol
Forked from chowse/ClientStatsD.js
Created August 3, 2011 15:46
Show Gist options
  • Save jsocol/1122957 to your computer and use it in GitHub Desktop.
Save jsocol/1122957 to your computer and use it in GitHub Desktop.

Revisions

  1. Chris Howse created this gist Jun 22, 2011.
    145 changes: 145 additions & 0 deletions ClientStatsD.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,145 @@


    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);
    36 changes: 36 additions & 0 deletions ClientStatsD.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,36 @@

    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