Hello,
I work on a project consiting of daemon which runs periodically (10 - 300
seconds) some bits of code (check nginx status, check presence of some
processes, ...). This daemon runs on our servers. I use log4perl everywhere.
However sometimes an admin shuts down nginx for a while (0 - few hours) and do
some maintainance. Nginx code logs errors when HTTP requests fails. Log file
is then filled with same repeated message(s).
When I browsed through collectd (monitoring of everything) I found
utils_complain.[ch] which address this problem. It consists of structure which
is associated with one error message and functions for logging (complaining,
integrated into its logging system). It looks like this:
// inside collectd plugin, code executed periodically
c_complain(c, ERROR, "connecting failed");
The above logs only if (c->last + c->interval) is less or equal time(). c-
>interval is doubled on every call. c->last is last time of logging.
After success c->interval is set to 0 with:
c_release(c);
This module is a copy of this C code (a bit generalized). Altough it's really
simple piece of code, I thought it could be useful for other peoples and I
don't know any other use cases than logging so I'm posting it here (patch
attached). I'll make better docs ASAP.
Regards,
Thomas.
From 7928be6a0b57581c996fa8a34e3937690327a70b Mon Sep 17 00:00:00 2001
From: Tomas Nechutny <nech...@gmail.com>
Date: Sun, 18 Jul 2010 22:56:59 +0200
Subject: [PATCH] Add Complaint class & test
---
lib/Log/Log4perl/Util/Complaint.pm | 131 ++++++++++++++++++++++++++++++++++++
t/061Complaint.t | 48 +++++++++++++
2 files changed, 179 insertions(+), 0 deletions(-)
create mode 100644 lib/Log/Log4perl/Util/Complaint.pm
create mode 100644 t/061Complaint.t
diff --git a/lib/Log/Log4perl/Util/Complaint.pm b/lib/Log/Log4perl/Util/Complaint.pm
new file mode 100644
index 0000000..b70929c
--- /dev/null
+++ b/lib/Log/Log4perl/Util/Complaint.pm
@@ -0,0 +1,131 @@
+
+=head1 NAME
+
+Log::Log4perl::Util::Complaint - Do something once or on increasing interval
+
+=head1 SYNOPSIS
+
+ use Log::Log4perl::Util::Complaint;
+
+ my $c = Log::Log4perl::Util::Complaint->new;
+
+ # inside infinite loop
+
+ my $fh = my_connect();
+ unless ($fh) {
+ $log->error("connect(): $!") if $c->take;
+ }
+
+=head1 DESCRIPTION
+
+This module is used for reduction of error log messages when error occurs
+repeatedly in loop. It was inspired by utils_complain from collectd.
+
+=cut
+
+# TODO documentation
+
+package Log::Log4perl::Util::Complaint;
+
+use strict;
+use warnings;
+
+our $FIRST_INTERVAL = 5;
+our $MAX_INTERVAL = 86400 * 7;
+
+sub new
+{
+ my ( $class, $first_interval, $max_interval ) = @_;
+
+ my $self = {};
+
+ $$self{last} = 0;
+ $$self{interval} = 0;
+
+ $$self{first_interval} =
+ defined $first_interval ? $first_interval : $FIRST_INTERVAL;
+
+ $$self{max_interval} =
+ defined $max_interval ? $max_interval : $MAX_INTERVAL;
+
+ return bless( $self, $class );
+}
+
+sub take_internal
+{
+ my ($self) = @_;
+
+ my $now = time;
+
+ if ( $$self{last} + $$self{interval} > $now ) {
+ return 0;
+ }
+
+ $$self{last} = $now;
+
+ if ( $$self{interval} < $$self{first_interval} ) {
+ $$self{interval} = $$self{first_interval};
+ }
+ else {
+ $$self{interval} *= 2;
+ }
+
+ if ( $$self{interval} > $$self{max_interval} ) {
+ $$self{interval} = $$self{max_interval};
+ }
+
+ return 1;
+}
+
+sub take
+{
+ my ($self) = @_;
+
+ if ( $$self{interval} < 0 ) { # reset `once' status
+ $$self{interval} *= -1;
+ }
+
+ return $self->take_internal;
+}
+
+sub take_once
+{
+ my ($self) = @_;
+
+ if ( $$self{interval} < 0 ) {
+ return 0;
+ }
+
+ if ( $self->take_internal ) {
+ $$self{interval} *= -1;
+ return 1;
+ }
+
+ return 0;
+}
+
+sub would_reset
+{
+ my ($self) = @_;
+
+ return $$self{interval} != 0;
+}
+
+sub reset
+{
+ my ($self) = @_;
+
+ $$self{interval} = 0;
+}
+
+1;
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2010 by Tomas Nechutny E<lt>nech...@gmail.come<gt>.
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
diff --git a/t/061Complaint.t b/t/061Complaint.t
new file mode 100644
index 0000000..edfdab7
--- /dev/null
+++ b/t/061Complaint.t
@@ -0,0 +1,48 @@
+use strict;
+use warnings;
+
+use Test::More qw(no_plan);
+
+use Log::Log4perl::Util::Complaint;
+
+my $c = Log::Log4perl::Util::Complaint->new( 1, 5 );
+
+ok( $c->take );
+is( $$c{interval}, 1 );
+
+sleep 1;
+
+ok( $c->take );
+is( $$c{interval}, 2 );
+ok( not $c->take );
+
+sleep 2;
+
+ok( $c->take );
+is( $$c{interval}, 4 );
+ok( not $c->take );
+
+sleep 4;
+
+ok( $c->take );
+is( $$c{interval}, 5 );
+ok( not $c->take );
+
+sleep 5;
+
+ok( $c->take );
+is( $$c{interval}, 5 );
+ok( not $c->take );
+
+sleep 5;
+
+ok( $c->take_once );
+is( $$c{interval}, -5 );
+ok( not $c->take_once );
+
+ok( $c->would_reset );
+
+$c->reset;
+is( $$c{interval}, 0 );
+ok( $c->take );
+
--
1.7.1
------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first
_______________________________________________
log4perl-devel mailing list
log4perl-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/log4perl-devel