11#!/usr/bin/env python
2+ # -*- coding: utf-8 -*-
23''' Copyright (c) 2013 Jean Baptiste Favre.
34 Sample script for Zabbix integration with memcached.
45'''
89import protobix
910import memcache
1011
11- __version__ = "0.0.1"
12-
13- ZBX_CONN_ERR = "ERR - unable to send data to Zabbix [%s]"
14-
15- def parse_args ():
16- ''' Parse the script arguments
17- '''
18- parser = optparse .OptionParser ()
19-
20- parser .add_option ("-d" , "--dry" , action = "store_true" ,
21- help = "Performs Memcache call but do not send "
22- "anything to the Zabbix server. Can be used "
23- "for both Update & Discovery mode" )
24- parser .add_option ("-D" , "--debug" , action = "store_true" ,
25- help = "Enable debug mode. This will prevent bulk send "
26- "operations and force sending items one after the "
27- "other, displaying result for each one" )
28- parser .add_option ("-v" , "--verbose" , action = "store_true" ,
29- help = "When used with debug option, will force value "
30- "display for each items managed. Beware that it "
31- "can be pretty too much verbose, specialy for LLD" )
32-
33- mode_group = optparse .OptionGroup (parser , "Program Mode" )
34- mode_group .add_option ("--update-items" , action = "store_const" ,
35- dest = "mode" , const = "update_items" ,
36- help = "Get & send items to Zabbix. This is the default "
37- "behaviour even if option is not specified" )
38- mode_group .add_option ("--discovery" , action = "store_const" ,
39- dest = "mode" , const = "discovery" ,
40- help = "If specified, will perform Zabbix Low Level "
41- "Discovery on Memcache. "
42- "Default is to get & send items" )
43- parser .add_option_group (mode_group )
44- parser .set_defaults (mode = "update_items" )
45-
46- general_options = optparse .OptionGroup (parser , "Memcache Configuration" )
47- general_options .add_option ("-H" , "--host" , metavar = "HOST" , default = "localhost" ,
48- help = "Memcache server hostname" )
49- general_options .add_option ("-p" , "--port" , help = "Memcache server port" ,
50- default = 11211 )
51- parser .add_option_group (general_options )
52-
53- polling_options = optparse .OptionGroup (parser , "Zabbix configuration" )
54- polling_options .add_option ("--zabbix-server" , metavar = "HOST" ,
55- default = "localhost" ,
56- help = "The hostname of Zabbix server or "
57- "proxy, default is localhost." )
58- polling_options .add_option ("--zabbix-port" , metavar = "PORT" , default = 10051 ,
59- help = "The port on which the Zabbix server or "
60- "proxy is running, default is 10051." )
61- parser .add_option_group (polling_options )
62-
63- (options , args ) = parser .parse_args ()
64-
65- """if options.mode == "update_items":
66- required.append("zabbix_server")"""
67-
68- return (options , args )
69-
70- def get_discovery (memcache , hostname ):
71- """ Discover 'dynamic' items like
72- http://redis.io/commands/info
73- replication: depends on slave number
74- cluster: empty if not applicable
75- keyspace: depends on database number
76- """
77- data = {}
78- data [hostname ] = {}
79- return data
80-
81- def get_metrics (memcache , hostname ):
82- data = {}
83- data [hostname ] = {}
84- ''' FIXME
85- add support for:
86- * stats slabs
87- * stats items
88- * stats sizes <= /!\ look memcached /!\
89- '''
90- result = memcache .get_stats ()
91- for node_stats in result :
92- server , stats = node_stats
93- host = server .split (':' )[0 ]
94- if not host in data :
95- data [host ] = {}
96- for stat in stats :
97- data [host ]["memcached.%s" % stat ] = stats [stat ]
98- return data
99-
100- def main ():
101- (options , args ) = parse_args ()
102-
103- if options .host == 'localhost' :
104- hostname = socket .getfqdn ()
105- else :
106- hostname = options .host
107-
108- try :
109- mc = memcache .Client (["%s:%s" % (hostname , options .port )])
110- except :
111- return 1
112-
113- zbx_container = protobix .DataContainer ()
114- if options .mode == "update_items" :
115- zbx_container .set_type ("items" )
116- data = get_metrics (mc , hostname )
117-
118- elif options .mode == "discovery" :
119- zbx_container .set_type ("lld" )
120- data = get_discovery (mc , hostname )
121-
122- zbx_container .add (data )
123- zbx_container .add_item (hostname , "memcached.zbx_version" , __version__ )
124-
125- zbx_container .set_host (options .zabbix_server )
126- zbx_container .set_port (int (options .zabbix_port ))
127- zbx_container .set_debug (options .debug )
128- zbx_container .set_verbosity (options .verbose )
129- zbx_container .set_dryrun (options .dry )
130-
131- try :
132- zbxret = zbx_container .send (zbx_container )
133- except protobix .SenderException as zbx_e :
134- if options .debug :
135- print ZBX_CONN_ERR % zbx_e .err_text
136- return 2
137- else :
12+ class MemcachedServer (object ):
13+
14+ __version__ = "0.0.8"
15+ ZBX_CONN_ERR = "ERR - unable to send data to Zabbix [%s]"
16+
17+ def _parse_args (self ):
18+ ''' Parse the script arguments
19+ '''
20+ parser = optparse .OptionParser ()
21+
22+ parser .add_option ("-d" , "--dry" , action = "store_true" ,
23+ help = "Performs Memcache call but do not send "
24+ "anything to the Zabbix server. Can be used "
25+ "for both Update & Discovery mode" )
26+ parser .add_option ("-D" , "--debug" , action = "store_true" ,
27+ help = "Enable debug mode. This will prevent bulk send "
28+ "operations and force sending items one after the "
29+ "other, displaying result for each one" )
30+ parser .add_option ("-v" , "--verbose" , action = "store_true" ,
31+ help = "When used with debug option, will force value "
32+ "display for each items managed. Beware that it "
33+ "can be pretty too much verbose, specialy for LLD" )
34+
35+ mode_group = optparse .OptionGroup (parser , "Program Mode" )
36+ mode_group .add_option ("--update-items" , action = "store_const" ,
37+ dest = "mode" , const = "update_items" ,
38+ help = "Get & send items to Zabbix. This is the default "
39+ "behaviour even if option is not specified" )
40+ mode_group .add_option ("--discovery" , action = "store_const" ,
41+ dest = "mode" , const = "discovery" ,
42+ help = "If specified, will perform Zabbix Low Level "
43+ "Discovery on Memcache. "
44+ "Default is to get & send items" )
45+ parser .add_option_group (mode_group )
46+ parser .set_defaults (mode = "update_items" )
47+
48+ general_options = optparse .OptionGroup (parser , "Memcache Configuration" )
49+ general_options .add_option ("-H" , "--host" , metavar = "HOST" , default = "localhost" ,
50+ help = "Memcache server hostname" )
51+ general_options .add_option ("-p" , "--port" , help = "Memcache server port" ,
52+ default = 11211 )
53+ parser .add_option_group (general_options )
54+
55+ polling_options = optparse .OptionGroup (parser , "Zabbix configuration" )
56+ polling_options .add_option ("--zabbix-server" , metavar = "HOST" ,
57+ default = "localhost" ,
58+ help = "The hostname of Zabbix server or "
59+ "proxy, default is localhost." )
60+ polling_options .add_option ("--zabbix-port" , metavar = "PORT" , default = 10051 ,
61+ help = "The port on which the Zabbix server or "
62+ "proxy is running, default is 10051." )
63+ parser .add_option_group (polling_options )
64+
65+ return parser .parse_args ()
66+
67+ def _get_metrics (self , memcache , hostname ):
68+ data = {}
69+ data [hostname ] = {}
70+ ''' FIXME
71+ add support for:
72+ * stats slabs
73+ * stats items
74+ * stats sizes <= /!\ look memcached /!\
75+ '''
76+ result = memcache .get_stats ()
77+ for node_stats in result :
78+ server , stats = node_stats
79+ host = server .split (':' )[0 ]
80+ if not host in data :
81+ data [host ] = {}
82+ for stat in stats :
83+ data [host ]["memcached.%s" % stat ] = stats [stat ]
84+ return data
85+
86+ def _init_container (self ):
87+ zbx_container = protobix .DataContainer (
88+ data_type = 'items' ,
89+ zbx_host = self .options .zabbix_server ,
90+ zbx_port = int (self .options .zabbix_port ),
91+ debug = self .options .debug ,
92+ dryrun = self .options .dry
93+ )
94+ return zbx_container
95+
96+ def run (self ):
97+ (self .options , args ) = self ._parse_args ()
98+ if self .options .host == 'localhost' :
99+ hostname = socket .getfqdn ()
100+ else :
101+ hostname = self .options .host
102+
103+ # Step 1: init container
104+ try :
105+ zbx_container = self ._init_container ()
106+ zbx_container .data_type = 'items'
107+ except :
108+ return 1
109+
110+ # Step 2: get data
111+ try :
112+ mc = memcache .Client (["%s:%s" % (hostname , self .options .port )])
113+ except urllib2 .URLError as e :
114+ if options .debug :
115+ print NGINX_CONN_ERR % e .reason
116+ return 2
117+
118+ # Step 3: format & load data into container
119+ try :
120+ data = self ._get_metrics (mc , hostname )
121+ zbx_container .add (data )
122+ zbx_container .add_item (hostname , "memcached.zbx_version" , self .__version__ )
123+ except :
124+ return 3
125+
126+ # Step 4: send container data to Zabbix server
127+ try :
128+ zbx_container .send (zbx_container )
129+ except protobix .SenderException as zbx_e :
130+ if self .options .debug :
131+ print self .ZBX_CONN_ERR % zbx_e .err_text
132+ return 4
133+ # Everything went fine. Let's return 0 and exit
138134 return 0
139135
140- if __name__ == " __main__" :
141- ret = main ()
136+ if __name__ == ' __main__' :
137+ ret = MemcachedServer (). run ()
142138 print ret
143-
139+ sys . exit ( ret )
0 commit comments