From 35732520d7403e44a7dac7bd727061bd69edc61c Mon Sep 17 00:00:00 2001 From: Bart Cortooms Date: Wed, 14 Jan 2009 17:04:37 +0100 Subject: [PATCH] Initial version --- plugins/other/amavis_ | 192 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100755 plugins/other/amavis_ diff --git a/plugins/other/amavis_ b/plugins/other/amavis_ new file mode 100755 index 00000000..ca14adba --- /dev/null +++ b/plugins/other/amavis_ @@ -0,0 +1,192 @@ +#!/usr/bin/perl -w +# +# Plugin to monitor amavisd-new statistics. Values are retrieved by querying +# the BerkeleyDB database 'snmp.db', in which amavisd-new stores its +# statistics. +# +# The plugin requires the Perl module BerkeleyDB. +# +# To use, setup /etc/munin/plugin-conf.d/amavis e.g. as follows: +# +# [amavis_*] +# env.amavis_db_home /var/lib/amavis/db +# user amavis +# +# Where env.amavis_db_home is the path to the amavisd-new BerkeleyDB files +# (/var/amavis/db by default). +# +# Then create symlinks in the Munin plugin directory named "amavis_time", +# "amavis_cache" and "amavis_content", or use munin-node-configure. +# +# Parameters: +# +# config +# autoconf +# suggest +# +# Config variables: +# +# amavis_db_home - where the amavisd-new berkeley db files are located +# +# Magic markers +#%# family=auto +#%# capabilities=autoconf +#%# capabilities=suggest + +use strict; +no warnings 'uninitialized'; + +use BerkeleyDB; + +my($dbfile) = 'snmp.db'; +my($db_home) = # DB databases directory + defined $ENV{'amavis_db_home'} ? $ENV{'amavis_db_home'} : '/var/amavis/db'; + +if ($ARGV[0] and $ARGV[0] eq "autoconf") { + if (-x "/usr/sbin/amavisd-agent") { + print "yes\n"; + exit 0; + } else { + print "no (/usr/sbin/amavisd-agent not found or not executable)\n"; + exit 1; + } +} elsif ($ARGV[0] and $ARGV[0] eq "suggest") { + print "time\n"; + print "cache\n"; + print "content\n"; + exit 0; +} + +my $stats_type = ""; +if ($0 =~ /^(?:|.*\/)amavis_(cache|content|time)$/) { + $stats_type = $1; +} else { + print "You need to create a symlink to this plugin called either amavis_cache, amavis_time or amavis_content to be able to use it.\n"; + exit 2; +} + +if ($ARGV[0] and $ARGV[0] eq "config") { + if ($stats_type eq "cache") { + print "graph_title Amavis cache hit / miss ratio\n"; + print "graph_args --lower-limit 0 --upper-limit 100 --rigid\n"; + print "graph_category mail\n"; + print "graph_info The ratio of cache hits and misses for AMaViSd-new.\n"; + print "graph_order hits misses\n"; + print "graph_scale no\n"; + print "graph_vlabel %\n"; + print "hits.label Cache hits\n"; + print "hits.draw AREA\n"; + print "hits.max 100\n"; + print "hits.min 0\n"; + print "misses.label Cache misses\n"; + print "misses.draw STACK\n"; + print "misses.max 100\n"; + print "misses.min 0\n"; + } elsif ($stats_type eq "content") { + print "graph_title Amavis scanned mails\n"; + print "graph_category mail\n"; + print "graph_period minute\n"; + print "graph_vlabel msgs / \${graph_period}\n"; + foreach my $type (qw(total clean spam spammy virus)) { + print "$type.label " . ucfirst($type) . " mails \n"; + print "$type.type DERIVE\n"; + print "$type.min 0\n"; + } + print "clean.info Legitimate mail.\n"; + print "spammy.info Mails with a spam score above the tag2 level.\n"; + print "spam.info Mails with a spam score above the kill level for spam.\n"; + print "virus.info Mails with a virus.\n"; + print "total.info Total number of scanned mails.\n"; + } elsif ($stats_type eq "time") { + print "graph_title Amavis average scan time\n"; + print "graph_info Average time spent in each phase of the mail scanning process, per mail.\n"; + print "graph_category mail\n"; + print "graph_vlabel sec / mail\n"; + print "graph_scale no\n"; + + print "msgs.label Total number of messages\n"; + print "msgs.graph no\n"; + print "msgs.type DERIVE\n"; + print "msgs.min 0\n"; + + foreach my $type (qw(decoding receiving sending spamcheck viruscheck total)) { + print "${type}.label " . ucfirst($type) . "\n"; + print "${type}.type DERIVE\n"; + print "${type}.min 0\n"; + print "${type}.cdef ${type},1000,/,msgs,/\n"; + } + } + exit 0; +} + + +my ($env, $db, @dbstat, $cursor); + +@dbstat = stat("$db_home/$dbfile"); +my $errn = @dbstat ? 0 : 0+$!; +$errn == 0 or die "stat $db_home/$dbfile: $!"; + +$env = BerkeleyDB::Env->new( + -Home => $db_home, + -Flags => DB_INIT_CDB | DB_INIT_MPOOL, + -ErrFile => \*STDOUT, + -Verbose => 1, +); +defined $env or die "BDB no env: $BerkeleyDB::Error $!"; + +$db = BerkeleyDB::Hash->new(-Filename => $dbfile, -Env => $env); +defined $db or die "BDB no db: $BerkeleyDB::Error $!"; + +my %values = (); +my ($eval_stat, $stat, $key, $val); + +$cursor = $db->db_cursor; # obtain read lock +defined $cursor or die "db_cursor error: $BerkeleyDB::Error"; + +while (($stat = $cursor->c_get($key, $val, DB_NEXT)) == 0) { + $values{$key} = $val; +} + +$stat == DB_NOTFOUND or die "c_get: $BerkeleyDB::Error $!"; +$cursor->c_close == 0 or die "c_close error: $BerkeleyDB::Error"; +$cursor = undef; + +$eval_stat = $@; + +if ($eval_stat ne '') { chomp($eval_stat); die "BDB $eval_stat\n"; } + +for my $k (sort keys %values) { + if ($values{$k} =~ /^(?:C32|C64) (.*)\z/) { + $values{$k} = $1; + } +} + +if ($stats_type eq "cache") { + my $hits = $values{'CacheHits'}; + my $misses = $values{'CacheMisses'}; + my $misses_ratio = $misses * 100.00 / ($hits + $misses); + my $hits_ratio = $hits * 100.00 / ($hits + $misses); + + printf("hits.value %.1f\n", $hits_ratio); + printf("misses.value %.1f\n", $misses_ratio); +} elsif ($stats_type eq "content") { + printf("total.value %d\n", $values{'InMsgs'}); + my $clean = $values{'ContentCleanMsgs'}; + if (defined($values{'ContentCleanTagMsgs'})) { + $clean += $values{'ContentCleanTagMsgs'}; + } + printf("clean.value %d\n", $clean); + printf("spam.value %d\n", $values{'ContentSpamMsgs'}); + printf("spammy.value %d\n", $values{'ContentSpammyMsgs'}); + printf("virus.value %d\n", $values{'ContentVirusMsgs'}); +} elsif ($stats_type eq "time") { + printf("decoding.value %d\n", $values{'TimeElapsedDecoding'}); + printf("receiving.value %d\n", $values{'TimeElapsedReceiving'}); + printf("sending.value %d\n", $values{'TimeElapsedSending'}); + printf("spamcheck.value %d\n", $values{'TimeElapsedSpamCheck'}); + printf("viruscheck.value %d\n", $values{'TimeElapsedVirusCheck'}); + printf("total.value %d\n", $values{'TimeElapsedTotal'}); + printf("msgs.value %d\n", $values{'InMsgs'}); +} + +$db->db_close == 0 or die "BDB db_close error: $BerkeleyDB::Error $!";