/[mon-modules]/parse_log.cgi
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /parse_log.cgi

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide annotations)
Sun Oct 5 22:26:34 2003 UTC (20 years, 6 months ago) by dpavlin
Branch: MAIN
Changes since 1.2: +76 -33 lines
added duration in time interval and days (not quite working yet)

1 dpavlin 1.1 #!/usr/bin/perl -w
2    
3     # parse file.alert mon logs and report (up|down)time of services
4     #
5     # 2003-09-03 Dobrica Pavlinusic <dpavlin@rot13.org>
6     # 2003-10-05 converted to CGI script
7     #
8    
9     use strict;
10     use POSIX qw(strftime);
11     use CGI qw/:standard *table/;
12     use CGI::Carp qw(fatalsToBrowser);
13     use Data::Sorting qw(:arrays);
14 dpavlin 1.2 use Time::ParseDate;
15 dpavlin 1.3 use Time::Available;
16 dpavlin 1.2
17 dpavlin 1.1 use Data::Dumper;
18    
19 dpavlin 1.2 my $date_fmt = "%Y-%m-%d";
20     my $date_time_fmt = "%Y-%m-%d %H:%M:%S";
21    
22     my $from_date = "now - 6 months";
23     my $to_date = "now";
24 dpavlin 1.1
25     # working days definition (1-7; mon=1)
26 dpavlin 1.3 my $dayMask = Time::Available::DAY_WEEKDAY;
27 dpavlin 1.1 # working hours
28 dpavlin 1.3 my $from_time_interval = "7:00";
29     my $to_time_interval = "17:00";
30 dpavlin 1.1
31 dpavlin 1.2 my $debug=1;
32 dpavlin 1.1 $debug++ if (grep(/-v/,@ARGV));
33     $debug++ if (grep(/-d/,@ARGV));
34    
35 dpavlin 1.3 my %days = (
36     Time::Available::DAY_MONDAY=>'Mo',
37     Time::Available::DAY_TUESDAY=>'Tu',
38     Time::Available::DAY_WEDNESDAY=>'We',
39     Time::Available::DAY_THURSDAY=>'Th',
40     Time::Available::DAY_FRIDAY=>'Fr',
41     Time::Available::DAY_SATURDAY=>'Sa',
42     Time::Available::DAY_SUNDAY=>'Su'
43     );
44    
45 dpavlin 1.1 my $q = new CGI;
46    
47     my $print_orphans = $q->param('print_orphans') || 0;
48     my $rep_reset = $q->param('rep_reset') || 0;
49     my @sg_selected = $q->param('sg_filter');
50    
51 dpavlin 1.3 # init misc sort parametars
52 dpavlin 1.1 my @sort;
53     my $order;
54     my %sort_param;
55     my ($usort,$dsort);
56     if ($q->param('usort')) {
57     $sort_param{'usort'} = $q->param('usort');
58     $q->delete('usort');
59     @sort = ( -compare => 'numeric', $sort_param{'usort'} );
60     }
61     if ($q->param('dsort')) {
62     $sort_param{'dsort'} = $q->param('dsort');
63     $q->delete('dsort');
64     @sort = ( -compare => 'numeric', -order=>'reverse', $sort_param{'dsort'} );
65     }
66    
67 dpavlin 1.3 # make interval
68     my $working_days;
69     if ($q->param('use_time_limit')) {
70     $dayMask=0;
71     foreach my $dm ($q->param('day_interval')) {
72     $dayMask |= $dm;
73     }
74     $working_days=new Time::Available(start=>$q->param('from_time_interval'),end=>$q->param('to_time_interval'),dayMask=>$dayMask);
75     }
76    
77 dpavlin 1.1 #
78     # This option (activated via command switch -r) will reset failure duration
79     # if repeated failure on same group/service happend.
80     # If you want honest reporting (or grouped only by group and service),
81     # you souldn't turn it on :-) However, if you have just failure events in your
82     # log, this will produce output which will show duration BETWEEN two failures
83     #
84    
85     # pretty format date
86     sub d {
87     my $utime = shift || return "?";
88 dpavlin 1.3 if ($debug) {
89     return strftime($date_time_fmt." [%s]",localtime($utime));
90     } else {
91     return strftime($date_time_fmt,localtime($utime));
92     }
93 dpavlin 1.1 }
94     # pretty format duration
95     sub dur {
96 dpavlin 1.3 my $dur = shift || return "0";
97 dpavlin 1.1 my $out = "";
98    
99     my $s = $dur;
100     my $d = int($s/(24*60*60));
101     $s = $s % (24*60*60);
102     my $h = int($s/(60*60));
103     $s = $s % (60*60);
104     my $m = int($s/60);
105     $s = $s % 60;
106    
107     $out .= $d."d " if ($d > 0);
108 dpavlin 1.2 if ($debug) {
109     $out .= sprintf("%02d:%02d:%02d [%d]",$h,$m,$s, $dur);
110     } else {
111     $out .= sprintf("%02d:%02d:%02d",$h,$m,$s);
112     }
113 dpavlin 1.1
114     return $out;
115     }
116    
117     # read log and calculate
118     #
119    
120     my %fail;
121     my %downtime; # total downtime
122     my %sg_filter; # filter for service/group
123 dpavlin 1.2 my %sg_count; # count number of downtimes
124 dpavlin 1.1
125     my $log_file="/home/dpavlin/mon-log/sap.log";
126    
127     my @data;
128    
129     open(LOG, $log_file) || die "$log_file: $!";
130    
131     while(<LOG>) {
132     chomp;
133     if (/^(failure|up)\s+(\S+)\s+(\S+)\s+(\d+)\s+\(([^)]+)\)\s+(.+)$/) {
134     my ($status,$group,$service,$utime,$date,$desc) = ($1,$2,$3,$4,$5,$6);
135     my $id = "$group/$service";
136     if ($status eq "up" && defined($fail{$id})) {
137     if (grep(m;$group/$service;,@sg_selected)) {
138     push @data, {
139     'sg'=>"$group/$service",
140 dpavlin 1.3 'from'=>$fail{$id},
141     'to'=>$utime,
142     'dur'=>($utime - $fail{$id}),
143     'int'=>$working_days->interval($utime,$fail{$id}),
144 dpavlin 1.1 'desc'=>$desc };
145     $downtime{"$group/$service"} += ($utime - $fail{$id}),
146 dpavlin 1.2 $sg_count{"$group/$service"}++;
147 dpavlin 1.1 }
148     $sg_filter{"$group/$service"}++;
149     delete $fail{$id};
150     } elsif ($status eq "up") {
151 dpavlin 1.2 if ($print_orphans && grep(m;$group/$service;,@sg_selected)) {
152 dpavlin 1.1 push @data, {
153     'sg'=>"$group/$service",
154 dpavlin 1.3 'from'=>-1,
155     'to'=>$utime,
156 dpavlin 1.1 'desc'=>$desc };
157 dpavlin 1.2 $sg_count{"$group/$service"}++;
158 dpavlin 1.1 }
159     delete $fail{$id};
160     $sg_filter{"$group/$service"}++;
161     } elsif (defined($fail{$id})) {
162 dpavlin 1.2 if ($rep_reset && grep(m;$group/$service;,@sg_selected)) {
163 dpavlin 1.1 push @data, {
164     'sg'=>"$group/$service",
165 dpavlin 1.3 'from'=>$fail{$id},
166     'to'=>$utime,
167     'dur'=>($utime - $fail{$id}),
168     'int'=>$working_days->interval($utime,$fail{$id}),
169 dpavlin 1.1 'desc'=>'[failure again]'};
170     $downtime{"$group/$service"} += ($utime - $fail{$id}),
171     $fail{$id} = $utime;
172 dpavlin 1.2 $sg_count{"$group/$service"}++;
173 dpavlin 1.1 }
174     $sg_filter{"$group/$service"}++;
175     } else {
176     $fail{$id} = $utime;
177     }
178     }
179     }
180     close(LOG);
181    
182     # generate output
183     #
184     print header,start_html("mon availiability report");
185    
186     # make some filters
187     #
188    
189     print start_form,
190     start_table({-border=>0,-cellspacing=>0,-cellpadding=>0}),
191     Tr(td(
192     em("Show just service/group:"),br,
193     checkbox_group(-name=>'sg_filter',
194     -values=>[keys %sg_filter],
195     -default=>[keys %sg_filter],
196     -linebreak=>'true',
197     ),
198     ),td(
199     em("Other options:"),br,
200     $q->checkbox(-name=>'rep_reset',-checked=>0,
201     -label=>"show repeated failures on same service as individual failures"),
202     br,
203     $q->checkbox(-name=>'print_orphans',-checked=>0,
204     -label=>"show records which are not complete in this interval"),
205     br,
206 dpavlin 1.2 $q->checkbox(-name=>'use_date_limit',-checked=>1,
207     -label=>"use date limit from:"),
208     $q->textfield(-name=>'from_date',-size=>20,-default=>$from_date),
209     " to: ",
210     $q->textfield(-name=>'to_date',-size=>20,-default=>$to_date),
211     small('Using <a href="http://search.cpan.org/search?mode=module&query=Time::ParseDate">Time::ParseDate</a>'),
212     br,
213 dpavlin 1.3 $q->checkbox(-name=>'use_time_limit',-checked=>1,
214     -label=>"use time limit for each day:"),
215     $q->textfield(-name=>'from_time_interval',-size=>8,-default=>$from_time_interval),
216     " to: ",
217     $q->textfield(-name=>'to_time_interval',-size=>8,-default=>$to_time_interval),
218     br,"Days: ",
219     $q->checkbox_group(-name=>'day_interval',
220     -values=>[ sort { $a <=> $b } keys %days ],
221     -labels=>\%days,
222     -defaults=>[
223     Time::Available::DAY_MONDAY,
224     Time::Available::DAY_TUESDAY,
225     Time::Available::DAY_WEDNESDAY,
226     Time::Available::DAY_THURSDAY,
227     Time::Available::DAY_FRIDAY,
228     ]
229     ),
230 dpavlin 1.1 $q->submit(-name=>'show',-value=>'Show report'),
231     )),end_table;
232    
233     # dump report
234     #
235    
236     sub sort_link {
237     my $q = shift || return;
238     my $col = shift || return;
239     my $dir = lc(shift) || return;
240     if ($sort_param{$dir.'sort'} && $sort_param{$dir.'sort'} eq $col) {
241     return '&'.$dir.'Arr;';
242     } else {
243     return '<a href="'.$q->url(-query=>1).'&'.$dir.'sort='.$col.'">&'.$dir.'Arr;</a>';
244     }
245     }
246    
247 dpavlin 1.2
248     my ($from_time,$to_time,$from_html,$to_html);
249     if ($q->param('use_date_limit')) {
250     $from_time = parsedate($q->param('from_date'), UK=>1);
251     $to_time = parsedate($q->param('to_date'), UK=>1);
252     $from_html = strftime($date_fmt,localtime($from_time));
253     $to_html = strftime($date_fmt,localtime($to_time));
254     $from_html .= " [$from_time] " if ($debug);
255     $to_html .= " [$to_time] " if ($debug);
256     }
257    
258     # sort data
259     #
260     my @sorted = sorted_array(@data, @sort);
261     #my @sorted = @data;
262    
263 dpavlin 1.3 print "-- sort: ",Dumper(@sort)," (data: ".@data." sorted: ".@sorted.") --\n",br,"-- dayMask: $dayMask --\n",br if ($debug);
264 dpavlin 1.2
265     print start_table({-border=>1,-cellspacing=>0,-cellpadding=>2,-width=>'100%'});
266    
267     print Tr(
268 dpavlin 1.1 th("group/service"),
269     th({-bgcolor=>'#f0f0f0'},
270 dpavlin 1.3 &sort_link($q,'from','u').' from '.
271     &sort_link($q,'from','d'),
272 dpavlin 1.2 br,$from_html
273 dpavlin 1.1 ),
274     th(
275 dpavlin 1.3 &sort_link($q,'to','u').' to '.
276     &sort_link($q,'to','d'),
277 dpavlin 1.2 br,$to_html
278 dpavlin 1.1 ),
279     th({-bgcolor=>'#e0e0e0'},
280 dpavlin 1.3 &sort_link($q,'dur','u').' duration '.
281     &sort_link($q,'dur','d')
282 dpavlin 1.1 ),
283     th("description")
284 dpavlin 1.2 ) if (scalar @sorted > 0);
285 dpavlin 1.1
286     foreach my $row (@sorted) {
287 dpavlin 1.3 next if ($q->param('use_date_limit') && ($row->{from} < $from_time || $row->{to} > $to_time));
288     my ($from,$dur,$int) = ('unknown','unknown','unknown');
289     if ($row->{from} != -1 ) {
290     $from = d($row->{from});
291     $dur = dur($row->{dur});
292     $int = dur($row->{int});
293     }
294 dpavlin 1.1 print Tr(
295     td({-align=>'left',-valign=>'center'},$row->{sg}),
296 dpavlin 1.3 td({-align=>'right',-bgcolor=>'#f0f0f0'},$from),
297     td({-align=>'right'},d($row->{to})),
298     td({-align=>'center',-bgcolor=>'#e0e0e0'},$dur),
299     td({-align=>'center',-bgcolor=>'#e0e0e0'},$int),
300 dpavlin 1.1 td({-align=>'left'},$row->{desc}),
301     ),"\n";
302     }
303    
304     # dump totals
305     #
306    
307     foreach my $sg (keys %downtime) {
308 dpavlin 1.2 print Tr(td({-colspan=>3,-align=>'right'},"total for $sg:"),
309     td({-bgcolor=>'#e0e0e0',-align=>'right'},dur($downtime{$sg})),
310     td(small("in ".$sg_count{$sg}." failures"))),"\n";
311 dpavlin 1.1 }
312    
313     print end_table,
314     end_form;
315    

  ViewVC Help
Powered by ViewVC 1.1.26