From 1aa624d182cdec1d1f5caa69f814df29947a76f0 Mon Sep 17 00:00:00 2001 From: Tobi Oetiker Date: Sat, 28 Aug 2010 07:59:55 +0000 Subject: I run smokeping on many boxes and and my Gentoo/Funtoo boxes frequently run into localization setup issues which will bomb out Smokeping's web interface. It works fine invoked from the shell. I use the attached patch to help me diagnose the server setup problem. The behavior is identical to current Smokeping in that it logs a message and throws a HTTP 500 error. The basic Smokeping localization sanity check has uncovered "insane" setups where the PERL %ENV environment variables are being ignored by "setlocale" on several of my boxes for unknown reasons. Obviously, smokeping should quit, which it does... -- Lee Thompson stagr.lee gmail.com --- lib/Smokeping.pm | 82 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 17 deletions(-) (limited to 'lib/Smokeping.pm') diff --git a/lib/Smokeping.pm b/lib/Smokeping.pm index 136b56b..6828430 100644 --- a/lib/Smokeping.pm +++ b/lib/Smokeping.pm @@ -8,7 +8,9 @@ use Pod::Usage; use Digest::MD5 qw(md5_base64); use SNMP_util; use SNMP_Session; -use POSIX; +# enable locale?? +#use locale; +use POSIX qw(locale_h signal_h sys_wait_h); use Smokeping::Config; use RRDs; use Sys::Syslog qw(:DEFAULT setlogsock); @@ -26,9 +28,36 @@ setlogsock('unix') # make sure we do not end up with , in odd places where one would expect a '.' # we set the environment variable so that our 'kids' get the benefit too -$ENV{LC_NUMERIC}='C'; -if (POSIX::setlocale(&POSIX::LC_NUMERIC,"") ne "C") { - die("Resetting LC_NUMERIC failed - try removing LC_ALL from the environment"); +$ENV{'LC_NUMERIC'}='C'; +if (setlocale(LC_NUMERIC,"") ne "C") { + if ($ENV{'LC_ALL'} eq 'C') { + # This has got to be a bug in perl/mod_perl, apache or libc + die("Your internalization implementation on your operating system is " + . "not responding to your setup of LC_ALL to \"C\" as LC_NUMERIC is " + . "coming up as \"" . setlocale(LC_NUMERIC, "") . "\" leaving " + . "smokeping unable to compare numbers..."); + } + elsif ($ENV{'LC_ALL'} ne "") { + # This error is most likely setup related and easy to fix with proper + # setup of the operating system or multilanguage locale setup. Hint, + # setting LANG is better than setting LC_ALL... + die("Resetting LC_NUMERIC failed probably because your international " + . "setup of the LC_ALL to \"". $ENV{'LC_ALL'} . "\" is overridding " + . "LC_NUMERIC. Setting LC_ALL is not compatible with smokeping..."); + } + else { + # This is pretty nasty to figure out. Seems there are still lots + # of bugs in LOCALE behavior and if you get this error, you are + # affected by it. The worst is when "setlocale" is reading the + # environment variables of your webserver and not reading the PERL + # %ENV array like it should. + die("Something is wrong with the internalization setup of your " + . "operating system, webserver, or the perl plugin to your webserver " + . "(like mod_perl) and smokeping can not compare numbers correctly. " + . "On unix, check your /etc/locale.gen and run sudo locale-gen, set " + . "LC_NUMERIC in your perl plugin config or even your webserver " + . "startup script to potentially fix or work around the problem..."); + } } @@ -311,11 +340,14 @@ FOR for(1..$multis){ $extra .= "-\$i$_"; }; - /^(==|!=|<|>|<=|>=|\*)(\d+(?:\.\d*)?|U|S|\d*\*)(%?)$/ + /^(==|!=|<|>|<=|>=|\*)(\d+(?:\.\d*)?|U|S|\d*\*)(%?)(?:(<|>|<=|>=)(\d+(?:\.\d*)?)(%?))$/ or die "ERROR: Alert $al pattern entry '$_' is invalid\n"; my $op = $1; my $value = $2; my $perc = $3; + my $op2 = $4; + my $value2 = $5; + my $perc2 = $6; if ($op eq '*') { if ($value =~ /^([1-9]\d*)\*$/) { $value = $1; @@ -336,17 +368,17 @@ FOR } elsif ($value eq 'U') { if ($op eq '==') { $sub .= "$it next if defined \$y->[$i$extra];\n"; - } elsif ($op eq '!=') { - $sub .= "$it next unless defined \$y->[$i$extra];\n"; - } else { - die "ERROR: invalid operator $op in connection U in Alert $al definition\n"; - } + } elsif ($op eq '!=') { + $sub .= "$it next unless defined \$y->[$i$extra];\n"; + } else { + die "ERROR: invalid operator $op in connection U in Alert $al definition\n"; + } } elsif ($value eq 'S') { if ($op eq '==') { $sub .= "$it next unless defined \$y->[$i$extra] and \$y->[$i$extra] eq 'S';\n"; } else { die "ERROR: S is only valid with == operator in Alert $al definition\n"; - } + } } elsif ($value eq '*') { if ($op ne '==') { die "ERROR: operator $op makes no sense with * in Alert $al definition\n"; @@ -354,16 +386,27 @@ FOR } else { if ( $x->{type} eq 'loss') { die "ERROR: loss should be specified in % (alert $al pattern)\n" unless $perc eq "%"; - } elsif ( $x->{type} eq 'rtt' ) { - $value /= 1000; - } else { - die "ERROR: unknown alert type $x->{type}\n"; - } + } elsif ( $x->{type} eq 'rtt' ) { + $value /= 1000; + } else { + die "ERROR: unknown alert type $x->{type}\n"; + } $sub .= <[$i$extra] $it and \$y->[$i$extra] =~ /^\\d/ -$it and \$y->[$i$extra] $op $value; +$it and \$y->[$i$extra] $op $value IF + if ($op2){ + if ( $x->{type} eq 'loss') { + die "ERROR: loss should be specified in % (alert $al pattern)\n" unless $perc2 eq "%"; + } elsif ( $x->{type} eq 'rtt' ) { + $value2 /= 1000; + } + $sub .= <[$i$extra] $op2 $value2 +IF + } + $sub .= "$it ;"; } $i++; } @@ -3205,6 +3248,11 @@ You can write to detect lines that have been losing more than 20% of the packets for two periods after startup. +If you want to make sure a value within a certain range you can use two conditions +in one element + + >45%<=55% + Sometimes it may be that conditions occur at irregular intervals. But still you only want to throw an alert if they occur several times within a certain amount of times. The operator B<*X*> will ignore up to I values and still -- cgit v1.2.3-24-g4f1b