Last active
December 20, 2015 16:29
-
-
Save zircote/6161466 to your computer and use it in GitHub Desktop.
redis statsd collection
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
#!/usr/bin/env python | |
import redis | |
import statsd | |
import time | |
import argparse | |
import logging | |
import sys | |
import os | |
#: redis info keys | |
DEFAULT_REDIS_PORT = 6379 | |
DEFAULT_REDIS_HOST = "localhost" | |
GAUGES = [ | |
'used_memory', | |
'used_memory_lua', | |
'used_memory_rss', | |
'mem_fragmentation_ratio', | |
'pubsub_channels', | |
'pubsub_patterns', | |
'rdb_saves', | |
'rdb_changes_since_last_save', | |
'aof_last_rewrite_time_sec', | |
'aof_last_rewrite_time_sec', | |
'blocked_clients', | |
'aof_rewrites', | |
'client_biggest_input_buf', | |
'client_longest_output_list', | |
'connected_clients', | |
'connected_slaves', | |
'evicted_keys', | |
'expired_keys', | |
'latest_fork_usec', | |
'instantaneous_ops_per_sec', | |
'rdb_last_bgsave_time_sec', | |
'rdb_changes_since_last_save', | |
'rdb_current_bgsave_time_sec', | |
'total_commands_processed', | |
'total_connections_received', | |
'rejected_connections', | |
'used_memory_peak', | |
'used_cpu_sys', | |
'used_cpu_sys_children', | |
'used_cpu_user', | |
'used_cpu_user_children', | |
'keyspace_read_hits', | |
'keyspace_read_misses', | |
'keyspace_write_hits', | |
'keyspace_write_misses', | |
] | |
parser = argparse.ArgumentParser('A python script to monitor and submit statistics to a statsd endpoint') | |
parser.add_argument("-s", "--server", type=str, default='localhost:6379', | |
help="the server(s) ',' delimited to collect stats from example:[test.com:6379,test.com]") | |
parser.add_argument("--namespace-service", help="the service namespace key for statsd", | |
default='redis', type=str) | |
parser.add_argument("-v", "--verbose", help="print the statsd namespaces being monitored", action="store_true") | |
parser.add_argument("-f", "--frequency", help="frequency to collect statistics in seconds [1]", default=1, type=int) | |
parser.add_argument("--statsd-host", help="statsd server address", default=DEFAULT_REDIS_HOST, type=str) | |
parser.add_argument("--statsd-port", help="statsd server port", default=8125, type=int) | |
parser.add_argument("--statsd-sample-rate", help="statsd sample rate", default=1, type=int) | |
parser.add_argument("--detach", help="detach process and run in background", action="store_true") | |
parser.add_argument("-l", "--loglevel", help="enable debugging", choices=('DEBUG', 'INFO', 'ERROR', 'CRITICAL', 'FATAL'), | |
default="INFO") | |
parser.add_argument("--namespace-format", default="{host}.{service_name}.{port}", type=str, | |
help="the namespace key format") | |
args = parser.parse_args() | |
'''Script Entry point | |
''' | |
def main(): | |
REDIS_SERVERS = dict() | |
logging.basicConfig(level=args.loglevel) | |
for server in args.server.split(','): | |
if server.find(':') > 0: | |
server, port = server.split(':') | |
else: | |
port = str(DEFAULT_REDIS_PORT) | |
ns = args.namespace_format.format(host=server.replace('.', '_'), port=port, service_name=args.namespace_service) | |
logging.info("ADDING redis host [%s] to statsd monitoring" % ns) | |
REDIS_SERVERS[ns] = redis.StrictRedis(host=server, port=int(port)) | |
statsd.Connection.set_defaults(host=args.statsd_host, port=args.statsd_port, sample_rate=args.statsd_sample_rate) | |
logging.debug("starting redis statsd monitoring with arguments: [%s]" % args) | |
while True: | |
for _server in REDIS_SERVERS: | |
try: | |
info = REDIS_SERVERS[_server].info() | |
log_gauges(_server, info) | |
except redis.RedisError as e: | |
logging.error(e) | |
time.sleep(args.frequency) | |
'''statsd redis host info parsing and logging | |
:param ns: the toplevel namespace to log the data into | |
:param info: the redis info dict | |
''' | |
def log_gauges(ns, info): | |
g = statsd.Gauge(ns) | |
for n in GAUGES: | |
if n in info: | |
g.send(n, info[n]) | |
for key in info: | |
if key[0:2] == 'db': | |
g.send('%s.expires' % key, info[key]['expires']) | |
g.send('%s.keys' % key, info[key]['keys']) | |
if __name__ == "__main__": | |
try: | |
if args.detach and os.fork(): | |
sys.exit() | |
main() | |
except OSError, e: | |
raise Exception("%s [%d]" % (e.strerror, e.errno)) |
Author
zircote
commented
Aug 6, 2013
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment