From 9afb7be58c7e295d7163beeac12addb69263aacc Mon Sep 17 00:00:00 2001 From: Volker Arend Date: Thu, 30 Nov 2017 12:57:06 +0100 Subject: [PATCH 1/2] fixed running check_logfiles process detection in pidfile check --- plugins-scripts/Nagios/CheckLogfiles.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins-scripts/Nagios/CheckLogfiles.pm b/plugins-scripts/Nagios/CheckLogfiles.pm index 5b77faf..4a48bea 100755 --- a/plugins-scripts/Nagios/CheckLogfiles.pm +++ b/plugins-scripts/Nagios/CheckLogfiles.pm @@ -1514,7 +1514,7 @@ sub check_pidfile { $pidfile_status = 0; } else { $pidfile_status = 2; - open(KILL, "/bin/ps -o args -e|"); + open(KILL, "/bin/ps -o pid,args -e|"); while () { if (/^(\d+)\s+.*check_logfiles.*/) { if ($1 == $pid) { From 606b6301541a7a7492b4ece592a42456142b4ca5 Mon Sep 17 00:00:00 2001 From: Volker Arend Date: Wed, 6 Dec 2017 14:51:58 +0100 Subject: [PATCH 2/2] added multiline parsing functionality --- plugins-scripts/Nagios/CheckLogfiles.pm | 52 +++++++++++++++++++++- t/110multiline.t | 59 +++++++++++++++++++++++++ t/data/multiline.log | 20 +++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 t/110multiline.t create mode 100644 t/data/multiline.log diff --git a/plugins-scripts/Nagios/CheckLogfiles.pm b/plugins-scripts/Nagios/CheckLogfiles.pm index 4a48bea..982b1b2 100755 --- a/plugins-scripts/Nagios/CheckLogfiles.pm +++ b/plugins-scripts/Nagios/CheckLogfiles.pm @@ -74,6 +74,10 @@ sub init { $self->{warning} = $params->{warning} || 0; $self->{critical} = $params->{critical} || 0; $self->{matchlines} = { OK => [], WARNING => [], CRITICAL => [], UNKNOWN => [] }; + + $self->{multiline} = $params->{multiline} || 0; + $self->{multilinestartpattern} = $params->{multilinestartpattern} || "\n"; + $self->init_macros; $self->default_options({ prescript => 1, smartprescript => 0, supersmartprescript => 0, postscript => 1, smartpostscript => 0, @@ -2013,6 +2017,10 @@ sub init { $self->{likeavirgin} = 0; $self->{linesread} = 0; $self->{linenumber} = 0; # used for context + + $self->{multiline} = $params->{multiline} || 0; + $self->{multilinestartpattern} = $params->{multilinestartpattern} || "\n"; + $self->{perfdata} = ""; $self->{max_readsize} = 1024 * 1024 * 128; # sysread can only read SSIZE_MAX bytes in one operation. @@ -2898,7 +2906,45 @@ sub scan { $self->trace("fake seek positioned at offset %u", $logfile->{offset}); } - while (my $line = $logfile->{fh}->getline()) { + # use the following negative look-ahead pattern to get multiline output chunks + # each chunk then represents a log message which can be processed + # + my $multilinePattern = $self->{multilinestartpattern} . "(.(?!" . $self->{multilinestartpattern} . "))+"; + + my $remainder = ""; + my $line; + + while ( ( $line = $remainder ) ne "" || ( $line = $logfile->{fh}->getline() ) ) { + + # multiline parsing works like this: + # concat line after line in logfile until concatted lines do not match anymore + # (checked by negative look-ahead pattern described above) + # treat the result as one log message + # + if ( $self->{multiline} ) { + + $remainder = ""; + + # read until the multiline-pattern does not match anymore + # + while ( ( $line =~ /^$multilinePattern$/s ) && ( my $nextLine = $logfile->{fh}->getline() ) ) { + + # stop if lines + nextLine would not match multiline pattern anymore + # + if ( ( $line . $nextLine ) =~ /^$multilinePattern$/s ) { + + $line .= $nextLine; + + } else { + + # keep this line for the next loop + # + $remainder = $nextLine; + last; + } + } + } + if ($self->{timedout}) { $self->trace(sprintf "leaving the scan loop after %d lines", $self->{linesread}); @@ -2913,7 +2959,9 @@ sub scan { Encode::decode($self->{options}->{encoding}, $line)); # the input stream is somewhat binary, so chomp doesn't know # it neads to remove \r\n on windows. - $line =~ s/$1/\n/g if $line =~ /(\r\n?|\n\r?)/; + if ( ! $self->{multiline} ) { + $line =~ s/$1/\n/g if $line =~ /(\r\n?|\n\r?)/; + } } chomp($line); # diff --git a/t/110multiline.t b/t/110multiline.t new file mode 100644 index 0000000..f8f7c2f --- /dev/null +++ b/t/110multiline.t @@ -0,0 +1,59 @@ +#!/usr/bin/perl -w +# +# 110multiline.t +# +# Test multiline parsing +# + +use strict; +use Test::More tests => 3; +use Cwd; +use lib "../plugins-scripts"; +use Nagios::CheckLogfiles::Test; +use constant TESTDIR => "."; + +my $configfile = < 'multiline', + options => 'allyoucaneat', + multiline => 1, + multilinestartpattern => '\\d{4}\\-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} \\- ', + logfile => './data/multiline.log', + criticalpatterns => [ 'ERROR' ] + }, +); + +EOCFG +open CCC, ">./etc/multiline.cfg"; +print CCC $configfile; +close CCC; + +my $cl = Nagios::CheckLogfiles::Test->new({ cfgfile => "./etc/multiline.cfg" }); +$cl->reset(); +$cl->run(); +diag($cl->has_result()); +diag($cl->{exitmessage}); + +my ($protocolFile) = glob( "./var/tmp/multiline.protocol*" ); +open( PROTOCOL, "<$protocolFile" ) || fail( "Could not open protocol file '$protocolFile': $!" ); +my @content = ; +close( PROTOCOL ); + +my $expectedContent = qq|CRITICAL Errors in multiline.log (tag multiline) +2017-08-07 19:51:02 - ERROR +Test subject glitched through catcher +Cake reward will be reduced +2017-08-07 19:51:09 - ERROR +..........>...\$\%\&...:! +{exitmessage}, qr/CRITICAL - \(3 errors in multiline.protocol-.+\) - 2017-08-07 19:57:37 - ERROR - but only one line really .../ ); +ok($cl->expect_result(0, 0, 3, 0, 2)); + diff --git a/t/data/multiline.log b/t/data/multiline.log new file mode 100644 index 0000000..7e3a624 --- /dev/null +++ b/t/data/multiline.log @@ -0,0 +1,20 @@ +2017-08-07 19:51:00 - INFO +Testchamber 16 initialized +Number of portals set to seven +2017-08-07 19:51:02 - ERROR +Test subject glitched through catcher +Cake reward will be reduced +2017-08-07 19:51:07 - INFO +Testchamber 17 initialized +Test subject entered with fully upgraded Portal Gun +2017-08-07 19:51:09 - ERROR +..........>...$%&...:! +