Skip to content

Commit

Permalink
Item12023: LogDispatchContrib work
Browse files Browse the repository at this point in the history
 - Add support for eachEventSince for the Rolling logfiles
 - Fix issues in the checker
 - Add unit tests for File and FileRolling
 - Level "warning" not "warn"

git-svn-id: http://svn.foswiki.org/trunk/LogDispatchContrib@15306 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
  • Loading branch information
GeorgeClark authored and GeorgeClark committed Aug 22, 2012
1 parent db2c787 commit 4089be4
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 45 deletions.
Expand Up @@ -34,7 +34,7 @@ sub check {
if ( defined $min_level && defined $max_level ) {
$e .= $this->ERROR(
"Minimum level <code>$min_level ($level2num{$min_level})</code> is not less than or equal to Maximum level: <code>$max_level ($level2num{$max_level})</code>"
) unless ( $level2num{$min_level} <= $level2num{$max_level} );
) unless ( $level2num{$min_level} le $level2num{$max_level} );
}

return $e;
Expand Down
10 changes: 5 additions & 5 deletions lib/Foswiki/Contrib/LogDispatchContrib/Config.spec
Expand Up @@ -55,11 +55,11 @@ $Foswiki::cfg{Log}{LogDispatch}{File}{Enabled} = $FALSE;
# written to STDERR.
$Foswiki::cfg{Log}{LogDispatch}{Screen}{Enabled} = $TRUE;

# **SELECT debug,info,notice,warn,error,critical,alert,emergency DISPLAY_IF /LogDispatch/i.test({Log}{Implementation}) && {Log}{LogDispatch}{Screen}{Enabled}**
# **SELECT debug,info,notice,warning,error,critical,alert,emergency DISPLAY_IF /LogDispatch/i.test({Log}{Implementation}) && {Log}{LogDispatch}{Screen}{Enabled}**
# Choose the minimum log level logged to STDERR.
$Foswiki::cfg{Log}{LogDispatch}{Screen}{MinLevel} = 'error';

# **SELECT debug,info,notice,warn,error,critical,alert,emergency DISPLAY_IF /LogDispatch/i.test({Log}{Implementation}) && {Log}{LogDispatch}{Screen}{Enabled}**
# **SELECT debug,info,notice,warning,error,critical,alert,emergency DISPLAY_IF /LogDispatch/i.test({Log}{Implementation}) && {Log}{LogDispatch}{Screen}{Enabled}**
# Choose the maximum log level logged to STDERR.
$Foswiki::cfg{Log}{LogDispatch}{Screen}{MaxLevel} = 'emergency';

Expand All @@ -76,11 +76,11 @@ $Foswiki::cfg{Log}{LogDispatch}{Syslog}{Facility} = 'user';
# Choose an identifier to prepend to each log record
$Foswiki::cfg{Log}{LogDispatch}{Syslog}{Identifier} = 'Foswiki';

# **SELECT debug,info,notice,warn,error,critical,alert,emergency DISPLAY_IF /LogDispatch/i.test({Log}{Implementation}) && {Log}{LogDispatch}{Syslog}{Enabled}**
# **SELECT debug,info,notice,warning,error,critical,alert,emergency DISPLAY_IF /LogDispatch/i.test({Log}{Implementation}) && {Log}{LogDispatch}{Syslog}{Enabled}**
# Choose the minimum log level logged to syslog.
$Foswiki::cfg{Log}{LogDispatch}{Syslog}{MinLevel} = 'warn';
$Foswiki::cfg{Log}{LogDispatch}{Syslog}{MinLevel} = 'warning';

# **SELECT debug,info,notice,warn,error,critical,alert,emergency DISPLAY_IF /LogDispatch/i.test({Log}{Implementation}) && {Log}{LogDispatch}{Syslog}{Enabled}**
# **SELECT debug,info,notice,warning,error,critical,alert,emergency DISPLAY_IF /LogDispatch/i.test({Log}{Implementation}) && {Log}{LogDispatch}{Syslog}{Enabled}**
# Choose the maximum log level logged to syslog.
$Foswiki::cfg{Log}{LogDispatch}{Syslog}{MaxLevel} = 'emergency';

Expand Down
158 changes: 119 additions & 39 deletions lib/Foswiki/Logger/LogDispatch.pm
Expand Up @@ -176,6 +176,12 @@ See Foswiki::Logger for the interface.
sub log {
my ( $this, $level, @fields ) = @_;

if (TRACE) {
foreach my $field (@_) {
print STDERR "field $field \n";
}
}

my $now = _time();
my $time = Foswiki::Time::formatTime( $now, 'iso', 'gmtime' );

Expand All @@ -185,32 +191,29 @@ sub log {
# to the date; Foswiki::Time::ParseTime can handle it, and it looks
# OK too.
unshift( @fields, "$time $level" );
my $message =
'| ' . join( ' | ', map { s/\|/&vbar;/g; $_ } @fields ) . ' |';

# Item10764, SMELL UNICODE: actually, perhaps we should open the stream this
# way for any encoding, not just utf8. Babar says: check what Catalyst does.
unless ( $this->{binmode} ) {
if ( utf8::is_utf8($message) ) {
require Encode;
$message =
Encode::encode( $Foswiki::cfg{Site}{CharSet}, $message, 0 );
}
}

# Optional obfsucation of IP addresses for some locations. However
# preserve them for auth failures.
if ( $Foswiki::cfg{Log}{LogDispatch}{MaskIP} ) {
if ( @_ > 4 ) {
unless ( $_[4] =~ /^AUTHENTICATION FAILURE/ ) {
if ( defined $Foswiki::cfg{Log}{LogDispatch}{MaskIP}
&& $Foswiki::cfg{Log}{LogDispatch}{MaskIP} ne 'none' )
{
if ( scalar @fields > 4 ) {
unless ( $fields[4] =~ /^AUTHENTICATION FAILURE/ )

# SMELL This isn't correct.
# && $fields[5] =~
# /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/ )
{

if ( $Foswiki::cfg{Log}{LogDispatch}{MaskIP} eq 'x.x.x.x' ) {
$_[5] = 'x.x.x.x';
$fields[5] = 'x.x.x.x';
}
else {

# defaults to Hash of IP
use Digest::MD5 qw( md5_hex );
my $md5hex = md5_hex( $_[5] );
$_[5] =
my $md5hex = md5_hex( $fields[5] );
$fields[5] =
hex( substr( $md5hex, 0, 2 ) ) . '.'
. hex( substr( $md5hex, 2, 2 ) ) . '.'
. hex( substr( $md5hex, 4, 2 ) ) . '.'
Expand All @@ -220,6 +223,19 @@ sub log {
}
}

my $message =
'| ' . join( ' | ', map { s/\|/&vbar;/g; $_ } @fields ) . ' |';

# Item10764, SMELL UNICODE: actually, perhaps we should open the stream this
# way for any encoding, not just utf8. Babar says: check what Catalyst does.
unless ( $this->{binmode} ) {
if ( utf8::is_utf8($message) ) {
require Encode;
$message =
Encode::encode( $Foswiki::cfg{Site}{CharSet}, $message, 0 );
}
}

$this->{logger}->log( level => $level, message => $message );

}
Expand Down Expand Up @@ -287,39 +303,95 @@ This logger implementation maps groups of levels to a single logfile, viz. By d
* =info= messages are output together.
* =warning=, =error=, =critical=, =alert=, =emergency= messages are
output together.
* =debug= messages are output together.
The actual groupings are configurable.
=cut

sub eachEventSince {
my ( $this, $time, $level ) = @_;
my $log = $this->_getLogForLevel($level);

# Find the year-month for the current time
my $now = _time();
my $nowLogYear = Foswiki::Time::formatTime( $now, '$year', 'servertime' );
my $nowLogMonth = Foswiki::Time::formatTime( $now, '$mo', 'servertime' );
# We will support a subset of the log filename patterns for the Rolling logger
# y - Year
# M - Month (2 digit only)
# d - Day in month
# D - Day in year

# Find the year-month for the first time in the range
my $logYear = Foswiki::Time::formatTime( $time, '$year', 'servertime' );
my $logMonth = Foswiki::Time::formatTime( $time, '$mo', 'servertime' );
my $prefix = '';
my $pattern = '';
my $postfix = '';
my $supportedPattern = 0;

if ( $Foswiki::cfg{Log}{LogDispatch}{FileRolling}{Enabled} ) {
if ( $Foswiki::cfg{Log}{LogDispatch}{FileRolling}{Pattern} =~
/^(.*)\%d\{([^\}]*)\}(.*)$/ )
{
$prefix = $1;
$pattern = $2;
$postfix = $3;
$supportedPattern = 1;

if ( !defined $pattern || $pattern =~ m/(?<!')[ehHmsSEFwWakKzZ]/ ) {
$pattern = '';
print STDERR
"Pattern $pattern contains unsupported characters, eachEventSince is not supported\n"
if TRACE;
$supportedPattern = 0;
}

# Get the names of all the logfiles in the time range
my @logs;
while ( !( $logMonth == $nowLogMonth && $logYear == $nowLogYear ) ) {
my $logfile = $log;
my $logTime = $logYear . sprintf( "%02d", $logMonth );
$logfile =~ s/\.log$/.$logTime/g;
push( @logs, $logfile );
$logMonth++;
if ( $logMonth == 13 ) {
$logMonth = 1;
$logYear++;
}
}

# Finally the current log
push( @logs, $log );
print STDERR "Pattern $pattern supported = $supportedPattern\n" if TRACE;

my @logs;
my $log = $this->_getLogForLevel($level);

if ( $Foswiki::cfg{Log}{LogDispatch}{FileRolling}{Enabled}
&& $supportedPattern )
{

my $incr =
$pattern =~ /(?<!')[dD]{1,3}/ ? 'P1d'
: $pattern =~ /(?<!')MM/ ? 'P1m1d'
: $pattern =~ /(?<!')y{1,4}/ ? 'P1y'
: '';

my $now = _time();
my $logtime = $time;

while ( $logtime <= $now ) {
my $firstDate =
Foswiki::Time::formatTime( $logtime, 'iso', 'gmtime' );
my $interval = $firstDate . '/' . $incr;
my ( $epoch, $epincr ) = Foswiki::Time::parseInterval($interval);

require Log::Log4perl::DateFormat;
my $formatted = Log::Log4perl::DateFormat->new($pattern);
my $filesfx = _format( $formatted, $epoch );

my $logfile = $log;
$logfile =~ s/\.log$/$prefix$filesfx$postfix/;

if ( -f $logfile ) {
print STDERR "Pushed $logfile\n" if TRACE;
push( @logs, $logfile );
}

$logtime = $epincr;
}

}
elsif ( $Foswiki::cfg{Log}{LogDispatch}{File}{Enabled} ) {
push( @logs, $log );
}
else {
Foswiki::Func::writeWarning(
"eachEventSince not supported for chosen log methods. File or FileRolling should be enabled."
);
require Foswiki::ListIterator;
return new Foswiki::ListIterator( [] );
}

my @iterators;
foreach my $logfile (@logs) {
Expand Down Expand Up @@ -387,6 +459,14 @@ sub _getLogForLevel {
return $log;
}

sub _format {
my $formatted = shift;
my $time = shift;
my $result = $formatted->format( $time, 0 );
$result =~ s/(\$+)/sprintf('%0'.length($1).'.'.length($1).'u', $$)/eg;
return $result;

}
1;
__END__
Module of Foswiki - The Free and Open Source Wiki, http://foswiki.org/
Expand Down

0 comments on commit 4089be4

Please sign in to comment.