view common/logwatch/php @ 380:21686c6a9ac4

Fix and expand PHP logwatch config * PHP-FPM logs (or newer PHP?) are formatted slightly differently * Added separate "service" to summarise contact form anti-spam (Added actual scripts and config - 63adae1a374a just had Puppet. This is what happens when you commit & push in one!)
author IBBoard <dev@ibboard.co.uk>
date Sat, 16 Oct 2021 15:43:04 +0100
parents
children
line wrap: on
line source

###############################################################################
# $Id$
###############################################################################
# $Log: php,v $
# Revision 1.2  2008/03/24 23:31:26  kirk
# added copyright/license notice to each script
#
# Revision 1.1  2006/11/12 18:28:31  bjorn
# New php service, by Jeremias Reith.
#
###############################################################################
#
# Logwatch service for php error logs
#
# Processes all messages and summarizes them
# Each message is given with a timestamp and RMS

#######################################################
## Copyright (C) 2006 by Jeremias Reith <jr@terragate.net>
## Covered under the included MIT/X-Consortium License:
##    http://www.opensource.org/licenses/mit-license.php
## All modifications and contributions by other persons to
## this script are assumed to have been donated to the
## Logwatch project and thus assume the above copyright
## and licensing terms.  If you want to make contributions
## under your own copyright or a different license this
## must be explicitly stated in the contribution an the
## Logwatch project reserves the right to not accept such
## contributions.  If you have made significant
## contributions to this script and want to claim
## copyright please contact logwatch-devel@lists.sourceforge.net.
#########################################################

use strict;
use Logwatch ':dates';
use Time::Local;
use POSIX qw(strftime);

my $date_format = '%d-%b-%Y %H:%M:%S';
my $filter = TimeFilter($date_format);
my $detail = exists $ENV{'LOGWATCH_DETAIL_LEVEL'} ? $ENV{'LOGWATCH_DETAIL_LEVEL'} : 0;

# we do not use any Date:: package (or strptime) as they are probably not available
my %month2num = ( Jan => 0, Feb => 1, Mar => 2, Apr => 3,
		  May => 4, Jun => 5, Jul => 6, Aug => 7,
		  Sep => 8, Oct => 9, Nov => 10, Dec => 11 );

# array of message categories (we do not use a hash to keep the order)
# first element: catorory name
# second element: matching regexp ($1 should contain the message)
# third element: anonymous hash ref (stores message  counts)
my @message_categories = (['Fatal errors', qr/\] (?:PHP (?:Fatal|Parse) error|ERROR): (.*)$/o, {}],
			  ['Warnings', qr/\] (?:PHP (?:Warning|Deprecated)|WARNING): (.*)$/o, {}],
			  ['Notices', qr/\] (?:PHP Notice|NOTICE): (.*)$/o, {}]);

# skipping categories depending on detail level
pop(@message_categories) if $detail < 10;
pop(@message_categories) if $detail < 5;


# counting messages
while(<>) {
    my $line = $_;
    # skipping messages that are not within the requested range
    # the last part of the regex matches optionally occurring specification
    # of timezones, either in Continent/City or abbrevations like UTC
    next unless $line =~ /^\[($filter)(?: \w+(?:\/\w+)?)?\]/o;
    $1 =~ /(\d+)-(\w+)-(\d+) (\d+):(\d+):(\d+)/;
    my $time;

    {
	# timelocal is quite chatty
	local $SIG{'__WARN__'}  = sub {};
	$time = timelocal($6, $5, $4, $1, $month2num{$2}, $3-1900);
    }

    foreach my $cur_cat (@message_categories) {
	if($line =~ /$cur_cat->[1]/) {
	    my $msgs = $cur_cat->[2];
	    $msgs->{$1} = {count => '0',
			   first_occurrence => $time,
			   sum => 0,
			   sqrsum => 0} unless exists $msgs->{$1};
	    $msgs->{$1}->{'count'}++;
	    # summing up timestamps and squares of timestamps
	    # in order to calculate the rms
	    # using first occurrence of message as offset in calculation to
	    # prevent an integer overflow
	    $msgs->{$1}->{'sum'} += $time - $msgs->{$1}->{'first_occurrence'};
	    $msgs->{$1}->{'sqrsum'} += ($time - $msgs->{$1}->{'first_occurrence'}) ** 2;
	    last;
	}
    }
}


# generating summary
foreach my $cur_cat (@message_categories) {
    # skipping non-requested message types
    next unless keys %{$cur_cat->[2]};
    my ($name, undef, $msgs) = @{$cur_cat};
    print $name, ":\n";
    my $last_count = 0;

    # sorting messages by count
    my @sorted_msgs = sort { $msgs->{$b}->{'count'} <=> $msgs->{$a}->{'count'} } keys %{$msgs};

    foreach my $msg (@sorted_msgs) {
	# grouping messages by number of occurrence
	print "\n", $msgs->{$msg}->{'count'}, " times:\n" unless $last_count == $msgs->{$msg}->{'count'};
	my $rms = 0;


	# printing timestamp
        print '[';

	if($msgs->{$msg}->{'count'} > 1) {
	    # calculating rms
	    $rms = int(sqrt(
			   ($msgs->{$msg}->{'count'} *
			    $msgs->{$msg}->{'sqrsum'} -
			    $msgs->{$msg}->{'sum'}) /
			   ($msgs->{$msg}->{'count'} *
			    ($msgs->{$msg}->{'count'} - 1))));

	    print strftime($date_format, localtime($msgs->{$msg}->{'first_occurrence'}+int($rms/2)));

	    print ' +/-';

	    # printing rms
	    if($rms > 86400) {
		print int($rms/86400) , ' day(s)';
	    } elsif($rms > 3600) {
		print int($rms/3600) , ' hour(s)';
	    } elsif($rms > 60) {
		print int($rms/60) , ' minute(s)';
	    } else {
		print $rms, ' seconds';
	    }
	} else {
	    # we have got this message a single time
	    print strftime($date_format, localtime($msgs->{$msg}->{'first_occurrence'}));
	}

	print '] ', $msg, "\n";
	$last_count = $msgs->{$msg}->{'count'};
    }

    print "\n";
}

# vi: shiftwidth=3 tabstop=3 et
# Local Variables:
# mode: perl
# perl-indent-level: 3
# indent-tabs-mode: nil
# End: