Add graphite gauge support

Add a new data type gauge for tracking absolute values.
This commit is contained in:
aaditya sood 2013-02-07 16:57:38 +05:30 committed by Patrick Hensley
parent 903f8d3934
commit 7c64944a7b
4 changed files with 40 additions and 7 deletions

View File

@ -20,10 +20,13 @@ class StatsClient(object):
hostport = StatsClient.HOSTPORT
self._hostport = hostport
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def timer(self, key, timestamp, sample_rate=1):
self._send('%s:%d|ms' % (key, round(timestamp)), sample_rate)
def gauge(self, key, value, sample_rate=1):
self._send('%s:%d|g' % (key, value), sample_rate)
def increment(self, key, sample_rate=1):
return self.counter(key, 1, sample_rate)
@ -85,6 +88,17 @@ class StatsTimer(object):
self._started = 0
class StatsGauge(object):
def __init__(self, client, key, sample_rate=1):
self._client = client
self._key = key
self._sample_rate = sample_rate
def set(self, value):
self._client.gauge(self._key, value, self._sample_rate)
class Stats(object):
def __init__(self, client):
@ -96,3 +110,5 @@ class Stats(object):
def get_timer(self, key):
return StatsTimer(self._client, key)
def get_gauge(self, key):
return StatsGauge(self._client, key)

View File

@ -53,6 +53,14 @@ class StatsClientTest(unittest.TestCase):
self._cli.counter('foo', 1, 0.2)
self.assertEquals(self._cli.packets[-1], ('foo:1|c', 0.2))
def test_gauge(self):
self._cli.gauge('foo', 5)
self.assertEquals(self._cli.packets[-1], ('foo:5|g', 1))
self._cli.counter('foo', -50)
self.assertEquals(self._cli.packets[-1], ('foo:-50|g', 1))
self._cli.counter('foo', 5.9)
self.assertEquals(self._cli.packets[-1], ('foo:5.9|g', 1))
class StatsTest(unittest.TestCase):
@ -86,4 +94,3 @@ def main():
if __name__ == '__main__':
main()

View File

@ -48,6 +48,7 @@ class Stats(object):
def __init__(self):
self.timers = defaultdict(list)
self.counts = defaultdict(float)
self.gauges = defaultdict(float)
self.percent = PERCENT
self.interval = INTERVAL
@ -163,7 +164,7 @@ class StatsDaemon(object):
self._flush_task = gevent.spawn(_flush_impl)
# start accepting connections
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
socket.IPPROTO_UDP)
self._sock.bind(self._bindaddr)
while 1:
@ -206,12 +207,16 @@ class StatsDaemon(object):
srate = float(fields[2][1:])
value = float(value if value else 1) * (1 / srate)
stats.counts[key] += value
elif stype == 'g':
value = float(value if value else 1)
stats.gauges[key] = value
def main():
opts = optparse.OptionParser(description=DESCRIPTION, version=__version__,
add_help_option=False)
opts.add_option('-b', '--bind', dest='bind_addr', default=':8125',
opts.add_option('-b', '--bind', dest='bind_addr', default=':8125',
help="bind [host]:port (host defaults to '')")
opts.add_option('-s', '--sink', dest='sink', action='append', default=[],
help="a graphite service to which stats are sent ([host]:port).")
@ -239,8 +244,7 @@ def main():
sd = StatsDaemon(options.bind_addr, options.sink, options.interval,
options.percent, options.verbose)
sd.start()
if __name__ == '__main__':
main()

View File

@ -86,6 +86,13 @@ class GraphiteSink(Sink):
buf.write('stats_counts.%s %f %d\n' % (key, val, now))
num_stats += 1
# counter stats
gauges = stats.gauges
for key, val in gauges.iteritems():
buf.write('stats.%s %f %d\n' % (key, val, now))
buf.write('stats_counts.%s %f %d\n' % (key, val, now))
num_stats += 1
buf.write('statsd.numStats %d %d\n' % (num_stats, now))
# TODO: add support for N retries
@ -99,4 +106,3 @@ class GraphiteSink(Sink):
sock.close()
except Exception, ex:
self.error(E_SENDFAIL % ('graphite', host, ex))