├── README.md ├── zbx_nginx_stats.py └── zbx_nginx_templates.xml /README.md: -------------------------------------------------------------------------------- 1 | # zbx_nginx_template 2 | 3 | Zabbix template for Nginx (python) 4 | 5 | It's accumulate nginx stats and parse the access.log (just pice of log at once) and push result in Zabbix through trap-messages 6 | 7 | ## System requirements 8 | 9 | - [python](http://www.python.org/downloads/) 10 | - [nginx](http://nginx.org/) with configured http_stub_status_module and access.log 11 | 12 | ## What's logging: 13 | 14 | - Request\sec 15 | - Response codes (200,301,302,403,404,500,503)\min 16 | - Active\Keepalive connections 17 | - Header and body reading 18 | - Accepted, handled connections 19 | 20 | ## Install 21 | 22 | 1) Put `zbx_nginx_stats.py` into your scripts path (like: `/etc/zabbix/script/nginx/`) on your Zabbix agent hosts. 23 | 24 | 2) Change next section in zbx_nginx_stats.py, to your configuration: 25 | 26 | ``` 27 | zabbix_host = '127.0.0.1' # Zabbix server IP 28 | zabbix_port = 10051 # Zabbix server port 29 | hostname = 'Zabbix Agent' # Name of monitored host, like it shows in zabbix web ui 30 | time_delta = 1 # grep interval in minutes 31 | 32 | # URL to nginx stat (http_stub_status_module) 33 | stat_url = 'https://nginx.server/nginx_stat' 34 | 35 | # Nginx log file path 36 | nginx_log_file_path = '/var/log/nginx/access.log' 37 | 38 | # Optional Basic Auth 39 | username = 'user' 40 | password = 'pass' 41 | 42 | # Temp file, with log file cursor position 43 | seek_file = '/tmp/nginx_log_stat' 44 | ``` 45 | 46 | 3) In script path (`/etc/zabbix/script/nginx/`) do: 47 | ``` 48 | chmod +x zbx_nginx_stats.py 49 | ``` 50 | 51 | 4) Configure cron to run script every one minute: 52 | ``` 53 | $ sudo crontab -e 54 | 55 | */1 * * * * /etc/zabbix/script/nginx/zbx_nginx_stats.py 56 | ``` 57 | 58 | 5) Import `zbx_nginx_template.xml` into zabbix in Tepmplate section web gui. 59 | 60 | 6) Add the following configurations to you Nginx configuration file. 61 | ``` 62 | location /nginx_stat { 63 | stub_status on; # Turn on nginx stats 64 | access_log off; # We do not need logs for stats 65 | allow 127.0.0.1; # Security: Only allow access from IP 66 | allow ::1; # Security IPv6: allow only from localhost 67 | deny all; # Deny requests from the other of the world 68 | } 69 | ``` 70 | 71 | That is all :) 72 | -------------------------------------------------------------------------------- /zbx_nginx_stats.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import urllib2, base64, re, struct, time, socket, sys, datetime, os.path 4 | 5 | try: 6 | import json 7 | except: 8 | import simplejson as json 9 | 10 | zabbix_host = '127.0.0.1' # Zabbix server IP 11 | zabbix_port = 10051 # Zabbix server port 12 | hostname = 'Zabbix Agent' # Name of monitored host, like it shows in zabbix web ui 13 | time_delta = 1 # grep interval in minutes 14 | 15 | # URL to nginx stat (http_stub_status_module) 16 | stat_url = 'https://nginx.server/nginx_stat' 17 | 18 | # Nginx log file path 19 | nginx_log_file_path = '/var/log/nginx/access.log' 20 | 21 | # Optional Basic Auth 22 | username = 'user' 23 | password = 'pass' 24 | 25 | # Temp file, with log file cursor position 26 | seek_file = '/tmp/nginx_log_stat' 27 | 28 | 29 | class Metric(object): 30 | def __init__(self, host, key, value, clock=None): 31 | self.host = host 32 | self.key = key 33 | self.value = value 34 | self.clock = clock 35 | 36 | def __repr__(self): 37 | if self.clock is None: 38 | return 'Metric(%r, %r, %r)' % (self.host, self.key, self.value) 39 | return 'Metric(%r, %r, %r, %r)' % (self.host, self.key, self.value, self.clock) 40 | 41 | def send_to_zabbix(metrics, zabbix_host='127.0.0.1', zabbix_port=10051): 42 | 43 | j = json.dumps 44 | metrics_data = [] 45 | for m in metrics: 46 | clock = m.clock or ('%d' % time.time()) 47 | metrics_data.append(('{"host":%s,"key":%s,"value":%s,"clock":%s}') % (j(m.host), j(m.key), j(m.value), j(clock))) 48 | json_data = ('{"request":"sender data","data":[%s]}') % (','.join(metrics_data)) 49 | data_len = struct.pack(' seek: 152 | nf.seek(seek) 153 | 154 | line = nf.readline() 155 | while line: 156 | if d in line: 157 | new_seek = nf.tell() 158 | total_rps += 1 159 | sec = int(re.match('(.*):(\d+):(\d+):(\d+)\s.*]', line).group(4)) 160 | code = re.match(r'(.*)"\s(\d*)\s', line).group(2) 161 | if code in res_code: 162 | res_code[code] += 1 163 | else: 164 | res_code[code] = 1 165 | 166 | rps[sec] += 1 167 | line = nf.readline() 168 | 169 | if total_rps != 0: 170 | write_seek(seek_file, str(new_seek)) 171 | 172 | nf.close() 173 | 174 | metric = (len(sys.argv) >= 2) and re.match(r'nginx\[(.*)\]', sys.argv[1], re.M | re.I).group(1) or False 175 | data = get(stat_url, username, password).split('\n') 176 | data = parse_nginx_stat(data) 177 | 178 | data_to_send = [] 179 | 180 | # Adding the metrics to response 181 | if not metric: 182 | for i in data: 183 | data_to_send.append(Metric(hostname, ('nginx[%s]' % i), data[i])) 184 | else: 185 | print data[metric] 186 | 187 | # Adding the request per seconds to response 188 | for t in range(0,60): 189 | data_to_send.append(Metric(hostname, 'nginx[rps]', rps[t], minute+t)) 190 | 191 | # Adding the response codes stats to respons 192 | for t in res_code: 193 | data_to_send.append(Metric(hostname, ('nginx[%s]' % t), res_code[t])) 194 | 195 | 196 | send_to_zabbix(data_to_send, zabbix_host, zabbix_port) 197 | -------------------------------------------------------------------------------- /zbx_nginx_templates.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2.0 4 | 2014-03-20T07:57:46Z 5 | 6 | 7 | Templates 8 | 9 | 10 | 11 | 829 | 830 | 831 | 832 | Nginx Connections 833 | 900 834 | 200 835 | 0.0000 836 | 100.0000 837 | 1 838 | 1 839 | 0 840 | 1 841 | 0 842 | 0.0000 843 | 0.0000 844 | 1 845 | 0 846 | 0 847 | 0 848 | 849 | 850 | 1 851 | 0 852 | 00C800 853 | 0 854 | 2 855 | 0 856 | 857 | Template Nginx 858 | nginx[keepalive_connections] 859 | 860 | 861 | 862 | 0 863 | 0 864 | C80000 865 | 0 866 | 2 867 | 0 868 | 869 | Template Nginx 870 | nginx[active_connections] 871 | 872 | 873 | 874 | 875 | 876 | Nginx Connections\min 877 | 900 878 | 200 879 | 0.0000 880 | 100.0000 881 | 1 882 | 1 883 | 0 884 | 1 885 | 0 886 | 0.0000 887 | 0.0000 888 | 1 889 | 0 890 | 0 891 | 0 892 | 893 | 894 | 1 895 | 0 896 | 00C800 897 | 0 898 | 2 899 | 0 900 | 901 | Template Nginx 902 | nginx_handled_connections_per_min 903 | 904 | 905 | 906 | 0 907 | 0 908 | C80000 909 | 0 910 | 2 911 | 0 912 | 913 | Template Nginx 914 | nginx[accepted_connections_per_min] 915 | 916 | 917 | 918 | 919 | 920 | Nginx Requests\sec 921 | 900 922 | 200 923 | 0.0000 924 | 100.0000 925 | 1 926 | 1 927 | 0 928 | 1 929 | 0 930 | 0.0000 931 | 0.0000 932 | 1 933 | 0 934 | 0 935 | 0 936 | 937 | 938 | 0 939 | 0 940 | 00C800 941 | 0 942 | 2 943 | 0 944 | 945 | Template Nginx 946 | nginx[rps] 947 | 948 | 949 | 950 | 951 | 952 | Nginx Response codes per minute 953 | 900 954 | 200 955 | 0.0000 956 | 100.0000 957 | 1 958 | 1 959 | 0 960 | 1 961 | 0 962 | 0.0000 963 | 0.0000 964 | 1 965 | 0 966 | 0 967 | 0 968 | 969 | 970 | 5 971 | 0 972 | C8C800 973 | 0 974 | 2 975 | 0 976 | 977 | Template Nginx 978 | nginx[404] 979 | 980 | 981 | 982 | 6 983 | 0 984 | C8C8C8 985 | 0 986 | 2 987 | 0 988 | 989 | Template Nginx 990 | nginx[499] 991 | 992 | 993 | 994 | 1 995 | 0 996 | 00C800 997 | 0 998 | 2 999 | 0 1000 | 1001 | Template Nginx 1002 | nginx[301] 1003 | 1004 | 1005 | 1006 | 4 1007 | 0 1008 | 00C8C8 1009 | 0 1010 | 2 1011 | 0 1012 | 1013 | Template Nginx 1014 | nginx[403] 1015 | 1016 | 1017 | 1018 | 0 1019 | 0 1020 | C80000 1021 | 0 1022 | 2 1023 | 0 1024 | 1025 | Template Nginx 1026 | nginx[200] 1027 | 1028 | 1029 | 1030 | 2 1031 | 0 1032 | 0000C8 1033 | 0 1034 | 2 1035 | 0 1036 | 1037 | Template Nginx 1038 | nginx[302] 1039 | 1040 | 1041 | 1042 | 7 1043 | 0 1044 | 960000 1045 | 0 1046 | 2 1047 | 0 1048 | 1049 | Template Nginx 1050 | nginx[500] 1051 | 1052 | 1053 | 1054 | 8 1055 | 0 1056 | 009600 1057 | 0 1058 | 2 1059 | 0 1060 | 1061 | Template Nginx 1062 | nginx[503] 1063 | 1064 | 1065 | 1066 | 3 1067 | 0 1068 | C800C8 1069 | 0 1070 | 2 1071 | 0 1072 | 1073 | Template Nginx 1074 | nginx[304] 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | --------------------------------------------------------------------------------