diff --git a/plugins/mysql/mysql_aggregate_ b/plugins/mysql/mysql_aggregate_ new file mode 100755 index 00000000..6293f8d8 --- /dev/null +++ b/plugins/mysql/mysql_aggregate_ @@ -0,0 +1,199 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# vim: set fileencoding=utf-8 +# +# Munin plugin to show Mysql COUNT(*) results for multiple values +# +# Copyright Igor Borodikhin +# +# License : GPLv3 +# +# parsed environment variables: +# host: hostname or ip-address of Mysql server (default - localhost) +# port: port number of Mysql server (default - 3306) +# user: username to access Mysql server (default - empty) +# password: password of Mysql user (default - empty) +# database: Mysql database name (default - empty) +# table: Mysql table name (no default, raises exception) +# field: field name, used in GROUP BY statement (default - empty, no group by) +# where: optional where condition (without "where", default - empty) +# +# This plugin shows graphs of Mysql COUNT(*) results. +# +# ## Requirements +# This plugin requires pythons MySQLdb module which can be installed via easy_install. +# +# ## Installation +# Copy file to directory /usr/share/munin/pligins/ and create symbolic links for each table you wish to monitor. +# For example, if you wish to monitor how many users Mysql has per host create this symlink: +# +# ln -s /usr/share/munin/plugins/mysql_aggregate_ /etc/munin/plugins/mysql_aggregate_user +# +# And specify some options in munin-node.conf: +# +# [mysql_aggregate_*] +# env.host 10.216.0.141 +# env.port 3306 +# env.user root +# env.password vErYsEcReT +# env.database mysql +# env.table user +# env.field Host +# env.label Mysql users +# env.vlabel users +# +#%# capabilities=autoconf +#%# family=contrib + +import os, sys, MySQLdb, MySQLdb.cursors + +progName = sys.argv[0] + +# Parse environment variables +# Mysql host +if "host" in os.environ and os.environ["host"] != None: + server = os.environ["host"] +else: + server = "localhost" + +# Mysql port +if "port" in os.environ and os.environ["port"] != None: + try: + port = int(os.environ["port"]) + except ValueError: + port = 3306 +else: + port = 3306 + +# Mysql username +if "user" in os.environ and os.environ["user"] != None: + login = os.environ["user"] +else: + login = "" + +# Mysql password +if "password" in os.environ and os.environ["password"] != None: + passw = os.environ["password"] +else: + passw = "" + +# Mysql database +if "database" in os.environ and os.environ["database"] != None: + db = os.environ["database"] +else: + db = "" + +# Mysql table name +if "table" in os.environ and os.environ["table"] != None: + table = os.environ["table"] +else: + raise Exception("You should provide 'env.table' in configuration file") +# Mysql group by field +if "field" in os.environ and os.environ["field"] != None: + groupBy = "GROUP BY %s" % os.environ["field"] + field = "%s, " % os.environ["field"] +else: + groupBy = "" + field = "" + +# Mysql where condition +if "where" in os.environ and os.environ["where"] != None: + where = "WHERE %s" % os.environ["where"] +else: + where = "" + +# Mysql connection handler +conn = None + +# Query to get field values +valuesQuery = "SELECT DISTINCT %s 1 FROM %s %s" % (field, table, where) +# Query to get graph data +aggregateQuery = "SELECT %sCOUNT(*) FROM %s %s %s" % (field, table, where, groupBy) + +# Connect to mysql +try: + conn = MySQLdb.connect(host=server, user=login, passwd=passw, db=db) + cursor = conn.cursor() +except MySQLdb.Error, e: + print "Error %d: %s" % (e.args[0], e.args[1]) + sys.exit(1) + +# init values tuple +if field != "": + values = {} + cursor.execute(valuesQuery) + results = cursor.fetchall() + for result in results: + values[result[0]] = 0 + +if len(sys.argv) == 2 and sys.argv[1] == "autoconf": + print "yes" +elif len(sys.argv) == 2 and sys.argv[1] == "config": + + if "label" in os.environ: + label = os.environ["label"] + else: + label = "Aggregate - %s" % table + + if "vlabel" in os.environ: + vlabel = os.environ["vlabel"] + else: + vlabel = "count(*)" + + if field == "": + print "graph mysql_aggregate_%s" % table + print "graph_title %s" % label + print "graph_vlabel %s" % vlabel + print "graph_category mysql" + print "" + print "values_count.label count" + else: + print "multigraph mysql_aggregate_%s" % table + print "graph_title %s" % label + print "graph_vlabel %s" % vlabel + print "graph_category mysql" + print "" + + for key in values.keys(): + print "%s_count.label %s" % (key.replace(".", "_"), key.replace(".", "_")) + + for key in values.keys(): + print "" + print "multigraph mysql_aggregate_%s.%s" % (table, key.replace(".", "_")) + print "graph_title %s, value %s" % (label, key.replace(".", "_")) + print "graph_vlabel %s" % vlabel + print "graph_category mysql" + print "" + print "%s_count.label %s" % (key.replace(".", "_"), key) + print "" + +else: + try: + cursor.execute(aggregateQuery) + + if field == "": + result = cursor.fetchone() + count = 0 + if result[0]: + count = count + result[0] + print "values_count.value %s" % count + else: + results = cursor.fetchall() + + for result in results: + values[result[0]] = result[1] + print "multigraph mysql_aggregate_%s" % table + + for key in values.keys(): + print "%s_count.value %s" % (key.replace(".", "_"), values[key]) + + for key in values.keys(): + print "" + print "multigraph mysql_aggregate_%s.%s" % (table, key.replace(".", "_")) + print "%s_count.value %s" % (key.replace(".", "_"), values[key]) + + except MySQLdb.Error, e: + print "Error %d: %s" % (e.args[0], e.args[1]) + +if conn: + conn.close() diff --git a/plugins/nginx/nginx-cache-multi_ b/plugins/nginx/nginx-cache-multi_ new file mode 100755 index 00000000..0299432e --- /dev/null +++ b/plugins/nginx/nginx-cache-multi_ @@ -0,0 +1,159 @@ +#!/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 +# ls -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": + if graph_type == "number": + vlabel = "requests" + else: + vlabel = "%" + + # Parent graph declaration + print "multigraph nginx_cache_multi_%s" % graph_type + print "graph_title Nginx cache status (%s)" % graph_type + print "graph_category nginx" + print "graph_vlabel %s" % vlabel + 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 nginx" + 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 alse 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 "" \ No newline at end of file