2
0
mirror of https://github.com/munin-monitoring/contrib.git synced 2018-11-08 00:59:34 +01:00
contrib-munin/plugins/other/cpufreq_
2011-12-18 15:10:11 +01:00

194 lines
4.8 KiB
Perl
Executable File

#!/usr/bin/perl -w
#
# munin plugin for monitoring cpu frequency
# Since multiple cpus on one graph doesn't really work, this plugin links to a cpu, i.e. cpufreq_cpu0
#
# written by BenV / JuNe
# email: benv-munin@junerules.com
#
# Version: 0.1
#
# Requires:
# Storable (saving state)
#
# Parameters:
#
# config required
#
# Configurable variables
# statedir location where the state file is saved. Defaults to /var/lib/munin/plugin-state.
# statefile name that's appended to statedir as filename for saving state. Defaults to "cpufreq_$cpu.state"
#
#%# family=auto
#%# capabilities=autoconf suggest
use strict;
if ($ARGV[0] and $ARGV[0] eq "autoconf" ) {
# Check required perl modules
unless (eval "require Storable")
{
print "No (Missing Storable)\n";
exit 1;
}
# Check for required proc/sys files
if (-d "/sys/devices/system/cpu/cpu0/cpufreq")
{
print "Yes\n";
exit 0;
}
print "No (Couldn't find /sys/devices/system/cpu/cpu0/cpufreq dir)";
exit 1;
}
if ($ARGV[0] and $ARGV[0] eq 'suggest' ) {
foreach my $d (</sys/devices/system/cpu/cpu[0-9]*/cpufreq/>)
{
$d =~ /(cpu[0-9]+)/i;
print "$1\n";
}
exit 0;
}
if (eval "require Storable")
{
Storable->import(qw /lock_store lock_nstore lock_retrieve/);
}
else
{
die "Sorry, you don't have Storable. (update your perl!)\n";
}
# Let's see what is requested.
my $target;
if ($0 =~ /_(cpu\d+)$/i)
{
$target = $1;
}
else
{
die "Error: we need to know what cpu you want, so link this plugin as cpufreq_cpu0 orso.";
}
my $statedir = $ENV{"statedir"} || "/var/lib/munin/plugin-state/";
my $statefile = $statedir.($ENV{"statefile"} || "/cpufreq_$target.state");
$statefile = glob($statefile); # Make it saner, remove tildes. Not foolproof though ;)
my $cpufreq;
eval { $cpufreq = lock_retrieve($statefile); };
unless(defined($cpufreq))
{
print STDERR "Couldn't read state file! (ignore this error on first run)\n";
$cpufreq = {};
}
my $cpufreq_now = {};
foreach my $d (</sys/devices/system/cpu/$target/cpufreq/stats/>)
{
unless(open(TIS, "<", "$d"."/time_in_state"))
{
die "Could not open ${d}/time_in_state: $!\n";
}
$d =~ /(cpu[0-9]+)/i;
my $cpu = $1;
while(<TIS>)
{
if (/^(\d+)\s(\d+)/)
{
$cpufreq_now->{$cpu}{$1} = $2;
$cpufreq_now->{total}{$cpu} = 0 unless(defined($cpufreq_now->{$cpu}));
$cpufreq_now->{total}{$cpu} += $2;
}
}
close(TIS);
}
# Let's figure out the percentages.
my %freq_p;
my $cpu = $target;
foreach my $freq (keys %{$cpufreq_now->{$cpu}})
{
my $new = $cpufreq_now->{$cpu}{$freq};
my $old = (defined($cpufreq->{$cpu}{$freq})?$cpufreq->{$cpu}{$freq}:0); # If no old data, we average everything.
my $total = $cpufreq_now->{total}{$cpu};
$total -= $cpufreq->{total}{$cpu} if (defined($cpufreq->{total}{$cpu}));
if (defined($total) && $total > 0)
{
my $p = ($new - $old) / $total;
$freq_p{$cpu}{$freq} = $p * 100.0;
$freq_p{avg}{$cpu} += $p * $freq; # Average speed, weighted average
}
else
{
$freq_p{$cpu}{$freq} = 0;
}
}
if ( $ARGV[0] and $ARGV[0] eq "config" )
{
print "graph_title Cpu frequency usage of $target\n";
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel CPU Frequency %\n";
print "graph_category System\n";
print "graph_info This graph shows information about the cpu frequency scaling of your CPU(s)\n";
my $count = 0;
my ($r,$g,$blue) = (0,255,0);
my $range = scalar(keys(%{$freq_p{$cpu}}));
my $step = (255+255) / ($range - 1);
# In order to let color work, let's go from green to yellow to red -- 00FF00 to FFFF00 to FF0000. 256 and 256 steps.
foreach my $freq (sort { $a <=> $b } keys %{$freq_p{$cpu}})
{
printf "freq_%d.label %s\n", $freq, "$freq KHz";
printf "freq_%d.info %s\n", $freq, "Time $cpu spent (percentage) running on $freq KHz";
printf "freq_%d.type GAUGE\n", $freq;
printf "freq_%d.draw %s\n", $freq, ($count++?"STACK":"AREA");
printf "freq_%d.colour %02X%02X%02X\n", $freq, $r,$g,$blue;
# Update color
my $s = $step;
if ($r < 255)
{
$r += $s;
if ($r > 255)
{
$s = $r - 255;
$r = 255;
$g -= $s;
}
}
else
{
$g -= $step;
$g = 0 if ($g < 0);
}
}
printf "cpuspeed_avg.label %s\n", "Average speed of cpu $cpu";
printf "cpuspeed_avg.info %s\n", "Average speed of cpu $cpu scaled to a percentage";
printf "cpuspeed_avg.GAUGE\n";
printf "cpuspeed_avg.LINE2\n";
printf "cpuspeed_avg.colour 0000FF\n";
exit 0;
}
# Print requested garbage.
foreach my $freq (sort { $a <=> $b } keys %{$freq_p{$cpu}})
{
printf "freq_%d.value %s\n", $freq, $freq_p{$cpu}{$freq};
}
# Average speed should be as a percentage as well. So divide it by the max freq.
my $max_freq = (sort { $a <=> $b } keys %{$freq_p{$cpu}})[-1];
if (defined($max_freq) && $max_freq > 0)
{
printf "cpuspeed_avg.value %d\n", $freq_p{avg}{$cpu} / $max_freq * 100;
}
# Save state!
eval { lock_nstore($cpufreq_now, $statefile) };
if ($@)
{
print STDERR "[$0] Error writing state file!\n";
}
exit 0;