Zabbix监控redis status

概述

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

展开阅读全文

没有更多推荐了,返回首页