/[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

Contents of /parse_log.cgi

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show annotations)
Sun Oct 5 22:26:34 2003 UTC (20 years, 5 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 #!/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 use Time::ParseDate;
15 use Time::Available;
16
17 use Data::Dumper;
18
19 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
25 # working days definition (1-7; mon=1)
26 my $dayMask = Time::Available::DAY_WEEKDAY;
27 # working hours
28 my $from_time_interval = "7:00";
29 my $to_time_interval = "17:00";
30
31 my $debug=1;
32 $debug++ if (grep(/-v/,@ARGV));
33 $debug++ if (grep(/-d/,@ARGV));
34
35 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 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 # init misc sort parametars
52 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 # 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 #
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 if ($debug) {
89 return strftime($date_time_fmt." [%s]",localtime($utime));
90 } else {
91 return strftime($date_time_fmt,localtime($utime));
92 }
93 }
94 # pretty format duration
95 sub dur {
96 my $dur = shift || return "0";
97 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 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
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 my %sg_count; # count number of downtimes
124
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 'from'=>$fail{$id},
141 'to'=>$utime,
142 'dur'=>($utime - $fail{$id}),
143 'int'=>$working_days->interval($utime,$fail{$id}),
144 'desc'=>$desc };
145 $downtime{"$group/$service"} += ($utime - $fail{$id}),
146 $sg_count{"$group/$service"}++;
147 }
148 $sg_filter{"$group/$service"}++;
149 delete $fail{$id};
150 } elsif ($status eq "up") {
151 if ($print_orphans && grep(m;$group/$service;,@sg_selected)) {
152 push @data, {
153 'sg'=>"$group/$service",
154 'from'=>-1,
155 'to'=>$utime,
156 'desc'=>$desc };
157 $sg_count{"$group/$service"}++;
158 }
159 delete $fail{$id};
160 $sg_filter{"$group/$service"}++;
161 } elsif (defined($fail{$id})) {
162 if ($rep_reset && grep(m;$group/$service;,@sg_selected)) {
163 push @data, {
164 'sg'=>"$group/$service",
165 'from'=>$fail{$id},
166 'to'=>$utime,
167 'dur'=>($utime - $fail{$id}),
168 'int'=>$working_days->interval($utime,$fail{$id}),
169 'desc'=>'[failure again]'};
170 $downtime{"$group/$service"} += ($utime - $fail{$id}),
171 $fail{$id} = $utime;
172 $sg_count{"$group/$service"}++;
173 }
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 $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 $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 $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
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 print "-- sort: ",Dumper(@sort)," (data: ".@data." sorted: ".@sorted.") --\n",br,"-- dayMask: $dayMask --\n",br if ($debug);
264
265 print start_table({-border=>1,-cellspacing=>0,-cellpadding=>2,-width=>'100%'});
266
267 print Tr(
268 th("group/service"),
269 th({-bgcolor=>'#f0f0f0'},
270 &sort_link($q,'from','u').' from '.
271 &sort_link($q,'from','d'),
272 br,$from_html
273 ),
274 th(
275 &sort_link($q,'to','u').' to '.
276 &sort_link($q,'to','d'),
277 br,$to_html
278 ),
279 th({-bgcolor=>'#e0e0e0'},
280 &sort_link($q,'dur','u').' duration '.
281 &sort_link($q,'dur','d')
282 ),
283 th("description")
284 ) if (scalar @sorted > 0);
285
286 foreach my $row (@sorted) {
287 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 print Tr(
295 td({-align=>'left',-valign=>'center'},$row->{sg}),
296 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 td({-align=>'left'},$row->{desc}),
301 ),"\n";
302 }
303
304 # dump totals
305 #
306
307 foreach my $sg (keys %downtime) {
308 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 }
312
313 print end_table,
314 end_form;
315

  ViewVC Help
Powered by ViewVC 1.1.26