#!/bin/bash
# -*- bash -*-

: <<=cut

=head1 NAME

nginx error - Munin plugin to monitor nginx error rates (http status codes per minute).

=head1 APPLICABLE SYSTEMS

Any Linux host, running nginx, with bash version > 4.0

=head1 CONFIGURATION

This shows the default configuration of this plugin.  You can override
the log file path and the logpattern.

  [nginx_error]
	env.logpath    /var/log/nginx
	env.logpattern a.*.log

	Nginx must also be configured to log accesses in "combined" log format (default)

=head1 USAGE

Link this plugin to /etc/munin/plugins/ and restart the munin-node.

This plugin also can be used like wildcard-plugin for monitoring particular virtual host log.
E.g.
    ln -s /usr/share/munin/plugins/nginx_error /etc/munin/plugins/nginx_error_mydomaincom
will parse the log file /var/log/nginx/a.mydomaincom.log

You can change 'env.logpattern' using asterisk ('*') to match your logs filenames.

=head1 INTERPRETATION

The plugin shows nginx http "error" status rates by parsing access log.

=head1 MAGIC MARKERS

 #%# family=auto
 #%# capabilities=autoconf

=head1 BUGS

None known.

=head1 VERSION

$Id:$

=head1 AUTHOR

vovansystems@gmail.com, 2013

=head1 LICENSE

GPLv3

=cut

if [ -z $logpath ]; then
  logpath='/var/log/nginx'
fi

name=`basename $0`

domain=${name/nginx_error/}
if [[ $domain != '_' && ${#domain} -ne 0 ]]; then
  domain=${domain:1}
  if [ -z $logpattern ]; then
    logpattern='a.*.log'
  fi
  logpattern=${logpattern/\*/$domain}
else
  logpattern='access.log'
fi

log="$logpath/$logpattern"

# declaring an array with http status codes, we are interested in
declare -A http_codes
http_codes[400]='Bad Request'
http_codes[401]='Unauthorized'
http_codes[403]='Forbidden'
http_codes[404]='Not Found'
http_codes[405]='Method Not Allowed'
http_codes[406]='Not Acceptable'
http_codes[408]='Request Timeout'
http_codes[429]='Too Many Requests'
http_codes[499]='Client Connection Terminated'
http_codes[500]='Internal Server Error'
http_codes[502]='Bad Gateway'
http_codes[503]='Service Unavailable'

do_ () { # Fetch
  declare -A line_counts
  values=`awk '{print $9}' $log | sort | uniq -c`
  while read -r line; do
        read -a tmp <<< "$line";
        line_counts[${tmp[1]}]=${tmp[0]};
  done <<< "$values"

  for k in ${!http_codes[@]}; do
    echo "error$k.value ${line_counts[$k]:-0}"
  done
  exit 0
}

do_config () {
  echo "graph_title $logpattern - Nginx errors per minute"
  echo 'graph_vlabel pages with http error codes / ${graph_period}'
  echo "graph_category nginx"
  echo "graph_period minute"
  echo "graph_info This graph shows nginx error amount per minute"
  for k in ${!http_codes[@]}; do
    echo "error$k.type DERIVE"
    echo "error$k.min 0"
    echo "error$k.label $k ${http_codes[$k]}"
  done
  exit 0
}

do_autoconf () {
  echo yes
  exit 0
}

case $1 in
  config|autoconf|'')
  eval do_$1
esac

exit $?
