Merge pull request #43 from msimerson/master
loadcheck: refactored. See =CHANGES section
This commit is contained in:
commit
d60882c857
141
plugins/loadcheck
Executable file → Normal file
141
plugins/loadcheck
Executable file → Normal file
@ -7,15 +7,16 @@ loadcheck
|
|||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
Only takes email transactions if the system load is at or below a
|
Only takes email transactions if the system load is at or below a
|
||||||
specified level.
|
specified level.
|
||||||
|
|
||||||
If this is running on a system that provides /kern/loadavg or
|
If this is running on a system that provides /kern/loadavg or
|
||||||
/proc/loadavg it will be used instead of the 'uptime' command.
|
/proc/loadavg it will be used instead of the 'uptime' command.
|
||||||
|
|
||||||
Once a load value is determined, it is cached for a period of time.
|
Once a load value is determined, it is cached for a period of time.
|
||||||
See the cache_time below.
|
See the cache_time below.
|
||||||
|
|
||||||
Since fork/exec is expensive in perl you'll want to use cache_time to avoid increasing your load on every connection by checking system load.
|
Since fork/exec is expensive in perl, if using the 'uptime' method,
|
||||||
|
use cache_time to avoid increasing your load on every connection.
|
||||||
|
|
||||||
=head1 CONFIG
|
=head1 CONFIG
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ assigned number of seconds. (Default: 10)
|
|||||||
|
|
||||||
uptime
|
uptime
|
||||||
|
|
||||||
The path to the command 'uptime' if different than the default.
|
The path to the command 'uptime' if different than the default.
|
||||||
(Default: /usr/bin/uptime)
|
(Default: /usr/bin/uptime)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -52,74 +53,50 @@ Steve Kemp's announcement of an alternate load limiter: http://www.nntp.perl.org
|
|||||||
|
|
||||||
Written by Peter Eisch <peter@boku.net>.
|
Written by Peter Eisch <peter@boku.net>.
|
||||||
|
|
||||||
|
=head1 CHANGES
|
||||||
|
|
||||||
|
v0.03 - msimerson - 2014-03-21
|
||||||
|
|
||||||
|
* refactored "find the way to get load avg" out of loadcheck (every
|
||||||
|
connection) into get_load_method which is run in register. If we can't
|
||||||
|
get the load average, don't register the hook.
|
||||||
|
|
||||||
|
* added BSD::getloadavg method (tested on FreeBSD)
|
||||||
|
|
||||||
|
v0.02 - github@rsiddall - resurrected from list archives
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
my $VERSION = 0.02;
|
my $VERSION = 0.03;
|
||||||
|
|
||||||
sub register {
|
sub register {
|
||||||
my ($self, $qp, @args) = @_;
|
my ($self, $qp, @args) = @_;
|
||||||
|
|
||||||
%{$self->{_args}} = @args;
|
$self->{_args} = { @args };
|
||||||
|
|
||||||
$self->{_args}->{max_load} = 7
|
|
||||||
if (!defined $self->{_args}->{max_load});
|
|
||||||
|
|
||||||
$self->{_args}->{uptime} = '/usr/bin/uptime'
|
|
||||||
if (!defined $self->{_args}->{uptime});
|
|
||||||
|
|
||||||
$self->{_args}->{cache_time} = 10
|
|
||||||
if (!defined $self->{_args}->{cache_time});
|
|
||||||
|
|
||||||
|
$self->{_args}{max_load} ||= 7;
|
||||||
|
$self->{_args}{uptime} ||= '/usr/bin/uptime';
|
||||||
|
$self->{_args}{cache_time} ||= 10;
|
||||||
$self->{_load} = -1;
|
$self->{_load} = -1;
|
||||||
$self->{_time} = 0;
|
$self->{_time} = 0;
|
||||||
|
$self->{_method} = $self->get_load_method();
|
||||||
|
|
||||||
$self->register_hook("connect", "loadcheck");
|
# only register the hook if we can measure load
|
||||||
|
if (ref $self->{_method} eq 'CODE') {
|
||||||
|
$self->register_hook("connect", "loadcheck");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub loadcheck {
|
sub loadcheck {
|
||||||
my ($self, $transaction) = @_;
|
my ($self, $transaction) = @_;
|
||||||
|
|
||||||
if (time() > ($self->{_time} + $self->{_args}->{cache_time})) {
|
if (time() > ($self->{_time} + $self->{_args}{cache_time})) {
|
||||||
|
# cache value expired, update
|
||||||
|
$self->{_method}->();
|
||||||
|
$self->{_time} = time();
|
||||||
|
};
|
||||||
|
|
||||||
# cached value expired
|
if ($self->{_load} > $self->{_args}{max_load}) {
|
||||||
|
|
||||||
if (-r '/kern/loadavg') { # *BSD
|
|
||||||
# contains fix-point scaling value
|
|
||||||
open(LD, "</kern/loadavg");
|
|
||||||
my $res = <LD>;
|
|
||||||
close LD;
|
|
||||||
my @vals = split(/ /, $res);
|
|
||||||
$self->{_load} = ($val[0] / $val[3]);
|
|
||||||
$self->{_time} = time();
|
|
||||||
$self->log(LOGDEBUG, "/kern/loadavg reported: $self->{_load}");
|
|
||||||
}
|
|
||||||
elsif (-r '/proc/loadavg') { # *inux
|
|
||||||
# contains decimal value
|
|
||||||
# contains fix-point scaling value
|
|
||||||
open(LD, "</proc/loadavg");
|
|
||||||
my $res = <LD>;
|
|
||||||
close LD;
|
|
||||||
$self->{_load} = (split(/ /, $res))[0];
|
|
||||||
$self->{_time} = time();
|
|
||||||
$self->log(LOGDEBUG, "/proc/loadavg reported: $self->{_load}");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
# the various formats returned:
|
|
||||||
#10:33AM up 2:06, 1 user, load averages: 6.55, 3.76, 2.48
|
|
||||||
# 12:29am 2 users, load average: 0.05, 0.05, 0.06
|
|
||||||
# 12:30am up 5 days, 12:43, 1 user, load average: 0.00, 0.00, 0.00
|
|
||||||
|
|
||||||
my $res = `$self->{_args}->{uptime}`;
|
|
||||||
if ($res =~ /aver\S+: (\d+\.\d+)/) {
|
|
||||||
$self->{_load} = $1;
|
|
||||||
$self->{_time} = time();
|
|
||||||
$self->log(LOGDEBUG,
|
|
||||||
"$self->{_args}->{uptime} reported: $self->{_load}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($self->{_load} > $self->{_args}->{max_load}) {
|
|
||||||
$self->log(LOGERROR, "local load too high: $self->{_load}");
|
$self->log(LOGERROR, "local load too high: $self->{_load}");
|
||||||
return DENYSOFT;
|
return DENYSOFT;
|
||||||
}
|
}
|
||||||
@ -127,3 +104,55 @@ sub loadcheck {
|
|||||||
return (DECLINED, "continuing with load: $self->{_load}");
|
return (DECLINED, "continuing with load: $self->{_load}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub get_load_method {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
eval "use BSD::getloadavg;";
|
||||||
|
if (!$@) {
|
||||||
|
return sub {
|
||||||
|
require BSD::getloadavg;
|
||||||
|
$self->{_load} = (getloadavg())[0];
|
||||||
|
$self->log(LOGDEBUG, "BSD::getloadavg reported: $self->{_load}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-r '/kern/loadavg') { # *BSD
|
||||||
|
return sub {
|
||||||
|
open(LD, '<', "/kern/loadavg"); # contains fix-point scaling value
|
||||||
|
my $res = <LD>;
|
||||||
|
close LD;
|
||||||
|
my @vals = split(/ /, $res);
|
||||||
|
$self->{_load} = ($vals[0] / $vals[3]);
|
||||||
|
$self->log(LOGDEBUG, "/kern/loadavg reported: $self->{_load}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-r '/proc/loadavg') { # *inux
|
||||||
|
return sub {
|
||||||
|
open(LD, "<", "/proc/loadavg"); # contains decimal value
|
||||||
|
my $res = <LD>; # contains fix-point scaling value
|
||||||
|
close LD;
|
||||||
|
$self->{_load} = (split(/ /, $res))[0];
|
||||||
|
$self->log(LOGDEBUG, "/proc/loadavg reported: $self->{_load}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-x $self->{_args}{uptime}) {
|
||||||
|
return sub {
|
||||||
|
# the various formats returned:
|
||||||
|
# 10:33AM up 2:06, 1 user, load averages: 6.55, 3.76, 2.48
|
||||||
|
# 12:29am 2 users, load average: 0.05, 0.05, 0.06
|
||||||
|
# 12:30am up 5 days, 12:43, 1 user, load average: 0.00, 0.00, 0.00
|
||||||
|
|
||||||
|
my $res = `$self->{_args}{uptime}`;
|
||||||
|
if ($res =~ /aver\S+: (\d+\.\d+)/) {
|
||||||
|
$self->{_load} = $1;
|
||||||
|
$self->log(LOGDEBUG, "$self->{_args}{uptime} reported: $self->{_load}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->log(LOGERROR, "unable to acquire system load");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user