root/trunk/node/node.d/loggrep.in

Revision 922, 4.2 kB (checked in by ilmari, 5 years ago)

Added support for summing values from log lines.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!@@PERL@@ -w
2 # -*- perl -*-
3 #
4 # Copyright (C) 2004 Dagfinn Ilmari Mannsaaker
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; version 2 dated June, 1991.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18 # USA.
19 #
20 #
21 # Counts the number of matching log lines
22 #
23 # Parameters:
24 #
25 #       config   (required)
26 #
27 # Config variables:
28 #
29 #       logfile       - Files to grep (shellglob) (required)
30 #       regex         - Regex to look for (required)
31 #       label         - Label
32 #       counter       - If set the value captured by the first paren
33 #                       in the regex is summed instead of coutning lines.
34 #                       The value is used for the vertical label.
35 #       regex_<key>   - Additional regexes
36 #       label_<key>   - Additional labels
37 #       counter_<key> - Additional counters (the value is ignored).
38 #       title         - Graph title
39 #
40 # TODO: Handle rotated logs
41 #
42 # Magic markers (optional - used by munin-config and some installation
43 # scripts):
44 #
45 #%# family=manual
46 use strict;
47
48 my %regex;
49 my $logfile = $ENV{logfile};
50 my $vlabel = defined $ENV{'counter'} ? $ENV{'counter'} : 'entries';
51
52 (my $name = $0) =~ s|.*/||;
53
54 die("No log file specified") unless defined $logfile;
55
56 if (exists $ENV{'regex'}) {
57     $regex{'count'}{'regex'} = qr/$ENV{'regex'}/;
58     $regex{'count'}{'label'} = $ENV{'label'} || $ENV{'regex'};
59     $regex{'count'}{'value'} = 0;
60     $regex{'count'}{'counter'} = defined $ENV{'counter'};
61 }
62
63 for my $key (map {/^regex_(.+)/} keys %ENV) {
64     $regex{$key}{'regex'} = qr/$ENV{"regex_$key"}/;
65     $regex{$key}{'label'} = $ENV{"label_$key"} || $ENV{"regex_$key"};
66     $regex{$key}{'value'} = 0;
67     $regex{$key}{'counter'} = defined $ENV{"counter_$key"};
68 }
69
70 die("No regexes specified") unless keys %regex;
71
72 my $statefile = "@@PLUGSTATE@@/$name.state";
73
74 if ($ARGV[0] and $ARGV[0] eq 'config') {
75     my $title = $ENV{title} || "Entries in $logfile";
76     print "graph_title $title\n";
77     print "graph_args --base 1000 -l 0\n";
78     print "graph_vlabel $vlabel / \${graph_period}\n";
79     print "graph_category other\n";
80     for my $key (keys %regex) {
81         print "$key.label $regex{$key}{'label'}\n";
82         print "$key.type DERIVE\n";
83         print "$key.min 0\n";
84         print "$key.draw LINE2\n";
85     }
86     exit 0;
87 }
88
89 my %pos = map { $_ => undef } glob($logfile);
90
91 if (-f $statefile) {
92     open(my $in, '<', $statefile) or die("Can't read $statefile: $!\n");
93     while (<$in>) {
94         chomp;
95         if (/^([^=]+)=(\d+)$/ && exists $regex{$1}) {
96             $regex{$1}{'value'} = $2;
97         } else {
98             last;
99         }
100     }
101     do {
102         chomp;
103         if (<$in> =~ /^(\d+)$/ and exists $pos{$_}) {
104             $pos{$_} = $1
105         }
106     } while (<$in>);
107     close $in;
108 }
109
110 for my $log (keys %pos) {
111     $pos{$log} = parse_log($log, $pos{$log});
112 }
113
114 for my $key (keys %regex) {
115     print "$key.value $regex{$key}{'value'}\n";
116 }
117
118 if(-l $statefile) {
119         die("$statefile is a symbolic link, refusing to touch it.\n");
120 }                               
121 open(my $out, '>', $statefile) or die("Can't write $statefile: $!\n");
122 for my $key (keys %regex) {
123     print $out "$key=$regex{$key}{'value'}\n";
124 }
125 for my $log (keys %pos) {
126     print $out "$log\n$pos{$log}\n";
127 }
128 close $out;
129
130 sub parse_log {
131     my ($fname, $start) = @_;
132     open(my $logfh, $fname) or die ("Can't open log file $fname: $!\n");
133     my $size = (stat $logfh)[7];
134
135     # First encounter
136     $start = $size unless defined $start;
137
138     # The log has been rotated, start over
139     $start = 0 if $size < $start;
140
141     seek($logfh, $start, 0) or die ("Can't seek to $fname:$start: $!\n");
142
143     while (tell($logfh) < $size) {
144         my $line = <$logfh>;
145
146         for my $match (values %regex) {
147             if ($line =~ $match->{'regex'}) {
148                 $match->{'value'} += $match->{'counter'} ? $1 : 1;
149             }
150         }
151     }
152     close($logfh);
153     return $size;
154 }
155
156 # vim:syntax=perl
157
Note: See TracBrowser for help on using the browser.