extend perfdata output

This commit is contained in:
garnier-quentin 2019-01-08 14:06:30 +01:00
parent 2fd9b453a5
commit 9d488a9e20
3 changed files with 313 additions and 58 deletions

View File

@ -389,12 +389,48 @@ sub change_seconds {
return $str;
}
sub scale_bytesbit {
my (%options) = @_;
my $base = 1024;
if (defined($options{dst_unit}) && defined($options{src_unit})) {
$options{value} *= 8 if ($options{dst_unit} =~ /b/ && $options{src_unit} =~ /B/);
$options{value} /= 8 if ($options{dst_unit} =~ /B/ && $options{src_unit} =~ /b/);
if ($options{dst_unit} =~ /b/) {
$base = 1000;
}
}
my %expo = ('' => 0, k => 1, m => 2, g => 3, t => 4, p => 5, e => 6);
my ($src_expo, $dst_expo) = (0, 0);
$src_expo = $expo{lc($options{src_quantity})} if (defined($options{src_quantity}) && $options{src_quantity} =~ /[kmgtpe]/i);
if ($options{dst_unit} eq 'auto') {
my @auto = ('', 'k', 'm', 'g', 't', 'p', 'e');
my $i = defined($options{src_quantity}) ? $expo{$options{src_quantity}} : 0;
for (; $i < scalar(@auto); $i++) {
last if ($options{value} < $base);
$options{value} = $options{value} / $base;
}
return ($options{value}, $auto[$i], $options{src_unit});
} elsif (defined($options{dst_quantity}) && ($options{dst_quantity} eq '' || $options{dst_quantity} =~ /[kmgtpe]/i )) {
my $dst_expo = $expo{lc($options{dst_quantity})};
if ($dst_expo - $src_expo > 0) {
$options{value} = $options{value} / ($base ** ($dst_expo - $src_expo));
} elsif ($dst_expo - $src_expo < 0) {
$options{value} = $options{value} * ($base ** (($dst_expo - $src_expo) * -1));
}
}
return $options{value};
}
sub convert_bytes {
my (%options) = @_;
my %expo = (k => 1, m => 2, g => 3, t => 4);
my %expo = (k => 1, m => 2, g => 3, t => 4, p => 5);
my $value = $options{value};
my $base = defined($options{network}) ? 1000 : 1024;
my $base = defined($options{network}) ? 1000 : 1024;
if ($options{unit} =~ /([kmgt])b/i) {
$value = $value * ($base ** $expo{lc($1)});
}
@ -403,40 +439,45 @@ sub convert_bytes {
}
sub parse_threshold {
my ($perf) = @_;
my (%options) = @_;
$perf = trim($perf);
my $perf = trim($options{threshold});
my $perf_result = { arobase => 0, infinite_neg => 0, infinite_pos => 0, start => "", end => "" };
my $arobase = 0;
my $infinite_neg = 0;
my $infinite_pos = 0;
my $value_start = "";
my $value_end = "";
my $global_status = 1;
my $global_status = 1;
if ($perf =~ /^(\@?)((?:~|(?:\+|-)?\d+(?:[\.,]\d+)?|):)?((?:\+|-)?\d+(?:[\.,]\d+)?)?$/) {
$value_start = $2 if (defined($2));
$value_end = $3 if (defined($3));
$arobase = 1 if (defined($1) && $1 eq '@');
$value_start =~ s/[\+:]//g;
$value_end =~ s/\+//;
if ($value_end eq '') {
$value_end = 1e500;
$infinite_pos = 1;
$perf_result->{start} = $2 if (defined($2));
$perf_result->{end} = $3 if (defined($3));
$perf_result->{arobase} = 1 if (defined($1) && $1 eq '@');
$perf_result->{start} =~ s/[\+:]//g;
$perf_result->{end} =~ s/\+//;
if ($perf_result->{end} eq '') {
$perf_result->{end} = 1e500;
$perf_result->{infinite_pos} = 1;
}
$value_start = 0 if ($value_start eq '');
$value_start =~ s/,/\./;
$value_end =~ s/,/\./;
$perf_result->{start} = 0 if ($perf_result->{start} eq '');
$perf_result->{start} =~ s/,/\./;
$perf_result->{end} =~ s/,/\./;
if ($value_start eq '~') {
$value_start = -1e500;
$infinite_neg = 1;
if ($perf_result->{start} eq '~') {
$perf_result->{start} = -1e500;
$perf_result->{infinite_neg} = 1;
}
} else {
$global_status = 0;
}
return ($global_status, $value_start, $value_end, $arobase, $infinite_neg, $infinite_pos);
return ($global_status, $perf_result);
}
sub get_threshold_litteral {
my (%options) = @_;
my $perf_output = ($options{arobase} == 1 ? "@" : "") .
(($options{infinite_neg} == 0) ? $options{start} : "~") .
":" .
(($options{infinite_pos} == 0) ? $options{end} : "");
return $perf_output;
}
1;

View File

@ -39,6 +39,7 @@ sub new {
"range-perfdata:s" => { name => 'range_perfdata' },
"filter-perfdata:s" => { name => 'filter_perfdata' },
"change-perfdata:s@" => { name => 'change_perfdata' },
"extend-perfdata:s@" => { name => 'extend_perfdata' },
"filter-uom:s" => { name => 'filter_uom' },
"verbose" => { name => 'verbose' },
"debug" => { name => 'debug' },
@ -237,7 +238,7 @@ sub output_json {
}
if ($options{force_ignore_perfdata} == 0) {
$self->change_perfdatas();
$self->change_perfdata();
foreach my $perf (@{$self->{perfdatas}}) {
next if (defined($self->{option_results}->{filter_perfdata}) &&
$perf->{label} !~ /$self->{option_results}->{filter_perfdata}/);
@ -327,7 +328,7 @@ sub output_xml {
}
if ($options{force_ignore_perfdata} == 0) {
$self->change_perfdatas();
$self->change_perfdata();
foreach my $perf (@{$self->{perfdatas}}) {
next if (defined($self->{option_results}->{filter_perfdata}) &&
$perf->{label} !~ /$self->{option_results}->{filter_perfdata}/);
@ -375,7 +376,7 @@ sub output_txt {
print "\n";
} else {
print "|";
$self->change_perfdatas();
$self->change_perfdata();
foreach my $perf (@{$self->{perfdatas}}) {
next if (defined($self->{option_results}->{filter_perfdata}) &&
$perf->{label} !~ /$self->{option_results}->{filter_perfdata}/);
@ -708,45 +709,216 @@ sub is_disco_show {
return 0;
}
# --add-perfdata=used,,scale(auto)
# --add-perfdata=used,,scale(MB)
# --add-perfdata=traffic_in,,scale(Mbps),mbps
# --add-perfdata=used,,percent()
# --add-perfdata=perfx,,math(perfx+10-100)
# --add-perfdata=free,used,used()
# --add-perfdata=used,free,free()
# ^([KMGTP])?(B|b|bps|\/s|auto)$
sub parse_pfdata_scale {
my ($self, %options) = @_;
# --extend-perfdata=traffic_in,,scale(Mbps),mbps
my $args = { unit => 'auto' };
if ($options{args} =~ /^([KMGTPEkmgtpe])?(B|b|bps|Bps|b\/s|auto)$/) {
$args->{quantity} = defined($1) ? $1 : '';
$args->{unit} = $2;
} elsif ($options{args} ne '') {
return 1;
}
return (0, $args);
}
# parse_threshold est dans misc maintenant.
sub parse_pfdata_math {
my ($self, %options) = @_;
# --extend-perfdata=perfx,,math(current + 10 - 100, 1)
my $args = { math => undef, apply_threshold => 0 };
my ($math, $apply_threshold) = split /\|/, $options{args};
if ($math =~ /^((?:[\s\.\-\+\*\/0-9\(\)]|current)+)$/) {
$args->{math} = $1;
} elsif ($options{args} ne '') {
return 1;
}
if (defined($apply_threshold) && $apply_threshold =~ /^\s*(0|1)\s*$/ ) {
$args->{apply_threshold} = $1;
}
return (0, $args);
}
sub apply_pfdata_scale {
my ($self, %options) = @_;
return if (${$options{perf}}->{unit} !~ /^([KMGTPEkmgtpe])?(B|b|bps|Bps|b\/s)$/);
my ($src_quantity, $src_unit) = ($1, $2);
my ($value, $dst_quantity, $dst_unit) = centreon::plugins::misc::scale_bytesbit(value => ${$options{perf}}->{value},
src_quantity => $src_quantity, src_unit => $src_unit, dst_quantity => $options{args}->{quantity}, dst_unit => $options{args}->{unit});
${$options{perf}}->{value} = sprintf("%.2f", $value);
if (defined($dst_unit)) {
${$options{perf}}->{unit} = $dst_quantity . $dst_unit;
} else {
${$options{perf}}->{unit} = $options{args}->{quantity} . $options{args}->{unit};
}
if (defined(${$options{perf}}->{max}) && ${$options{perf}}->{max} ne '') {
($value) = centreon::plugins::misc::scale_bytesbit(value => ${$options{perf}}->{max},
src_quantity => $src_quantity, src_unit => $src_unit,
dst_quantity => defined($dst_unit) ? $dst_quantity : $options{args}->{quantity},
dst_unit => defined($dst_unit) ? $dst_unit : $options{args}->{unit});
${$options{perf}}->{max} = sprintf("%.2f", $value);
}
foreach my $threshold ('warning', 'critical') {
next if (${$options{perf}}->{$threshold} eq '');
my ($status, $result) = centreon::plugins::misc::parse_threshold(threshold => ${$options{perf}}->{$threshold});
next if ($status == 0);
if ($result->{start} ne '' && $result->{infinite_neg} == 0) {
($result->{start}) = centreon::plugins::misc::scale_bytesbit(value => $result->{start},
src_quantity => $src_quantity, src_unit => $src_unit,
dst_quantity => defined($dst_unit) ? $dst_quantity : $options{args}->{quantity},
dst_unit => defined($dst_unit) ? $dst_unit : $options{args}->{unit});
}
if ($result->{end} ne '' && $result->{infinite_pos} == 0) {
($result->{end}) = centreon::plugins::misc::scale_bytesbit(value => $result->{end},
src_quantity => $src_quantity, src_unit => $src_unit,
dst_quantity => defined($dst_unit) ? $dst_quantity : $options{args}->{quantity},
dst_unit => defined($dst_unit) ? $dst_unit : $options{args}->{unit});
}
${$options{perf}}->{$threshold} = centreon::plugins::misc::get_threshold_litteral(%$result);
}
}
sub apply_pfdata_invert {
my ($self, %options) = @_;
return if (!defined(${$options{perf}}->{max}) || ${$options{perf}}->{max} eq '');
${$options{perf}}->{value} = ${$options{perf}}->{max} - ${$options{perf}}->{value};
foreach my $threshold ('warning', 'critical') {
next if (${$options{perf}}->{$threshold} eq '');
my ($status, $result) = centreon::plugins::misc::parse_threshold(threshold => ${$options{perf}}->{$threshold});
next if ($status == 0);
my $tmp = { arobase => $result->{arobase}, infinite_pos => 0, infinite_neg => 0, start => $result->{start}, end => $result->{end} };
$tmp->{infinite_neg} = 1 if ($result->{infinite_pos} == 1);
$tmp->{infinite_pos} = 1 if ($result->{infinite_neg} == 1);
if ($result->{start} ne '' && $result->{infinite_neg} == 0) {
$tmp->{end} = ${$options{perf}}->{max} - $result->{start};
}
if ($result->{end} ne '' && $result->{infinite_pos} == 0) {
$tmp->{start} = ${$options{perf}}->{max} - $result->{end};
}
${$options{perf}}->{$threshold} = centreon::plugins::misc::get_threshold_litteral(%$tmp);
}
}
sub apply_pfdata_percent {
my ($self, %options) = @_;
return if (!defined(${$options{perf}}->{max}) || ${$options{perf}}->{max} eq '');
${$options{perf}}->{value} = sprintf("%.2f", ${$options{perf}}->{value} * 100 / ${$options{perf}}->{max});
${$options{perf}}->{unit} = '%';
foreach my $threshold ('warning', 'critical') {
next if (${$options{perf}}->{$threshold} eq '');
my ($status, $result) = centreon::plugins::misc::parse_threshold(threshold => ${$options{perf}}->{$threshold});
next if ($status == 0);
if ($result->{start} ne '' && $result->{infinite_neg} == 0) {
$result->{start} = sprintf("%.2f", $result->{start} * 100 / ${$options{perf}}->{max});
}
if ($result->{end} ne '' && $result->{infinite_pos} == 0) {
$result->{end} = sprintf("%.2f", $result->{end} * 100 / ${$options{perf}}->{max});
}
${$options{perf}}->{$threshold} = centreon::plugins::misc::get_threshold_litteral(%$result);
}
${$options{perf}}->{max} = 100;
}
sub apply_pfdata_math {
my ($self, %options) = @_;
my $math = $options{args}->{math};
$math =~ s/current/\$value/g;
my $value = ${$options{perf}}->{value};
eval "\${\$options{perf}}->{value} = $math";
return if ($options{args}->{apply_threshold} == 0);
foreach my $threshold ('warning', 'critical') {
next if (${$options{perf}}->{$threshold} eq '');
my ($status, $result) = centreon::plugins::misc::parse_threshold(threshold => ${$options{perf}}->{$threshold});
next if ($status == 0);
if ($result->{start} ne '' && $result->{infinite_neg} == 0) {
$value = $result->{start};
eval "\$result->{start} = $math";
}
if ($result->{end} ne '' && $result->{infinite_pos} == 0) {
$value = $result->{end};
eval "\$result->{end} = $math";
}
${$options{perf}}->{$threshold} = centreon::plugins::misc::get_threshold_litteral(%$result);
}
${$options{perf}}->{max} = 100;
}
sub load_perfdata_extend_args {
my ($self, %options) = @_;
if (defined($self->{option_results}->{change_perfdata})) {
foreach (@{$self->{option_results}->{change_perfdata}}) {
if (! /^(.+?),(.+)$/) {
$self->add_option_msg(short_msg => "Wrong change-perfdata option '" . $_ . "' (syntax: match,substitute)");
$self->option_exit();
}
$self->{change_perfdata}->{$1} = $2;
foreach ([$self->{option_results}->{change_perfdata}, 1], [$self->{option_results}->{extend_perfdata}, 2]) {
next if (!defined($_->[0]));
foreach my $arg (@{$_->[0]}) {
$self->parse_perfdata_extend_args(arg => $arg, type => $_->[1]);
}
}
}
sub change_perfdatas {
sub parse_perfdata_extend_args {
my ($self, %options) = @_;
if ($self->{option_results}->{change_perfdata}) {
foreach (@{$self->{perfdatas}}) {
foreach my $filter (keys %{$self->{change_perfdata}}) {
if ($_->{label} =~ /$filter/) {
eval "\$_->{label} =~ s{$filter}{$self->{change_perfdata}->{$filter}}";
last;
}
# --extend-perfdata=searchlabel,newlabel,method[,newuom]
my ($pfdata_match, $pfdata_substitute, $method, $uom_substitute) = split /,/, $options{arg};
return if (!defined($pfdata_match) || $pfdata_match eq '');
$self->{pfdata_extends} = [] if (!defined($self->{pfdata_extends}));
my $pfdata_extends = {
pfdata_match => defined($pfdata_match) && $pfdata_match ne '' ? $pfdata_match : undef,
pfdata_substitute => defined($pfdata_substitute) && $pfdata_substitute ne '' ? $pfdata_substitute : undef,
uom_substitute => defined($uom_substitute) && $uom_substitute ne '' ? $uom_substitute : undef,
type => $options{type}
};
if (defined($method) && $method ne '') {
if ($method !~ /^\s*(invert|percent|scale|math)\s*\(\s*(.*?)\s*\)\s*$/) {
$self->output_add(long_msg => "method in argument '$options{arg}' is unknown", debug => 1);
return ;
}
$pfdata_extends->{method_name} = $1;
my $args = $2;
if (my $func = $self->can('parse_pfdata_' . $pfdata_extends->{method_name})) {
(my $status, $pfdata_extends->{method_args}) = $func->($self, args => $args);
if ($status == 1) {
$self->output_add(long_msg => "argument in method '$options{arg}' is unknown", debug => 1);
return ;
}
}
}
push @{$self->{pfdata_extends}}, $pfdata_extends;
}
sub apply_perfdata_explode {
my ($self, %options) = @_;
return if ($self->{explode_perfdata_total} == 0);
foreach (@{$self->{perfdatas}}) {
next if ($_->{max} eq '');
@ -763,6 +935,48 @@ sub change_perfdatas {
}
}
sub apply_perfdata_extend {
my ($self, %options) = @_;
foreach my $extend (@{$self->{pfdata_extends}}) {
my $new_pfdata = [];
for (my $i = 0; $i < scalar(@{$self->{perfdatas}}); $i++) {
next if ($self->{perfdatas}->[$i]->{label} !~ /$extend->{pfdata_match}/);
my $new_perf = { %{$self->{perfdatas}->[$i]} };
if (defined($extend->{pfdata_substitute})) {
eval "\$new_perf->{label} =~ s{$extend->{pfdata_match}}{$extend->{pfdata_substitute}}";
}
if (defined($extend->{method_name})) {
my $func = $self->can('apply_pfdata_' . $extend->{method_name});
$func->($self, perf => \$new_perf, args => $extend->{method_args});
}
if (defined($extend->{uom_substitute})) {
$new_perf->{unit} = $extend->{uom_substitute};
}
if ($extend->{type} == 1) {
$self->{perfdatas}->[$i] = $new_perf;
} else {
push @$new_pfdata, $new_perf;
}
}
push @{$self->{perfdatas}}, @$new_pfdata;
}
}
sub change_perfdata {
my ($self, %options) = @_;
$self->apply_perfdata_extend();
$self->apply_perfdata_explode();
}
1;
__END__

View File

@ -78,14 +78,14 @@ sub threshold_validate {
# $options{value} : threshold value
my $status = 1;
$self->{threshold_label}->{$options{label}} = {value => $options{value}, start => undef, end => undef, arobase => undef, infinite_neg => undef, infinite_pos => undef};
$self->{threshold_label}->{$options{label}} = { value => $options{value}, start => undef, end => undef, arobase => undef, infinite_neg => undef, infinite_pos => undef };
if (!defined($options{value}) || $options{value} eq '') {
return $status;
}
($status, $self->{threshold_label}->{$options{label}}->{start}, $self->{threshold_label}->{$options{label}}->{end}, $self->{threshold_label}->{$options{label}}->{arobase}, $self->{threshold_label}->{$options{label}}->{infinite_neg}, $self->{threshold_label}->{$options{label}}->{infinite_pos}) =
centreon::plugins::misc::parse_threshold($options{value});
($status, my $result_perf) =
centreon::plugins::misc::parse_threshold(threshold => $options{value});
$self->{threshold_label}->{$options{label}} = { %{$self->{threshold_label}->{$options{label}}}, %$result_perf };
return $status;
}