Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / postfix / postfix_mailstats_ @ 1fe97cbf

Historique | Voir | Annoter | Télécharger (4,19 ko)

1
#!/usr/bin/perl -w
2
# -*- perl -*-
3

    
4
=head1 NAME
5

    
6
postfix_mailstats_ - Plugin to monitor the number of mails delivered and
7
rejected by postfix
8

    
9
=head1 CONFIGURATION
10

    
11
Uses the last part of the symlink name for grepping the correct data from the
12
postfix log file. The name must be syslog_name from the postfix config.
13
The environment settings still applay to this plugin.
14

    
15
Configuration parameters for /etc/munin/postfix_mailstats_,
16
if you need to override the defaults below:
17

    
18
 [postfix_mailstats]
19
  env.logdir  - Which logfile to use
20
  env.logfile - What file to read in logdir
21

    
22
=head2 DEFAULT CONFIGURATION
23

    
24
 [postfix_mailstats]
25
  env.logdir  /var/log
26
  env.logfile mail.log
27

    
28
=head1 AUTHOR
29

    
30
Records show that the plugin was contributed by Nicolai Langfeldt in
31
2003.  Nicolai can't find anything in his email about this and expects
32
the plugin is based on the corresponding exim plugin - to which it now
33
bears no resemblance.
34

    
35
Extended for multiple queue use by Clemens Schwaighofer (gullevek@gullevek.org) in 2010.
36

    
37
=head1 LICENSE
38

    
39
GPLv2
40

    
41
=head1 MAGIC MARKERS
42

    
43
=begin comment
44

    
45
These magic markers are used by munin-node-configure when installing
46
munin-node.
47

    
48
=end comment
49

    
50
 #%# family=manual
51
 #%# capabilities=autoconf
52

    
53
=head1 RANDOM COMMENTS
54

    
55
Would be cool if someone ported this to Munin::Plugin for both state
56
file and log tailing.
57

    
58
=cut
59

    
60
# get the postfix queue number to look for
61
$0 =~ /postfix_mailstats_([\w\d\-]+)$/;
62
my $postfix = $1;
63
my $statefile = "$ENV{MUNIN_PLUGSTATE}/munin-plugin-".$postfix."_mailstats.state";
64
my $pos;
65
my $delivered = 0;
66
my $rejects = {};
67
my $LOGDIR  = $ENV{'logdir'}  || '/var/log';
68
my $LOGFILE = $ENV{'logfile'} || 'mail.log';
69

    
70
my $logfile = "$LOGDIR/$LOGFILE";
71

    
72
if ($ARGV[0] and $ARGV[0] eq "autoconf")
73
{
74
	my $logfile;
75
	if (-d $LOGDIR)
76
	{
77
		if (-f $logfile)
78
		{
79
				if (-r $logfile)
80
				{
81
					print "yes\n";
82
					exit 0;
83
				}
84
				else
85
				{
86
					print "no (logfile '$logfile' not readable)\n";
87
				}
88
		}
89
		else
90
		{
91
			print "no (logfile '$logfile' not found)\n";
92
		}
93
	}
94
	else
95
	{
96
		print "no (could not find logdir '$LOGDIR')\n";
97
	}
98

    
99
	exit 0;
100
}
101

    
102

    
103
if (-f $statefile)
104
{
105
	open (IN, '<', $statefile) or die "Unable to open state-file: $!\n";
106
	if (<IN> =~ /^(\d+):(\d+)/)
107
	{
108
		($pos, $delivered) = ($1, $2);
109
	}
110
	while (<IN>)
111
	{
112
		if (/^([0-9a-z.\-]+):(\d+)$/)
113
		{
114
			$rejects->{$1} = $2;
115
		}
116
	}
117
	close IN;
118
}
119

    
120
if (! -f $logfile)
121
{
122
	print "delivered.value U\n";
123
	foreach my $i (sort keys %{$rejects})
124
	{
125
		print "r$i.value U\n";
126
	}
127
	exit 0;
128
}
129

    
130
$startsize = (stat $logfile)[7];
131

    
132
if (!defined $pos)
133
{
134
    # Initial run.
135
    $pos = $startsize;
136
}
137

    
138
parseLogfile($logfile, $pos, $startsize);
139
$pos = $startsize;
140

    
141
if ( $ARGV[0] and $ARGV[0] eq "config" )
142
{
143
	print "graph_title Postfix message throughput for $postfix\n";
144
	print "graph_args --base 1000 -l 0\n";
145
	print "graph_vlabel mails / \${graph_period}\n";
146
	print "graph_scale  no\n";
147
	print "graph_total  Total\n";
148
	print "graph_category mail\n";
149
	print "delivered.label delivered\n";
150
	print "delivered.type DERIVE\n";
151
	print "delivered.draw AREA\n";
152
	print "delivered.min 0\n";
153
	foreach my $i (sort keys %{$rejects})
154
	{
155
		print "r$i.label reject $i\n";
156
		print "r$i.type DERIVE\n";
157
		print "r$i.draw STACK\n";
158
		print "r$i.min 0\n";
159
	}
160
	exit 0;
161
}
162

    
163
print "delivered.value $delivered\n";
164
foreach my $i (sort keys %{$rejects})
165
{
166
	print "r$i.value ", $rejects->{$i}, "\n";
167
}
168

    
169
if (-l $statefile)
170
{
171
	die ("$statefile is a symbolic link, refusing to touch it.");
172
}				
173
open (OUT, '>', $statefile) or die "Unable to open statefile: $!\n";
174
print OUT "$pos:$delivered\n";
175
foreach my $i (sort keys %{$rejects})
176
{
177
	print OUT "$i:", $rejects->{$i}, "\n";
178
}
179
close OUT;
180

    
181
sub parseLogfile 
182
{    
183
	my ($fname, $start, $stop) = @_;
184
	open (LOGFILE, $fname)
185
		or die "Unable to open logfile $fname for reading: $!\n";
186
	seek (LOGFILE, $start, 0)
187
		or die "Unable to seek to $start in $fname: $!\n";
188

    
189
	while (tell (LOGFILE) < $stop) 
190
	{
191
		my $line = <LOGFILE>;
192
		chomp ($line);
193

    
194
		if ($line =~ /$postfix\/qmgr.*from=.*size=[0-9]*/ ||
195
			$line =~ /$postfix\/smtp.* status=sent /) 
196
		{
197
			$delivered++;
198
		} 
199
		elsif ($line =~ /$postfix\/smtpd.*reject: \S+ \S+ \S+ (\S+)/ ||
200
			   $line =~ /$postfix\/cleanup.* reject: (\S+)/)
201
		{
202
			$rejects->{$1}++;
203
		}
204
	}
205
	close(LOGFILE) or warn "Error closing $fname: $!\n";    
206
}
207

    
208
# vim:syntax=perl