概述
zabbix采用Trapper方式监控redis status
原理
redis-cli info命令得到redis服务器的统计信息,脚本对信息分两部分处理:
(1)# Keyspace部分为Zabbix agent,因为不确定db的数目所以此段的items也不确定,Zabbix server需要low level discovery(redis.discovery脚本)来确定db的数目以确定对redis服务器发起哪些items请求
(2)其余部分为Zabbix trapper,脚本整理这些信息并向Zabbix server发送(items要事先定义好)
配置
(1)Zabbix agent
low level discovery
item prototypes
userparameter_redis.conf
#Redis UserParameter=redis.discovery,/m2odata/server/zabbix-agent/scripts/lld-redis.py -a password UserParameter=redis[*],/m2odata/server/zabbix-agent/scripts/redis_zabbix.py $1 $2 $3 -a password
lld-redis.py
#!/usr/bin/env python #-*- coding: utf-8 -*- __author__ = \'pdd\' __date__ = \'2016/11/28\' \'\'\' redis db low level discovery \'\'\' import re import json import redis def discovery(host, port, password): client = redis.StrictRedis(host=host, port=port, password=password) server_info = client.info() dbs = [(\'db%d\' % x) for x in range(0,16) if (\'db%d\' % x) in server_info] # redis默认15个db data = [{"{#DBNAME}": db} for db in dbs] print(json.dumps({"data": data}, indent=4)) if __name__==\'__main__\': host = \'127.0.0.1\' port = 6379 password = \'password\' discovery(host, port, password)
(2)Zabbix trapper # 一分钟发送一次数据到Zabbix server
*/1 * * * * /storage/server/zabbix-agent/scripts/redis_zabbix.py -a password
redis_zabbix.py
#!/usr/bin/python import redis, json, re, struct, time, socket, argparse parser = argparse.ArgumentParser(description=\'Zabbix Redis status script\') parser.add_argument(\'redis_hostname\',nargs=\'?\') parser.add_argument(\'metric\',nargs=\'?\') parser.add_argument(\'db\',default=\'none\',nargs=\'?\') parser.add_argument(\'-p\',\'--port\',dest=\'redis_port\',action=\'store\',help=\'Redis server port\',default=6379,type=int) parser.add_argument(\'-a\',\'--auth\',dest=\'redis_pass\',action=\'store\',help=\'Redis server pass\',default=None) args = parser.parse_args() zabbix_host = \'127.0.0.1\' #IP address of Zabbix Server # Zabbix Server IP zabbix_port = 10051 # Zabbix Server Port # Name of monitored server like it shows in zabbix web ui display redis_hostname = args.redis_hostname if args.redis_hostname else socket.gethostname() class Metric(object): def __init__(self, host, key, value, clock=None): self.host = host self.key = key self.value = value self.clock = clock def __repr__(self): result = None if self.clock is None: result = \'Metric(%r, %r, %r)\' % (self.host, self.key, self.value) else: result = \'Metric(%r, %r, %r, %r)\' % (self.host, self.key, self.value, self.clock) return result def send_to_zabbix(metrics, zabbix_host, zabbix_port): result = None j = json.dumps metrics_data = [] for m in metrics: clock = m.clock or (\'%d\' % time.time()) metrics_data.append((\'{"host":%s,"key":%s,"value":%s,"clock":%s}\') % (j(m.host), j(m.key), j(m.value), j(clock))) json_data = (\'{"request":"sender data","data":[%s]}\') % (\',\'.join(metrics_data)) data_len = struct.pack(\'<Q\', len(json_data)) packet = \'ZBXD\x01\'+ data_len + json_data # For debug: #print(packet) #print(\':\'.join(x.encode(\'hex\') for x in packet)) try: zabbix = socket.socket() zabbix.connect((zabbix_host, zabbix_port)) zabbix.sendall(packet) resp_hdr = _recv_all(zabbix, 13) if not resp_hdr.startswith(\'ZBXD\x01\') or len(resp_hdr) != 13: print(\'Wrong zabbix response\') result = False else: resp_body_len = struct.unpack(\'<Q\', resp_hdr[5:])[0] resp_body = zabbix.recv(resp_body_len) zabbix.close() resp = json.loads(resp_body) # For debug # print(resp) if resp.get(\'response\') == \'success\': result = True else: print(\'Got error from Zabbix: %s\' % resp) result = False except: print(\'Error while sending data to Zabbix\') result = False finally: return result def _recv_all(sock, count): buf = \'\' while len(buf)<count: chunk = sock.recv(count-len(buf)) if not chunk: return buf buf += chunk return buf def main(): if redis_hostname and args.metric: client = redis.StrictRedis(host=redis_hostname, port=args.redis_port, password=args.redis_pass) server_info = client.info() if args.metric: if args.db and args.db in server_info.keys(): server_info[\'key_space_db_keys\'] = server_info[args.db][\'keys\'] server_info[\'key_space_db_expires\'] = server_info[args.db][\'expires\'] server_info[\'key_space_db_avg_ttl\'] = server_info[args.db][\'avg_ttl\'] def list_key_space_db(): if args.db in server_info: print(args.db) else: print(\'database_detect\') def default(): if args.metric in server_info.keys(): print(server_info[args.metric]) { \'list_key_space_db\': list_key_space_db, }.get(args.metric, default)() else: print(\'Not selected metric\'); else: client = redis.StrictRedis(host=redis_hostname, port=args.redis_port, password=args.redis_pass) server_info = client.info() a = [] for i in server_info: a.append(Metric(redis_hostname, (\'redis[%s]\' % i), server_info[i])) # Send packet to zabbix send_to_zabbix(a, zabbix_host, zabbix_port) if __name__ == \'__main__\': main()
参考:https://github.com/blacked/zbx_redis_template