├── README.md ├── getMemcachedInfo.py ├── img └── memcached-zabbix.jpg └── zbx_memcached_template.xml /README.md: -------------------------------------------------------------------------------- 1 | memcached-zabbix-template 2 | ========================= 3 | 4 | Description 5 | ----------- 6 | 7 | This is a minimal template to get info from your Memcached server from two possible places. Via zabbix-agentd in clients or via externalscripts in zabbix server. Choose your option. 8 | 9 | Monitoring information by now: 10 | 11 | * 'bytes' 12 | * 'cmd_get' 13 | * 'cmd_set' 14 | * 'curr_items' 15 | * 'curr_connections' 16 | * 'limit_maxbytes' 17 | * 'uptime' 18 | * 'get_hits' 19 | * 'get_misses' 20 | * 'evictions' 21 | 22 | And the calculated items (HIT)-ratio and usage in %: 23 | 24 | * 'ratio' 25 | * 'usage' 26 | 27 | Installation in the Zabbix Server 28 | --------------------------------- 29 | 30 | You should look for the external scripts directory in your Zabbix Server configuration file. 31 | In the CentOS 6.5 RPM Zabbix installation is: 32 | 33 | ``` 34 | /usr/lib/zabbix/externalscripts 35 | ``` 36 | 37 | Copy the python script there. A chmod/chown to get execution permission is necessary. 38 | 39 | Now, in your Zabbix frontend: Configuration-Templates section, Import bottom in the right side. 40 | 41 | Choose the XML file and import. 42 | 43 | Apply this new template to your Memcached servers. 44 | 45 | You don't need to modify the template if you are using the standard port to access to the Memcached (port 11211). 46 | If you need a different memcached port for the monitor, you will need to modify the {$MEMCACHEDRPORT} macro. 47 | 48 | It permits a fast configuration because of you can apply the same template to all your memcached servers without modification/installation in the agents. 49 | 50 | Of course, it can be to work in the agent/client side too. 51 | 52 | Triggers 53 | -------- 54 | 55 | There is a trigger to detect memcached port issues 56 | 57 | Environment 58 | ----------- 59 | 60 | * Zabbix 2.2.x 61 | 62 | Contributors 63 | ------------ 64 | 65 | * [Pascal Pflaum] (https://github.com/PascalPflaum) 66 | * [Tony Rogers] (https://github.com/teriyakichild) 67 | * [Zhujinhe](https://github.com/zhujinhe/) 68 | 69 | 70 | Screenshots 71 | ----------- 72 | 73 | ![Screenshot](img/memcached-zabbix.jpg) 74 | 75 | 76 | -------------------------------------------------------------------------------- /getMemcachedInfo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import getopt, sys 5 | from telnetlib import Telnet 6 | 7 | # default memcached server to check 8 | memcachedServer = '127.0.0.1' 9 | memcachedPort = '11211' 10 | 11 | ITEMS = ( 12 | 'bytes', 13 | 'cmd_get', 14 | 'cmd_set', 15 | 'curr_items', 16 | 'curr_connections', 17 | 'evictions', 18 | 'limit_maxbytes', 19 | 'uptime', 20 | 'get_hits', 21 | 'get_misses', 22 | 'version', 23 | 'bytes_read', 24 | 'bytes_written', 25 | ) 26 | 27 | ################################################################################ 28 | ### This is based in Enrico Tröger sources from: 29 | ### http://www.pending.io/yet-another-zabbix-template-to-monitor-memcache/ 30 | ### but I chose to make it with dictionaries instead of objects. 31 | ################################################################################ 32 | class MemcachedStatsReader(object): 33 | 34 | #---------------------------------------------------------------------- 35 | def __init__(self, server, port): 36 | self._server = server 37 | self._port = port 38 | self._stats_raw = None 39 | self._stats = None 40 | 41 | #---------------------------------------------------------------------- 42 | def read(self): 43 | self._read_stats() 44 | self._parse_stats() 45 | return self._stats 46 | 47 | #---------------------------------------------------------------------- 48 | def _read_stats(self): 49 | connection = Telnet(self._server, self._port, timeout=30) 50 | connection.write('stats\n') 51 | connection.write('quit\n') 52 | self._stats_raw = connection.read_all() 53 | 54 | #---------------------------------------------------------------------- 55 | def _parse_stats(self): 56 | self._stats = {} 57 | for line in self._stats_raw.splitlines(): 58 | if not line.startswith('STAT'): 59 | continue 60 | parts = line.split() 61 | if not parts[1] in ITEMS: 62 | continue 63 | index = parts[1] 64 | self._stats[index] = parts[2] 65 | try: 66 | ratio = float (self._stats["get_hits"]) * 100 / float (self._stats["cmd_get"]) 67 | except ZeroDivisionError: 68 | ratio = 0.0 69 | self._stats["ratio"] = round (ratio, 2) 70 | try: 71 | usage = float (self._stats["bytes"]) * 100 / float (self._stats["limit_maxbytes"]) 72 | except ZeroDivisionError: 73 | usage = 0.0 74 | self._stats["usage"] = round (usage, 2) 75 | 76 | #---------------------------------------------------------------------- 77 | 78 | def Usage (): 79 | print "Usage: getMemcachedInfo.py -h 127.0.0.1 -p 11211 -a " 80 | sys.exit(2) 81 | 82 | 83 | def main(host, port): 84 | 85 | getInfo = "ratio" 86 | argv = sys.argv[1:] 87 | try: 88 | opts, args = getopt.getopt(argv, "h:p:a:") 89 | for opt,arg in opts: 90 | if opt == '-h': 91 | host = arg 92 | if opt == '-p': 93 | port = arg 94 | if opt == '-a': 95 | getInfo = arg 96 | except: 97 | Usage() 98 | 99 | data = MemcachedStatsReader(host, port) 100 | items = data.read() 101 | try: 102 | print items[getInfo] 103 | except: 104 | print "Not valid item." 105 | 106 | if __name__ == '__main__': 107 | main(memcachedServer, memcachedPort) 108 | -------------------------------------------------------------------------------- /img/memcached-zabbix.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vicendominguez/memcached-zabbix-template/a47f0f0c8e5e74e26086a79f7e374080f55c7672/img/memcached-zabbix.jpg -------------------------------------------------------------------------------- /zbx_memcached_template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2.0 4 | 2015-02-10T08:52:15Z 5 | 6 | 7 | Templates 8 | 9 | 10 | 11 | 630 | 631 | 632 | 633 | {Template Memcached Info:net.tcp.service[tcp,,{$MEMCACHEDRPORT}].count(#3,0,"eq")}=3 634 | Memcached port {$MEMCACHEDRPORT} is not running 635 | 636 | 0 637 | 4 638 | 639 | 0 640 | 641 | 642 | 643 | 644 | 645 | Memcached Key Info 646 | 900 647 | 200 648 | 0.0000 649 | 100.0000 650 | 1 651 | 1 652 | 0 653 | 1 654 | 0 655 | 0.0000 656 | 0.0000 657 | 0 658 | 0 659 | 0 660 | 0 661 | 662 | 663 | 0 664 | 5 665 | 00C800 666 | 0 667 | 2 668 | 0 669 | 670 | Template Memcached Info 671 | getMemcachedInfo.py["-h","{HOST.CONN}","-p","{$MEMCACHEDRPORT}","-a","cmd_get"] 672 | 673 | 674 | 675 | 1 676 | 2 677 | 0000C8 678 | 0 679 | 2 680 | 0 681 | 682 | Template Memcached Info 683 | getMemcachedInfo.py["-h","{HOST.CONN}","-p","{$MEMCACHEDRPORT}","-a","get_hits"] 684 | 685 | 686 | 687 | 2 688 | 5 689 | C800C8 690 | 0 691 | 2 692 | 0 693 | 694 | Template Memcached Info 695 | getMemcachedInfo.py["-h","{HOST.CONN}","-p","{$MEMCACHEDRPORT}","-a","cmd_set"] 696 | 697 | 698 | 699 | 3 700 | 2 701 | C80000 702 | 0 703 | 2 704 | 0 705 | 706 | Template Memcached Info 707 | getMemcachedInfo.py["-h","{HOST.CONN}","-p","{$MEMCACHEDRPORT}","-a","get_misses"] 708 | 709 | 710 | 711 | 712 | 713 | Memcached Memory Space 714 | 500 715 | 400 716 | 0.0000 717 | 0.0000 718 | 0 719 | 0 720 | 2 721 | 1 722 | 1 723 | 0.0000 724 | 0.0000 725 | 0 726 | 0 727 | 0 728 | 0 729 | 730 | 731 | 0 732 | 0 733 | 00C800 734 | 0 735 | 2 736 | 0 737 | 738 | Template Memcached Info 739 | getMemcachedInfo.py["-h","{HOST.CONN}","-p","{$MEMCACHEDRPORT}","-a","limit_maxbytes"] 740 | 741 | 742 | 743 | 1 744 | 0 745 | C80000 746 | 0 747 | 2 748 | 0 749 | 750 | Template Memcached Info 751 | getMemcachedInfo.py["-h","{HOST.CONN}","-p","{$MEMCACHEDRPORT}","-a","bytes"] 752 | 753 | 754 | 755 | 756 | 757 | 758 | --------------------------------------------------------------------------------