-
Notifications
You must be signed in to change notification settings - Fork 4
/
uloganalyser
executable file
·163 lines (142 loc) · 4.39 KB
/
uloganalyser
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/perl
BEGIN { unshift @INC, '/etc/snmp/uloganalyser-plugin', '.'; }
use strict;
use warnings;
# process a log with plugins and place the results in a file
# Copyright (C) 2009-2011 Glen Pitt-Pladdy
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
#
my $VERSION = 20150516;
#
# Thanks for ideas, unhandled log lines, patches and feedback to:
#
# Przemek Orzechowski
# usage: postfix-loganalyser <old mail log> <current mail log> <stats file>
my ( $logold, $lognew, $statsfile, @modules ) = @ARGV;
# quick and dirty plugin setup - depends on module returning ref to register sub
my @lines;
my @ends;
foreach (@modules) {
s/\.pm$//;
my $register = require "$_.pm";
&$register ( \@lines, \@ends, $VERSION );
}
# santiy check
if ( ! $logold or ! -f $logold ) {
# warn "WARNING - old mail log file not found\n";
}
if ( ! $lognew or ! -f $lognew ) {
die "FATAL - current log file not found: $lognew\n";
}
if ( ! $statsfile ) {
die "FATAL - stats file not specified\n";
}
# read in the current stats if it exists
my %stats;
my $repeatline = '';
if ( -f $statsfile ) {
open ST, $statsfile or die "FATAL - can't read previous statistics: $!\n";
while ( defined ( my $line = <ST> ) ) {
chomp $line;
if ( $line =~ /^([\w\-_:]+)=([\d\.]+)$/ ) {
$stats{$1} = $2;
} elsif ( $line =~ /^repeatline=(.*)$/ ) {
$repeatline = $1;
} else {
die "FATAL - don't understand line \"$line\" in stats\n";
}
}
close ST;
}
# initialise basics
if ( ! $stats{'lastrun'} ) { $stats{'lastrun'} = $^T; }
if ( ! $stats{'lastline'} ) { $stats{'lastline'} = 0; }
if ( ! $stats{'lastposition'} ) { $stats{'lastposition'} = 0; }
# process the log files
# we only look at the old log file if it is newer than the last run
if ( $stats{'lastinode'} and -f $logold and ( stat ( $logold ) )[1] == $stats{'lastinode'} ) {
# read in old file from $stats{lastline}
readlogfile ( $logold );
# set $stats{lastline} to zero to start at the beginning of the new file
$stats{'lastline'} = 0;
$stats{'lastposition'} = 0;
}
# current log file
readlogfile ( $lognew );
# wrap up with end stuff
for (@ends) {
if ( $_ ) { &$_( \%stats ) };
}
# update for our run
$stats{'lastrun'} = $^T;
# write stats to temporary file
open ST, ">$statsfile.TMP.$$"
or die "FATAL - can't write \"$statsfile.TMP.$$\": $!\n";
print ST "lastrun=$stats{lastrun}\n";
delete $stats{'lastrun'};
print ST "lastline=$stats{lastline}\n";
delete $stats{'lastline'};
print ST "lastposition=$stats{lastposition}\n";
delete $stats{'lastposition'};
print ST "repeatline=$repeatline\n";
# dump rest of stats
foreach my $stat (sort keys %stats) {
print ST "$stat=$stats{$stat}\n";
}
close ST;
rename "$statsfile.TMP.$$", $statsfile
or die "FATAL - can't move \"$statsfile.TMP.$$\" to \"$statsfile\": $!\n";
sub readlogfile {
my ( $log ) = @_;
open LOG, $log or die "FATAL - can't read \"$log\": $!\n";
# skip to where we left off
seek LOG, $stats{'lastposition'}, 0;
my $i = $stats{'lastline'};
# read lines from here
my $line;
while ( defined ( $line = <LOG> ) ) {
chomp $line;
# check for repeats & expand if needed
if ( $line =~ / message repeated (\d+) times?$/ ) {
my $repeat = $1;
while ( $repeat-- > 0 ) {
for (@lines) {
&$_( $repeatline, $i, $log, \%stats ) and last;
}
}
} elsif ( $line =~ / message repeated (\d+) times: \[\s*([^\s].*)\s?\]$/ ) {
my $repeat = $1;
$repeatline = $2;
while ( $repeat-- > 0 ) {
for (@lines) {
&$_( $repeatline, $i, $log, \%stats ) and last;
}
}
} else {
# run through each plugin
for (@lines) {
&$_( $line, $i, $log, \%stats ) and last;
}
$repeatline = $line;
}
++$i;
}
$stats{'lastline'} = $i; # save for next time
$stats{'lastposition'} = tell LOG; # save for next time
$stats{'lastinode'} = ( stat LOG )[1];
close LOG;
}