summaryrefslogtreecommitdiffstats
path: root/lib/Smokeping/matchers
diff options
context:
space:
mode:
authorNiko Tyni <ntyni@iki.fi>2005-02-13 20:23:04 +0100
committerNiko Tyni <ntyni@iki.fi>2005-02-13 20:23:04 +0100
commit6d76521656e91daa160bc8019828f1b68d7aa5dc (patch)
treeaaa27615a0702942fa1606d9a5c89f0a3547467c /lib/Smokeping/matchers
parent6dba1afbe4b475a7d34f5ef867b7b37291cd1484 (diff)
downloadsmokeping-6d76521656e91daa160bc8019828f1b68d7aa5dc.tar.gz
smokeping-6d76521656e91daa160bc8019828f1b68d7aa5dc.tar.xz
Moved probes, matchers and ciscoRttMonMIB modules to lib/Smokeping.
Diffstat (limited to 'lib/Smokeping/matchers')
-rw-r--r--lib/Smokeping/matchers/avgratio.pm148
-rw-r--r--lib/Smokeping/matchers/base.pm127
-rw-r--r--lib/Smokeping/matchers/median.pm80
3 files changed, 355 insertions, 0 deletions
diff --git a/lib/Smokeping/matchers/avgratio.pm b/lib/Smokeping/matchers/avgratio.pm
new file mode 100644
index 0000000..fab0164
--- /dev/null
+++ b/lib/Smokeping/matchers/avgratio.pm
@@ -0,0 +1,148 @@
+package Smokeping::matchers::avgratio;
+
+=head1 NAME
+
+Smokeping::matchers::avgratio - detect changes in average median latency
+
+=head1 OVERVIEW
+
+The avgratio matcher establishes a historic average median latency over
+several measurement rounds. It compares this average, against a second
+average latency value again build over several rounds of measurment.
+
+=head1 DESCRIPTION
+
+Call the matcher with the following sequence:
+
+ type = matcher
+ pattern = avgratio(historic=>a,current=>b,comparator=>o,percentage=>p)
+
+=over
+
+=item historic
+
+The number of median values to use for building the 'historic' average.
+
+=item current
+
+The number of median values to use for building the 'current' average.
+
+=item comparator
+
+Which comparison operator should be used to compare current/historic with percentage.
+
+=item percentage
+
+Right hand side of the comparison.
+
+=back
+
+ old <--- historic ---><--- current ---> now
+
+=head1 EXAMPLE
+
+Take build the average median latency over 10 samples, use this to divid the
+current average latency built over 2 samples and check if it is bigger than
+150%.
+
+ avgratio(historic=>10,current=>2,comparator=>'>',percentage=>150);
+
+ avg(current)/avg(historic) > 150/100
+
+This means the matcher will activate when the current latency average if
+more than 1.5 times the historic latency average established over the last
+10 rounds of measurement.
+
+=head1 COPYRIGHT
+
+Copyright (c) 2004 by OETIKER+PARTNER AG. All rights reserved.
+
+=head1 SPONSORSHIP
+
+The development of this matcher has been sponsored by Virtela Communications www.virtela.net.
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+=head1 AUTHOR
+
+Tobias Oetiker <tobi@oetiker.ch>
+
+=cut
+
+use vars qw($VERSION);
+
+
+$VERSION = 1.0;
+
+use strict;
+use base qw(Smokeping::matchers::base);
+use Carp;
+
+sub new(@)
+{
+ my $class = shift;
+ my $rules = {
+ historic=>'\d+',
+ current=>'\d+',
+ comparator=>'(<|>|<=|>=|==)',
+ percentage=>'\d+(\.\d+)?' };
+
+ my $self = $class->SUPER::new($rules,@_);
+ $self->{param}{sub} = eval "sub {\$_[0] ".$self->{param}{comparator}." \$_[1]}";
+ croak "compiling comparator $self->{param}{comparator}: $@" if $@;
+ $self->{param}{value} = $self->{param}{percentage}/100;
+ return $self;
+}
+
+sub Length($)
+{
+ my $self = shift;
+ return $self->{param}{historic} + $self->{param}{current};
+}
+
+sub Desc ($) {
+ croak "Detect changes in average median latency";
+}
+
+sub avg(@){
+ my $sum=0;
+ my $cnt=0;
+ for (@_){
+ next unless defined $_;
+ $sum += $_;
+ $cnt ++;
+ }
+ return $sum/$cnt if $cnt;
+ return undef;
+}
+
+sub Test($$)
+{ my $self = shift;
+ my $data = shift; # @{$data->{rtt}} and @{$data->{loss}}
+ my $len = $self->Length;
+ my $rlen = scalar @{$data->{rtt}};
+ return undef
+ if $rlen < $len
+ or (defined $data->{rtt}[-$len] and $data->{rtt}[-$len] eq 'S');
+ my $ac = $self->{param}{historic};
+ my $bc = $self->{param}{current};
+ my $cc = $ac +$bc;
+ my $ha = avg(@{$data->{rtt}}[-$cc..-$bc-1]);
+ my $ca = avg(@{$data->{rtt}}[-$bc..-1]);
+ return undef unless $ha and $ca;
+ return &{$self->{param}{sub}}($ca/$ha,$self->{param}{value});
+}
diff --git a/lib/Smokeping/matchers/base.pm b/lib/Smokeping/matchers/base.pm
new file mode 100644
index 0000000..cd69871
--- /dev/null
+++ b/lib/Smokeping/matchers/base.pm
@@ -0,0 +1,127 @@
+package Smokeping::matchers::base;
+
+=head1 NAME
+
+Smokeping::matchers::base - Base Class for implementing SmokePing Matchers
+
+=head1 OVERVIEW
+
+This is the base class for writing SmokePing matchers. Every matcher must
+inherit from the base class and provide it's own methods for the 'buisness'
+logic.
+
+=head1 DESCRIPTION
+
+Every matcher must provide the following methods:
+
+=cut
+
+use vars qw($VERSION);
+use Carp;
+
+$VERSION = 1.0;
+
+use strict;
+
+=head2 new
+
+The new method expects hash elements as an argument
+eg new({x=>'\d+',y=>'\d+'},x=>1,y=>2). The first part is
+a syntax rule for the arguments it should expect and the second part
+are the arguments itself. The first part will be supplied
+by the child class as it calls the partent method.
+
+=cut
+
+sub new(@)
+{
+ my $this = shift;
+ my $class = ref($this) || $this;
+ my $rules = shift;
+ my $self = { param => { @_ } };
+ foreach my $key (keys %{$self->{param}}){
+ my $regex = $rules->{$key};
+ croak "key '$key' is not known byt this matcher" unless defined $rules->{$key};
+ croak "key '$key' contains invalid data: '$self->{param}{$key}'" unless $self->{param}{$key} =~ m/^$regex$/;
+ }
+ bless $self, $class;
+ return $self;
+}
+
+=head2 Length
+
+The Length method returns the number of values the
+matcher will expect from SmokePing. This method must
+be overridden by the children of the base class.
+
+=cut
+
+sub Length($)
+{
+ my $self = shift;
+ croak "SequenceLength must be overridden by the subclass";
+}
+
+=head2 Desc
+
+Simply return the description of the function. This method must
+be overwritten by a children of the base class.
+
+=cut
+
+
+sub Desc ($) {
+ croak "MatcherDesc must be overridden by the subclass";
+}
+
+=head2 Test
+
+Run the matcher and return true or false. The Test method is called
+with a hash of two arrays giving it access to both rtt and loss values
+
+ my $data=shift;
+ my @rtt = @{$data->{rtt}};
+ my @loss = @{$data->{loss}};
+
+The arrays are ordered from old to new.
+
+ @rdd[old..new]
+
+There may be more than the expected number of elements in this array. Address them with
+$x[-1] to $x[-max].
+
+
+=cut
+
+sub Test($$)
+{ my $self = shift;
+ my $data = shift; # @{$data->{rtt}} and @{$data->{loss}}
+ croak "Match must be overridden by the subclass";
+
+}
+
+=head1 COPYRIGHT
+
+Copyright (c) 2004 by OETIKER+PARTNER AG. All rights reserved.
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+=head1 AUTHOR
+
+Tobias Oetiker <tobi@oetiker.ch>
+
+=cut
diff --git a/lib/Smokeping/matchers/median.pm b/lib/Smokeping/matchers/median.pm
new file mode 100644
index 0000000..e8d43cf
--- /dev/null
+++ b/lib/Smokeping/matchers/median.pm
@@ -0,0 +1,80 @@
+package Smokeping::matchers::median;
+
+=head1 NAME
+
+Smokeping::matchers::median - Find persistant change in latency
+
+=head1 OVERVIEW
+
+The idea behind this matcher is to find sustained changes in latency.
+
+The median matcher takes a number of past median latencies. It splits the latencies into
+two groups (old and new) and again finds the median for each groups. If the
+difference between the two medians is bigger than a certain value, it will
+give a match.
+
+=head1 DESCRIPTION
+
+Call the matcher with the following sequence:
+
+ type = matcher
+ pattern = median(old=>x,new=>y,diff=>z)
+
+This will create a matcher which consumes x+y latency-datapoints, builds the
+two medians and the matches if the difference between the median latency is
+larger than z seconds.
+
+=head1 COPYRIGHT
+
+Copyright (c) 2004 by OETIKER+PARTNER AG. All rights reserved.
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+=head1 AUTHOR
+
+Tobias Oetiker <tobi@oetiker.ch>
+
+=cut
+
+use strict;
+use base qw(Smokeping::matchers::base);
+use vars qw($VERSION);
+$VERSION = 1.0;
+use Carp;
+
+# how many values does the matcher need to do it's magic
+sub Length($)
+{
+ my $self = shift;
+ return $self->{param}{old} + $self->{param}{new};
+}
+
+sub Desc ($) {
+ croak "Finde changes in median latency";
+}
+
+sub Test($$)
+{ my $self = shift;
+ my $data = shift; # @{$data->{rtt}} and @{$data->{loss}}
+ my $ac = $self->{param}{old};
+ my $bc = $self->{param}{new};
+ my $cc = $ac +$bc;
+ my $oldm = (sort {$a <=> $b} @{$data->{rtt}}[-$cc..-$bc-1])[int($a/2)];
+ $ac++;
+ my $newm = (sort {$a <=> $b} @{$data->{rtt}}[-$bc..-1])[int($bc/2)];
+ return abs($oldm-$newm) > $self->{param}{diff};
+}