2011-02-16 08:17:48 +03:00
|
|
|
# python_example.py
|
|
|
|
|
|
|
|
# Steve Ivy <steveivy@gmail.com>
|
|
|
|
# http://monkinetic.com
|
2012-08-30 21:04:47 +04:00
|
|
|
|
2012-12-23 14:36:55 +04:00
|
|
|
from __future__ import print_function
|
2012-12-10 01:03:12 +04:00
|
|
|
from random import random
|
|
|
|
from socket import socket, AF_INET, SOCK_DGRAM
|
|
|
|
|
2012-11-12 20:42:47 +04:00
|
|
|
class StatsdClient(object):
|
2012-11-12 20:23:56 +04:00
|
|
|
def __init__(self, host='localhost', port=8125):
|
2012-12-23 19:15:43 +04:00
|
|
|
"""
|
|
|
|
Sends statistics to the stats daemon over UDP
|
|
|
|
|
|
|
|
>>> from python_example import StatsdClient
|
|
|
|
"""
|
2012-12-10 01:00:36 +04:00
|
|
|
self.addr = (host, port)
|
2012-11-12 20:20:43 +04:00
|
|
|
|
2012-12-23 19:18:34 +04:00
|
|
|
def timing(self, stat, time):
|
2011-02-16 08:26:43 +03:00
|
|
|
"""
|
|
|
|
Log timing information
|
2012-12-23 19:15:43 +04:00
|
|
|
|
2012-12-10 00:57:57 +04:00
|
|
|
>>> client = StatsdClient()
|
2012-12-23 19:15:43 +04:00
|
|
|
>>> client.timing('example.timing', 500)
|
2011-02-16 08:26:43 +03:00
|
|
|
"""
|
2011-02-17 19:27:47 +03:00
|
|
|
stats = {}
|
2012-12-23 15:13:19 +04:00
|
|
|
stats[stat] = "{0}|ms".format(time)
|
2012-12-23 19:18:34 +04:00
|
|
|
self.send(stats, self.addr)
|
2011-02-16 08:05:42 +03:00
|
|
|
|
2012-12-10 00:30:51 +04:00
|
|
|
def increment(self, stats, sample_rate=1):
|
2011-02-16 08:26:43 +03:00
|
|
|
"""
|
|
|
|
Increments one or more stats counters
|
2012-12-23 19:15:43 +04:00
|
|
|
|
2012-12-10 00:57:57 +04:00
|
|
|
>>> client = StatsdClient()
|
2012-12-23 19:15:43 +04:00
|
|
|
>>> client.increment('example.increment')
|
|
|
|
>>> client.increment('example.increment', 0.5)
|
2011-02-16 08:26:43 +03:00
|
|
|
"""
|
2012-12-10 00:30:51 +04:00
|
|
|
self.update_stats(stats, 1, sample_rate)
|
2011-02-16 08:05:42 +03:00
|
|
|
|
2012-12-10 00:30:51 +04:00
|
|
|
def decrement(self, stats, sample_rate=1):
|
2011-02-16 08:26:43 +03:00
|
|
|
"""
|
|
|
|
Decrements one or more stats counters
|
2012-12-23 19:15:43 +04:00
|
|
|
|
2012-12-10 00:57:57 +04:00
|
|
|
>>> client = StatsdClient()
|
2012-12-23 19:15:43 +04:00
|
|
|
>>> client.decrement('example.decrement')
|
2011-02-16 08:26:43 +03:00
|
|
|
"""
|
2012-12-10 00:30:51 +04:00
|
|
|
self.update_stats(stats, -1, sample_rate)
|
2012-08-30 21:04:47 +04:00
|
|
|
|
2012-12-10 00:30:51 +04:00
|
|
|
def update_stats(self, stats, delta=1, sampleRate=1):
|
2011-02-16 08:26:43 +03:00
|
|
|
"""
|
|
|
|
Updates one or more stats counters by arbitrary amounts
|
2012-12-23 19:15:43 +04:00
|
|
|
|
2012-12-10 00:57:57 +04:00
|
|
|
>>> client = StatsdClient()
|
2012-12-23 19:15:43 +04:00
|
|
|
>>> client.update_stats('example.update_stats', 17)
|
2011-02-16 08:26:43 +03:00
|
|
|
"""
|
2012-12-23 14:40:39 +04:00
|
|
|
if not isinstance(stats, list):
|
2011-02-16 08:05:42 +03:00
|
|
|
stats = [stats]
|
|
|
|
data = {}
|
|
|
|
for stat in stats:
|
2012-12-23 15:13:19 +04:00
|
|
|
data[stat] = "{0}|c".format(delta)
|
2012-12-23 19:01:21 +04:00
|
|
|
self.sample_send(data, sampleRate)
|
2012-08-30 21:04:47 +04:00
|
|
|
|
2012-12-23 19:01:21 +04:00
|
|
|
def sample_send(self, data, sample_rate=1):
|
2011-02-16 08:26:43 +03:00
|
|
|
"""
|
2012-12-23 19:01:21 +04:00
|
|
|
Sample and squirt the metrics over UDP
|
|
|
|
|
|
|
|
>>> client = StatsdClient()
|
|
|
|
>>> client.sample_send({"example.sample_send": "13|c"}, 1)
|
|
|
|
True
|
2011-02-16 08:26:43 +03:00
|
|
|
"""
|
2012-12-23 19:01:21 +04:00
|
|
|
return self.send(self.sample(data, sample_rate), self.addr)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def sample(data, sample_rate=1):
|
|
|
|
"""
|
|
|
|
Sample data dict
|
|
|
|
TODO(rbtz@): Convert to generator
|
2012-08-30 21:04:47 +04:00
|
|
|
|
2012-12-23 19:01:21 +04:00
|
|
|
>>> StatsdClient.sample({"example.sample2": "2"}, 1)
|
|
|
|
{'example.sample2': '2'}
|
|
|
|
>>> StatsdClient.sample({"example.sample3": "3"}, 0)
|
|
|
|
{}
|
|
|
|
>>> from random import seed
|
|
|
|
>>> seed(1)
|
|
|
|
>>> StatsdClient.sample({"example.sample5": "5", "example.sample7": "7"}, 0.99)
|
|
|
|
{'example.sample5': '5|@0.99', 'example.sample7': '7|@0.99'}
|
|
|
|
>>> StatsdClient.sample({"example.sample5": "5", "example.sample7": "7"}, 0.01)
|
|
|
|
{}
|
|
|
|
"""
|
|
|
|
sampled_data = {}
|
|
|
|
if 0 < sample_rate < 1:
|
2012-12-10 01:03:12 +04:00
|
|
|
if random() <= sample_rate:
|
2012-12-10 00:49:34 +04:00
|
|
|
for stat, value in data.items():
|
2012-12-23 15:13:19 +04:00
|
|
|
sampled_data[stat] = "{0}|@{1}".format(value, sample_rate)
|
2012-12-23 19:01:21 +04:00
|
|
|
elif sample_rate == 0:
|
|
|
|
sampled_data = {}
|
2011-02-16 08:05:42 +03:00
|
|
|
else:
|
2012-12-10 01:00:36 +04:00
|
|
|
sampled_data = data
|
2012-12-23 19:01:21 +04:00
|
|
|
return sampled_data
|
2012-08-30 21:04:47 +04:00
|
|
|
|
2012-12-23 19:01:21 +04:00
|
|
|
@staticmethod
|
|
|
|
def send(_dict, addr):
|
|
|
|
"""
|
|
|
|
Sends key/value pairs via UDP.
|
|
|
|
|
|
|
|
>>> StatsdClient.send({"example.send":"11|c"}, ("127.0.0.1", 8125))
|
|
|
|
True
|
|
|
|
"""
|
|
|
|
# TODO(rbtz@): IPv6 support
|
2011-02-16 08:05:42 +03:00
|
|
|
udp_sock = socket(AF_INET, SOCK_DGRAM)
|
|
|
|
try:
|
2012-12-23 19:01:21 +04:00
|
|
|
# TODO(rbtz@): Add batch support
|
|
|
|
for item in _dict.items():
|
|
|
|
udp_sock.sendto(":".join(item).encode('utf-8'), addr)
|
2012-12-10 00:42:43 +04:00
|
|
|
except Exception:
|
2011-02-16 08:17:48 +03:00
|
|
|
import sys
|
2012-12-10 00:44:48 +04:00
|
|
|
import traceback
|
2012-12-23 14:36:55 +04:00
|
|
|
print("Unexpected error: ", traceback.format_exc(), file=sys.stderr)
|
2012-12-10 00:47:10 +04:00
|
|
|
return False
|
|
|
|
return True
|
2012-11-12 20:20:43 +04:00
|
|
|
|
|
|
|
|
|
|
|
if __name__=="__main__":
|
|
|
|
c = StatsdClient()
|
|
|
|
c.increment('example.python')
|