root / plugins / munin / munin_stats_plugins @ c5ab6538
Historique | Voir | Annoter | Télécharger (3,94 ko)
| 1 |
#!/usr/bin/env perl |
|---|---|
| 2 |
use 5.010; |
| 3 |
use strict; |
| 4 |
use warnings; |
| 5 |
use autodie; |
| 6 |
use Munin::Plugin; |
| 7 |
use File::Temp qw(tempdir tempfile); |
| 8 |
use Time::HiRes qw(gettimeofday tv_interval); |
| 9 |
use File::Spec::Functions qw(catfile); |
| 10 |
use File::Basename qw(basename); |
| 11 |
|
| 12 |
=head1 NAME |
| 13 |
|
| 14 |
munin_stats_plugins - Report the time it takes to run all munin plugins |
| 15 |
|
| 16 |
=head1 SYNOPSIS |
| 17 |
|
| 18 |
In F</etc/munin/plugin-conf.d/munin-node>, because we invoke plugins |
| 19 |
with munin-run, some of which may need root privileges: |
| 20 |
|
| 21 |
[munin_stats_plugins] |
| 22 |
user root |
| 23 |
|
| 24 |
Put this in cron somewhere: |
| 25 |
|
| 26 |
# Refresh the statistics |
| 27 |
MUNIN_STATS_PLUGINS_RELOAD=1 munin-run munin_stats_plugins |
| 28 |
|
| 29 |
E.g.: |
| 30 |
|
| 31 |
40 4 * * * root MUNIN_STATS_PLUGINS_RELOAD=1 munin-run munin_stats_plugins |
| 32 |
|
| 33 |
Then run it: |
| 34 |
|
| 35 |
# Get the statistics |
| 36 |
munin-run munin_stats_plugins |
| 37 |
|
| 38 |
=head1 DESCRIPTION |
| 39 |
|
| 40 |
Runs all the munin plugins in F</etc/munin/plugins> and reports the |
| 41 |
time it takes to run each one with C<system> and L<Time::HiRes>. Since |
| 42 |
running all the plugins again on each munin-update run would lead to |
| 43 |
epic recursive failure, you have to reload the statistics database |
| 44 |
yourself by reloading it in cron somewhere. |
| 45 |
|
| 46 |
=head1 AUTHOR |
| 47 |
|
| 48 |
E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avar@cpan.org> |
| 49 |
|
| 50 |
=head1 LICENSE |
| 51 |
|
| 52 |
This program is in the public domain. |
| 53 |
|
| 54 |
=head1 MAGIC MARKERS |
| 55 |
|
| 56 |
#%# family=manual |
| 57 |
|
| 58 |
=cut |
| 59 |
|
| 60 |
my $statedir = $ENV{MUNIN_PLUGSTATE};
|
| 61 |
my $statefile = $0; $statefile =~ s[^.*/][]; |
| 62 |
my $cache = catfile($statedir, $statefile . '-cache'); |
| 63 |
my $cache_tmp = "$cache.tmp"; |
| 64 |
|
| 65 |
my @plugins = parse_plugin_time($cache); |
| 66 |
|
| 67 |
# We should reload our data |
| 68 |
if (not $ARGV[0] and $ENV{MUNIN_STATS_PLUGINS_RELOAD}) {
|
| 69 |
$ARGV[0] = 'reload'; |
| 70 |
} |
| 71 |
|
| 72 |
given ($ARGV[0]) {
|
| 73 |
when ("reload") {
|
| 74 |
# Plugin names |
| 75 |
my @plugs = plugin_names(); |
| 76 |
|
| 77 |
# Run all the plugins |
| 78 |
my $time = plugin_times(@plugs); |
| 79 |
|
| 80 |
write_plugin_times($cache_tmp, $cache, $time); |
| 81 |
} |
| 82 |
when ("config") {
|
| 83 |
print <<END; |
| 84 |
graph_title Munin plugin processing time |
| 85 |
graph_scale yes |
| 86 |
graph_vlabel seconds |
| 87 |
graph_category munin |
| 88 |
graph_info Shows the processing time of munin plugins in seconds |
| 89 |
END |
| 90 |
for my $plugin (@plugins) {
|
| 91 |
my ($time, $name) = @$plugin; |
| 92 |
my $fieldname = clean_fieldname($name); |
| 93 |
print <<END; |
| 94 |
$fieldname.label $name |
| 95 |
$fieldname.info The processing time of $name |
| 96 |
$fieldname.draw AREASTACK |
| 97 |
END |
| 98 |
} |
| 99 |
} |
| 100 |
default {
|
| 101 |
for my $plugin (@plugins) {
|
| 102 |
my ($time, $name) = @$plugin; |
| 103 |
my $fieldname = clean_fieldname($name); |
| 104 |
print <<END; |
| 105 |
$fieldname.value $time |
| 106 |
END |
| 107 |
} |
| 108 |
} |
| 109 |
} |
| 110 |
|
| 111 |
sub slurp {
|
| 112 |
do {
|
| 113 |
local (@ARGV, $/) = shift; |
| 114 |
scalar <>; |
| 115 |
}; |
| 116 |
} |
| 117 |
|
| 118 |
sub parse_plugin_time |
| 119 |
{
|
| 120 |
my ($file) = @_; |
| 121 |
|
| 122 |
my $cont = slurp($file); |
| 123 |
|
| 124 |
my @plugins; |
| 125 |
while ($cont =~ /^ (?<time>[\d.]+) \s+ (?<plugin>.*) $/mgx) {
|
| 126 |
push @plugins => [ $+{time} => $+{plugin} ];
|
| 127 |
} |
| 128 |
|
| 129 |
# Sort by size |
| 130 |
@plugins = sort { $b->[0] <=> $a->[0] } @plugins;
|
| 131 |
|
| 132 |
@plugins; |
| 133 |
} |
| 134 |
|
| 135 |
sub plugin_names {
|
| 136 |
map { basename $_ } grep { -x } glob "/etc/munin/plugins/*";
|
| 137 |
} |
| 138 |
|
| 139 |
sub plugin_times {
|
| 140 |
my (@p) = @_; |
| 141 |
my %time; |
| 142 |
|
| 143 |
my $dir = tempdir("munin-stats-plugins-XXXX", CLEANUP => 1, TMPDIR => 1);
|
| 144 |
|
| 145 |
for my $plugin (@p) {
|
| 146 |
my ($fh, $file) = tempfile(DIR => $dir); |
| 147 |
my $t0 = [gettimeofday]; |
| 148 |
if (system qq[MUNIN_STATS_PLUGINS_RELOAD=0 munin-run "$plugin" >"$file" 2>&1]) {
|
| 149 |
my $cont = slurp($file); |
| 150 |
die "munin-run: Failed to run plugin $plugin: $?, output: $cont"; |
| 151 |
} |
| 152 |
my $t1 = [gettimeofday]; |
| 153 |
|
| 154 |
my $elapsed = tv_interval($t0, $t1); |
| 155 |
$time{$plugin} = sprintf "%0.2f", $elapsed;
|
| 156 |
} |
| 157 |
|
| 158 |
return \%time; |
| 159 |
} |
| 160 |
|
| 161 |
sub write_plugin_times {
|
| 162 |
my ($tmp, $real, $time) = @_; |
| 163 |
|
| 164 |
# Write out the runtimes to a tempfile |
| 165 |
open my $fh, ">", $cache_tmp; |
| 166 |
while (my ($p, $t) = each %$time) {
|
| 167 |
say $fh "$t $p"; |
| 168 |
} |
| 169 |
close $fh; |
| 170 |
|
| 171 |
# Rename the temp to the real thing. If we wrote it to begin |
| 172 |
# with we might have a race condition. |
| 173 |
rename $cache_tmp, $cache; |
| 174 |
} |
