#!/usr/bin/env python # -*- coding: utf-8 -*- # vim: set fileencoding=utf-8 # # Munin plugin to monitor nginx cache statuses. # # Copyright Igor Borodikhin # # License : GPLv3 # # This plugin generates two graphs - with number of requests and with percents. # Create these symlinks: # ln -s /usr/share/munin/plugins/nginx-cache-multi_ /etc/munin/plugins/nginx-cache-multi_number # ln -s /usr/share/munin/plugins/nginx-cache-multi_ /etc/munin/plugins/nginx-cache-multi_percent # # You can override the log file location. # # [nginx-cache-multi] # env.logfile /var/log/nginx/cache-access.log # # Nginx must be configured to include "cs=$upstream_cache_status" in the # log file. Example format: # # log_format cache '$remote_addr - $host [$time_local] "$request" $status ' # '$body_bytes_sent "$http_referer" ' # 'rt=$request_time ut="$upstream_response_time" ' # 'cs=$upstream_cache_status'; #%# capabilities=autoconf #%# family=contrib import os, sys, re # How we've been called prog_name = sys.argv[0] prog_name = prog_name[prog_name.rfind("/")+1:] # What is graph type? graph_type = prog_name[prog_name.rfind("_")+1:] # Where to store plugin state if "MUNIN_PLUGSTATE" in os.environ: state_dir = os.environ["MUNIN_PLUGSTATE"] else: state_dir = None # Log path if "logfile" in os.environ: log_file = os.environ["logfile"] else: log_file = "/var/log/nginx/access.log" cache_status_list = { "MISS" : 0, "EXPIRED" : 0, "UPDATING" : 0, "STALE" : 0, "HIT" : 0, "NONE" : 0, "TOTAL" : 0 } if len(sys.argv) == 2 and sys.argv[1] == "autoconf": print "yes" elif len(sys.argv) == 2 and sys.argv[1] == "config": graph_args = "" if graph_type == "number": vlabel = "requests" else: vlabel = "%" graph_args = "graph_args -l 0" # Parent graph declaration print "multigraph nginx_cache_multi_%s" % graph_type print "graph_title Nginx cache status (%s)" % graph_type print "graph_category webserver" print "graph_vlabel %s" % vlabel if graph_args: print(graph_args) for key in cache_status_list.keys(): if key != "TOTAL": print "%s.label %s" % (key.lower(), key.capitalize()) print "%s.draw AREASTACK" % key.lower() print "%s.min 0" % key.lower() print "" for key in cache_status_list.keys(): # Other graphs declaration if key != "TOTAL": print "multigraph nginx_cache_multi_%s.%s" % (graph_type, key.lower()) print "graph_title Nginx cache status (%s) - %s" % (graph_type, key.capitalize()) print "graph_category webserver" print "graph_vlabel %s" % vlabel print "%s.label %s" % (key.lower(), key.capitalize()) print "%s.draw LINE1" % key.lower() print "%s.min 0" % key.lower() print "" else: last_byte_file = "%s/%s_state" % (state_dir, prog_name) last_byte_handle = None # Load last position in log file try: last_byte_handle = open(last_byte_file, "r") last_byte = int(last_byte_handle.read()) except Exception: last_byte = 0 if last_byte_handle != None: last_byte_handle.close() # Open log file for reading try: log_handle = open(log_file, "r") except Exception: print "Log file %s not readable" % log_file sys.exit(1) # Find out log size and set proper position depending on log size try: log_size = int(os.path.getsize(log_file)) except ValueError: log_size = 0 if log_size < last_byte: last_byte = 0 # Set position on file log_handle.seek(last_byte) reg_exp = re.compile(r"cs=([^\s]+)") for line in log_handle: match = reg_exp.search(line) cache_status = match.group(1) if cache_status == "-": cache_status = "NONE" cache_status_list[cache_status] += 1 cache_status_list["TOTAL"] += 1 try: last_byte_handle = open(last_byte_file, "w") last_byte_handle.write(str(log_handle.tell())) last_byte_handle.close() except Exception: sys.exit(1) log_handle.close() # Handle graph type (_num for absolute numbers and anything else for percents) if graph_type != "number": for key in cache_status_list.keys(): if key != "TOTAL": cache_status_list[key] = cache_status_list[key] * 100 / cache_status_list["TOTAL"] cache_status_list["TOTAL"] = 100 # Parent graph declaration print "multigraph nginx_cache_multi_%s" % graph_type #print "total.value %s" % cache_status_list["TOTAL"] for key in cache_status_list.keys(): if key != "TOTAL": print "%s.value %s" % (key.lower(), cache_status_list[key]) print "" for key in cache_status_list.keys(): # Other graphs declaration if key != "TOTAL": print "multigraph nginx_cache_multi_%s.%s" % (graph_type, key.lower()) print "total.value %s" % cache_status_list["TOTAL"] print "%s.value %s" % (key.lower(), cache_status_list[key]) print ""