Last active
December 11, 2015 02:52
-
-
Save tclh123/09165070feac5b50006d to your computer and use it in GitHub Desktop.
from statsd examples
This file contains hidden or 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
# Steve Ivy <[email protected]> | |
# http://monkinetic.com | |
from random import random | |
from socket import socket, AF_INET, SOCK_DGRAM | |
class StatsdClient(object): | |
SC_TIMING = "ms" | |
SC_COUNT = "c" | |
SC_GAUGE = "g" | |
SC_SET = "s" | |
def __init__(self, host='localhost', port=8125): | |
""" | |
Sends statistics to the stats daemon over UDP | |
>>> from python_example import StatsdClient | |
""" | |
self.addr = (host, port) | |
def timing(self, stats, value): | |
""" | |
Log timing information | |
>>> client = StatsdClient() | |
>>> client.timing('example.timing', 500) | |
>>> client.timing(('example.timing23', 'example.timing29'), 500) | |
""" | |
self.update_stats(stats, value, self.SC_TIMING) | |
def gauge(self, stats, value): | |
""" | |
Log gauges | |
>>> client = StatsdClient() | |
>>> client.gauge('example.gauge', 47) | |
>>> client.gauge(('example.gauge41', 'example.gauge43'), 47) | |
""" | |
self.update_stats(stats, value, self.SC_GAUGE) | |
def set(self, stats, value): | |
""" | |
Log set | |
>>> client = StatsdClient() | |
>>> client.set('example.set', "set") | |
>>> client.set(('example.set61', 'example.set67'), "2701") | |
""" | |
self.update_stats(stats, value, self.SC_SET) | |
def increment(self, stats, sample_rate=1): | |
""" | |
Increments one or more stats counters | |
>>> client = StatsdClient() | |
>>> client.increment('example.increment') | |
>>> client.increment('example.increment', 0.5) | |
""" | |
self.count(stats, 1, sample_rate) | |
def decrement(self, stats, sample_rate=1): | |
""" | |
Decrements one or more stats counters | |
>>> client = StatsdClient() | |
>>> client.decrement('example.decrement') | |
""" | |
self.count(stats, -1, sample_rate) | |
def count(self, stats, value, sample_rate=1): | |
""" | |
Updates one or more stats counters by arbitrary value | |
>>> client = StatsdClient() | |
>>> client.count('example.counter', 17) | |
""" | |
self.update_stats(stats, value, self.SC_COUNT, sample_rate) | |
def update_stats(self, stats, value, _type, sample_rate=1): | |
""" | |
Pipeline function that formats data, samples it and passes to send() | |
>>> client = StatsdClient() | |
>>> client.update_stats('example.update_stats', 73, "c", 0.9) | |
""" | |
stats = self.format(stats, value, _type) | |
self.send(self.sample(stats, sample_rate), self.addr) | |
@staticmethod | |
def format(keys, value, _type): | |
""" | |
General format function. | |
>>> StatsdClient.format("example.format", 2, "T") | |
{'example.format': '2|T'} | |
>>> formatted = StatsdClient.format(("example.format31", "example.format37"), "2", "T") | |
>>> formatted['example.format31'] == '2|T' | |
True | |
>>> formatted['example.format37'] == '2|T' | |
True | |
>>> len(formatted) | |
2 | |
""" | |
data = {} | |
value = "{0}|{1}".format(value, _type) | |
# TODO: Allow any iterable except strings | |
if not isinstance(keys, (list, tuple)): | |
keys = [keys] | |
for key in keys: | |
data[key] = value | |
return data | |
@staticmethod | |
def sample(data, sample_rate): | |
""" | |
Sample data dict | |
TODO(rbtz@): Convert to generator | |
>>> StatsdClient.sample({"example.sample2": "2"}, 1) | |
{'example.sample2': '2'} | |
>>> StatsdClient.sample({"example.sample3": "3"}, 0) | |
{} | |
>>> from random import seed | |
>>> seed(1) | |
>>> sampled = StatsdClient.sample({"example.sample5": "5", "example.sample7": "7"}, 0.99) | |
>>> len(sampled) | |
2 | |
>>> sampled['example.sample5'] | |
'5|@0.99' | |
>>> sampled['example.sample7'] | |
'7|@0.99' | |
>>> StatsdClient.sample({"example.sample5": "5", "example.sample7": "7"}, 0.01) | |
{} | |
""" | |
if sample_rate >= 1: | |
return data | |
elif sample_rate < 1: | |
if random() <= sample_rate: | |
sampled_data = {} | |
for stat, value in data.items(): | |
sampled_data[stat] = "{0}|@{1}".format(value, sample_rate) | |
return sampled_data | |
return {} | |
@staticmethod | |
def send(_dict, addr): | |
""" | |
Sends key/value pairs via UDP. | |
>>> StatsdClient.send({"example.send":"11|c"}, ("127.0.0.1", 8125)) | |
""" | |
# TODO(rbtz@): IPv6 support | |
# TODO(rbtz@): Creating socket on each send is a waste of recources | |
udp_sock = socket(AF_INET, SOCK_DGRAM) | |
# TODO(rbtz@): Add batch support | |
for item in _dict.items(): | |
udp_sock.sendto(":".join(item).encode('utf-8'), addr) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment