Blame scripts/services/http-error

Packit Bot ea69bd
#!/usr/bin/perl -w
Packit Bot ea69bd
#
Packit Bot ea69bd
# $Id$
Packit Bot ea69bd
#
Packit Bot ea69bd
# Logwatch service for http error logs
Packit Bot ea69bd
# To be placed in 
Packit Bot ea69bd
#	/etc/logwatch/scripts/http-error
Packit Bot ea69bd
#
Packit Bot ea69bd
# Processes all messages and summarizes them
Packit Bot ea69bd
# Each message is given with a timestamp and RMS
Packit Bot ea69bd
#
Packit Bot ea69bd
########################################################
Packit Bot ea69bd
##(C) 2006 by Jeremias Reith <jr@terragate.net>
Packit Bot ea69bd
## Modified 2009 by Michael Baierl
Packit Bot ea69bd
## Covered under the included MIT/X-Consortium License:
Packit Bot ea69bd
##    http://www.opensource.org/licenses/mit-license.php
Packit Bot ea69bd
## All modifications and contributions by other persons to
Packit Bot ea69bd
## this script are assumed to have been donated to the
Packit Bot ea69bd
## Logwatch project and thus assume the above copyright
Packit Bot ea69bd
## and licensing terms.  If you want to make contributions
Packit Bot ea69bd
## under your own copyright or a different license this
Packit Bot ea69bd
## must be explicitly stated in the contribution an the
Packit Bot ea69bd
## Logwatch project reserves the right to not accept such
Packit Bot ea69bd
## contributions.  If you have made significant
Packit Bot ea69bd
## contributions to this script and want to claim
Packit Bot ea69bd
## copyright please contact logwatch-devel@lists.sourceforge.net.
Packit Bot ea69bd
######################################################### 
Packit Bot ea69bd
Packit Bot ea69bd
use strict;
Packit Bot ea69bd
use Logwatch ':dates';
Packit Bot ea69bd
use Time::Local;
Packit Bot ea69bd
use POSIX qw(strftime);
Packit Bot ea69bd
Packit Bot ea69bd
my $date_format = '... %b %d %H:%M:%S %Y';
Packit Bot ea69bd
my $filter = TimeFilter($date_format);
Packit Bot ea69bd
my $detail = exists $ENV{'LOGWATCH_DETAIL_LEVEL'} ? $ENV{'LOGWATCH_DETAIL_LEVEL'} : 0;
Packit Bot ea69bd
my $Ignore_not_exist_all = $ENV{'ignore_not_exist_all'} || 0;
Packit Bot ea69bd
my $Ignore_not_exist_no_referer = $ENV{'ignore_not_exist_no_referer'} || 0;
Packit Bot ea69bd
Packit Bot ea69bd
# we do not use any Date:: package (or strptime) as they are probably not available
Packit Bot ea69bd
my %month2num = ( Jan => 0, Feb => 1, Mar => 2, Apr => 3,
Packit Bot ea69bd
		  May => 4, Jun => 5, Jul => 6, Aug => 7,
Packit Bot ea69bd
		  Sep => 8, Oct => 9, Nov => 10, Dec => 11 );
Packit Bot ea69bd
Packit Bot ea69bd
# array of message categories (we do not use a hash to keep the order)
Packit Bot ea69bd
# first element: catorory name 
Packit Bot ea69bd
# second element: matching regexp ($1 should contain the message)
Packit Bot ea69bd
# third element: anonymous hash ref (stores message  counts)
Packit Bot ea69bd
my @message_categories = (['Errors', qr/\[error\] (.*)$/o, {}],
Packit Bot ea69bd
			  ['Warnings', qr/\[warn\] (.*)$/o, {}],
Packit Bot ea69bd
			  ['Notices', qr/\[info\] (.*)$/o, {}]);
Packit Bot ea69bd
Packit Bot ea69bd
# skipping categories depending on detail level
Packit Bot ea69bd
pop(@message_categories) if $detail < 10;
Packit Bot ea69bd
pop(@message_categories) if $detail < 5;
Packit Bot ea69bd
Packit Bot ea69bd
# counting messages
Packit Bot ea69bd
while(<>) {
Packit Bot ea69bd
    my $line = $_;
Packit Bot ea69bd
    # skip PHP messages (have a separate script)
Packit Bot ea69bd
    next if $line =~ / PHP (Warning|Fatal error|Notice):/o;
Packit Bot ea69bd
    # Ignore does not exist messages if asked
Packit Bot ea69bd
    if ($line =~ /does not exist:/o) {
Packit Bot ea69bd
       next if $Ignore_not_exist_all;
Packit Bot ea69bd
       next if $Ignore_not_exist_no_referer and $line !~ /, referer: /o;
Packit Bot ea69bd
    }
Packit Bot ea69bd
    # skipping messages that are not within the requested range
Packit Bot ea69bd
    next unless $line =~ /^\[($filter)\]/o;
Packit Bot ea69bd
    $1 =~ /(\w+) (\w+) (\d+) (\d+):(\d+):(\d+) (\d+)/;
Packit Bot ea69bd
    my $time;
Packit Bot ea69bd
Packit Bot ea69bd
    {
Packit Bot ea69bd
	# timelocal is quite chatty
Packit Bot ea69bd
	local $SIG{'__WARN__'}  = sub {};
Packit Bot ea69bd
	$time = timelocal($6, $5, $4, $3, $month2num{$2}, $7-1900);
Packit Bot ea69bd
    }
Packit Bot ea69bd
Packit Bot ea69bd
    foreach my $cur_cat (@message_categories) {
Packit Bot ea69bd
	if($line =~ /$cur_cat->[1]/) {
Packit Bot ea69bd
	    my $msgs = $cur_cat->[2];
Packit Bot ea69bd
	    $msgs->{$1} = {count => '0',
Packit Bot ea69bd
			   first_occurrence => $time,
Packit Bot ea69bd
			   sum => 0, 
Packit Bot ea69bd
			   sqrsum => 0} unless exists $msgs->{$1};
Packit Bot ea69bd
	    $msgs->{$1}->{'count'}++;
Packit Bot ea69bd
	    # summing up timestamps and squares of timestamps
Packit Bot ea69bd
	    # in order to calculate the rms
Packit Bot ea69bd
	    # using first occurrence of message as offset in calculation to 
Packit Bot ea69bd
	    # prevent an integer overflow
Packit Bot ea69bd
	    $msgs->{$1}->{'sum'} += $time - $msgs->{$1}->{'first_occurrence'};
Packit Bot ea69bd
	    $msgs->{$1}->{'sqrsum'} += ($time - $msgs->{$1}->{'first_occurrence'}) ** 2;
Packit Bot ea69bd
	    last;
Packit Bot ea69bd
	}
Packit Bot ea69bd
    }
Packit Bot ea69bd
}
Packit Bot ea69bd
Packit Bot ea69bd
Packit Bot ea69bd
# generating summary
Packit Bot ea69bd
foreach my $cur_cat (@message_categories) {
Packit Bot ea69bd
    # skipping non-requested message types
Packit Bot ea69bd
    next unless keys %{$cur_cat->[2]};
Packit Bot ea69bd
    my ($name, undef, $msgs) = @{$cur_cat};
Packit Bot ea69bd
    print $name, ":\n";
Packit Bot ea69bd
    my $last_count = 0;
Packit Bot ea69bd
Packit Bot ea69bd
    # sorting messages by count
Packit Bot ea69bd
    my @sorted_msgs = sort { $msgs->{$b}->{'count'} <=> $msgs->{$a}->{'count'} } keys %{$msgs};
Packit Bot ea69bd
Packit Bot ea69bd
    foreach my $msg (@sorted_msgs) {
Packit Bot ea69bd
	# grouping messages by number of occurrence
Packit Bot ea69bd
	print "\n", $msgs->{$msg}->{'count'}, " times:\n" unless $last_count == $msgs->{$msg}->{'count'};   
Packit Bot ea69bd
	my $rms = 0;
Packit Bot ea69bd
Packit Bot ea69bd
Packit Bot ea69bd
	# printing timestamp
Packit Bot ea69bd
        print '[';
Packit Bot ea69bd
Packit Bot ea69bd
	if($msgs->{$msg}->{'count'} > 1) {
Packit Bot ea69bd
	    # calculating rms
Packit Bot ea69bd
	    $rms = int(sqrt(
Packit Bot ea69bd
			   ($msgs->{$msg}->{'count'} * 
Packit Bot ea69bd
			    $msgs->{$msg}->{'sqrsum'} - 
Packit Bot ea69bd
			    $msgs->{$msg}->{'sum'}) / 
Packit Bot ea69bd
			   ($msgs->{$msg}->{'count'} * 
Packit Bot ea69bd
			    ($msgs->{$msg}->{'count'} - 1))));
Packit Bot ea69bd
Packit Bot ea69bd
	    print strftime($date_format, localtime($msgs->{$msg}->{'first_occurrence'}+int($rms/2)));
Packit Bot ea69bd
Packit Bot ea69bd
	    print ' +/-';
Packit Bot ea69bd
	    
Packit Bot ea69bd
	    # printing rms
Packit Bot ea69bd
	    if($rms > 86400) {
Packit Bot ea69bd
		print int($rms/86400) , ' day(s)';
Packit Bot ea69bd
	    } elsif($rms > 3600) {
Packit Bot ea69bd
		print int($rms/3600) , ' hour(s)';
Packit Bot ea69bd
	    } elsif($rms > 60) {
Packit Bot ea69bd
		print int($rms/60) , ' minute(s)';
Packit Bot ea69bd
	    } else {
Packit Bot ea69bd
		print $rms, ' seconds';
Packit Bot ea69bd
	    }
Packit Bot ea69bd
	} else {
Packit Bot ea69bd
	    # we have got this message a single time
Packit Bot ea69bd
	    print strftime($date_format, localtime($msgs->{$msg}->{'first_occurrence'}));
Packit Bot ea69bd
	}
Packit Bot ea69bd
	   
Packit Bot ea69bd
	print '] ', $msg, "\n";	
Packit Bot ea69bd
	$last_count = $msgs->{$msg}->{'count'};
Packit Bot ea69bd
    }
Packit Bot ea69bd
Packit Bot ea69bd
    print "\n";
Packit Bot ea69bd
}
Packit Bot ea69bd