Zuletzt geändert am 21. September 2014 um 09:15

Munin - cpu per core

Code

#!/usr/bin/perl -w
# -*- cperl -*-
use JSON;

=head1 NAME

cpu_per_core - plugin to monitor CPU usage for each CPU core

=head1 CONFIGURATION


=head1 NOTES

=head1 AUTHOR

Matija Grabnar

=head1 LICENSE

GPLv2

=head1 MAGIC MARKERS

 #%# family=system
 #%# capabilities=autoconf

=cut

use strict;
use Munin::Plugin;

my $cache = "/tmp/cpu_per_core.json";

my( $cpu,
    $user,
    $nice,
    $system,
    $idle,
    $iowait,
    $irq,
    $softirq,
    $steal,
    $guest,
    $guest_nice);
my @cpu;

sub print_values {
  my ($json,$str);
  if (open(CACHE,"<","$cache")) {
    my $str=<CACHE>;
    eval {
      $json = decode_json($str);
    };
  }
  print "multigraph cpu_per_core\n";
  open(INP,"<","/proc/stat") || die "Can not open /proc/stat/: $!\n";
  while (<INP>) {
    next unless /^cpu(\d+)\s+(\d+)(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?\s+/;
    $cpu     = $1;
    $user    = $2;
    $nice    = $3 || 0;
    $system  = $4 || 0;
    $idle    = $5 || 0;
    $iowait  = $6 || 0;
    $irq     = $7 || 0;
    $softirq = $8 || 0;
    $steal   = $9 || 0;
    $guest   = $10 || 0;
    $guest_nice = $11 || 0;
    push(@cpu,{
	       cpu     => $1,
	       user    => $2,
	       nice    => $3 || 0,
	       system  => $4 || 0,
	       idle    => $5 || 0,
	       iowait  => $6 || 0,
	       irq     => $7 || 0,
	       softirq => $8 || 0,
	       steal   => $9 || 0,
	       guest   => $10 || 0,
	       guest_nice => $11 || 0,
	      });
    if (defined($json->[$cpu])) {
      $user =    $cpu[$cpu]->{user}    - $json->[$cpu]->{user};
      $nice =    $cpu[$cpu]->{nice}    - $json->[$cpu]->{nice};
      $system =  $cpu[$cpu]->{system}  - $json->[$cpu]->{system};
      $idle =    $cpu[$cpu]->{idle}    - $json->[$cpu]->{idle};
      $iowait =  $cpu[$cpu]->{iowait}  - $json->[$cpu]->{iowait};
      $irq =     $cpu[$cpu]->{irq}     - $json->[$cpu]->{irq};
      $softirq = $cpu[$cpu]->{softirq} - $json->[$cpu]->{softirq};
      $steal =   $cpu[$cpu]->{steal}   - $json->[$cpu]->{steal};
      $guest =   $cpu[$cpu]->{guest}   - $json->[$cpu]->{guest};
      $guest_nice = $cpu[$cpu]->{guest_nice} - $json->[$cpu]->{guest_nice};
    } else {
      $user = $cpu[$cpu]->{user};
      $nice = $cpu[$cpu]->{nice};
      $system = $cpu[$cpu]->{system};
      $idle = $cpu[$cpu]->{idle};
      $iowait = $cpu[$cpu]->{iowait};
      $irq = $cpu[$cpu]->{irq};
      $softirq = $cpu[$cpu]->{softirq};
      $steal = $cpu[$cpu]->{steal};
      $guest = $cpu[$cpu]->{guest};
      $guest_nice = $cpu[$cpu]->{guest_nice};
    }
    my $usage = int(100-100*($idle/($user+$nice+$system+$idle+$iowait+
				    $irq+$softirq+$steal+$guest+$guest_nice)));
    print sprintf "cpu%d_usage.value %d\n",$cpu,$usage;
  }

  foreach my $cpu (sort {$a->{cpu}<=>$b->{cpu}} @cpu) {
    if (defined($json->[$cpu->{cpu}])) {
      $user =    $cpu->{user}    - $json->[$cpu->{cpu}]->{user};
      $nice =    $cpu->{nice}    - $json->[$cpu->{cpu}]->{nice};
      $system =  $cpu->{system}  - $json->[$cpu->{cpu}]->{system};
      $idle =    $cpu->{idle}    - $json->[$cpu->{cpu}]->{idle};
      $iowait =  $cpu->{iowait}  - $json->[$cpu->{cpu}]->{iowait};
      $irq =     $cpu->{irq}     - $json->[$cpu->{cpu}]->{irq};
      $softirq = $cpu->{softirq} - $json->[$cpu->{cpu}]->{softirq};
      $steal =   $cpu->{steal}   - $json->[$cpu->{cpu}]->{steal};
      $guest =   $cpu->{guest}   - $json->[$cpu->{cpu}]->{guest};
      $guest_nice = $cpu->{guest_nice} - $json->[$cpu->{cpu}]->{guest_nice};
    } else {
      $user       = $cpu->{user};
      $nice       = $cpu->{nice};
      $system     = $cpu->{system};
      $idle       = $cpu->{idle};
      $iowait     = $cpu->{iowait};
      $irq        = $cpu->{irq};
      $softirq    = $cpu->{softirq};
      $steal      = $cpu->{steal};
      $guest      = $cpu->{guest};
      $guest_nice = $cpu->{guest_nice};
    }
    my $total = $user + $nice + $system + $idle + $iowait + $irq +
      $softirq + $steal + $guest + $guest_nice;

    my $factor = 100/$total;

    print sprintf "multigraph cpu_per_core.cpu%d\n",$cpu->{cpu};
    print sprintf "cpu%d_system.value %3.6f\n",$cpu->{cpu},$system * $factor;
    print sprintf "cpu%d_user.value %3.6f\n",$cpu->{cpu},$user * $factor;
    print sprintf "cpu%d_nice.value %3.6f\n",$cpu->{cpu},$nice * $factor;
    print sprintf "cpu%d_idle.value %3.6f\n",$cpu->{cpu},$idle * $factor;
    print sprintf "cpu%d_iowait.value %3.6f\n",$cpu->{cpu},$iowait * $factor;
    print sprintf "cpu%d_irq.value %3.6f\n",$cpu->{cpu},$irq * $factor;
    print sprintf "cpu%d_softirq.value %3.6f\n",$cpu->{cpu},$softirq * $factor;
    print sprintf "cpu%d_steal.value %3.6f\n",$cpu->{cpu},$steal * $factor;
    print sprintf "cpu%d_guest.value %3.6f\n",$cpu->{cpu},$guest * $factor;
    print sprintf "cpu%d_guest_nice.value %3.6f\n",$cpu->{cpu},$guest_nice
       * $factor;
  }

  $str = encode_json(\@cpu);
  open(CACHE,">",$cache) ||
    die "Can not write to cache file $cache : $!\n";
  print CACHE $str;
  close(CACHE);
}

need_multigraph();

$ARGV[0]='' unless defined($ARGV[0]);

if ( $ARGV[0] eq "autoconf" ) {
  if (open(INP,"<","/proc/stat")) {
    print "yes\n";
    exit 0;
  } else {
    print "no\n";
    exit 0;
  }
}

if ( $ARGV[0] eq "config" ) {

  # The headers
  print "multigraph cpu_per_core\n";
  print "graph_info Monitoring CPU per core\n";
  print "graph_title CPU per Core usage\n";
  print "graph_vlabel %\n";
  print "graph_category system\n";
  print "graph_scale no\n";
  print "graph_args --upper-limit 100 --lower-limit 0 --rigid\n";
  print "graph_vlabel %\n";

    open(INP,"<","/proc/stat") || die "Can not open /proc/stat/: $!\n";
  while (<INP>) {
    next unless /^cpu(\d+)\s+(\d+)(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?(\s+\d+)?\s+/;
    $cpu     = $1;
    $user    = $2;
    $nice    = $3 || 0;
    $system  = $4 || 0;
    $idle    = $5 || 0;
    $iowait  = $6 || 0;
    $irq     = $7 || 0;
    $softirq = $8 || 0;
    $steal   = $9 || 0;
    $guest   = $10 || 0;
    $guest_nice = $11 || 0;
    push(@cpu,{
	       cpu     => $1,
	       user    => $2,
	       nice    => $3 || 0,
	       system  => $4 || 0,
	       idle    => $5 || 0,
	       iowait  => $6 || 0,
	       irq     => $7 || 0,
	       softirq => $8 || 0,
	       steal   => $9 || 0,
	       guest   => $10 || 0,
	       guest_nice => $11 || 0,
	      });
    print "cpu${cpu}_usage.label CPU core $cpu - % busy\n";
    print "cpu${cpu}_usage.type GAUGE\n";
    print "cpu${cpu}_usage.max 100\n";
    print "cpu${cpu}_usage.warning 0:85\n";
    print "cpu${cpu}_usage.critical 0:90\n";
  }

  foreach my $cpu (sort {$a->{cpu}<=>$b->{cpu}} @cpu) {
    print sprintf "multigraph cpu_per_core.cpu%d\n",$cpu->{cpu};
    print sprintf "graph_info CPU core %d\n",$cpu->{cpu};
    print sprintf "graph_title CPU core %d usage\n",$cpu->{cpu};
    print "graph_scale no\n";
    print "graph_args --upper-limit 100 --lower-limit 0 --rigid\n";
    print "graph_vlabel %\n";
    print "graph_category mandarina\n";

    print sprintf "cpu%d_system.label system\n",$cpu->{cpu};    
    print sprintf "cpu%d_system.draw AREA\n",$cpu->{cpu};
    print sprintf "cpu%d_system.type GAUGE\n",$cpu->{cpu};
    print sprintf "cpu%d_system.info CPU time spent in system state\n",$cpu->{cpu};

    print sprintf "cpu%d_user.label user\n",$cpu->{cpu};
    print sprintf "cpu%d_user.draw STACK\n",$cpu->{cpu};
    print sprintf "cpu%d_user.type GAUGE\n",$cpu->{cpu};
    print sprintf "cpu%d_user.info CPU time spent in user state\n",$cpu->{cpu};

    print sprintf "cpu%d_nice.label nice\n",$cpu->{cpu};
    print sprintf "cpu%d_nice.draw STACK\n",$cpu->{cpu};
    print sprintf "cpu%d_nice.type GAUGE\n",$cpu->{cpu};
    print sprintf "cpu%d_nice.info CPU time spent in nice state\n",$cpu->{cpu};

    print sprintf "cpu%d_idle.label idle\n",$cpu->{cpu};
    print sprintf "cpu%d_idle.draw STACK\n",$cpu->{cpu};
    print sprintf "cpu%d_idle.type GAUGE\n",$cpu->{cpu};
    print sprintf "cpu%d_idle.info CPU time spent in idle state\n",$cpu->{cpu};

    print sprintf "cpu%d_iowait.label iowait\n",$cpu->{cpu};
    print sprintf "cpu%d_iowait.draw STACK\n",$cpu->{cpu};
    print sprintf "cpu%d_iowait.type GAUGE\n",$cpu->{cpu};
    print sprintf "cpu%d_iowait.info CPU time spent in iowait state\n",$cpu->{cpu};

    print sprintf "cpu%d_irq.label irq\n",$cpu->{cpu};
    print sprintf "cpu%d_irq.draw STACK\n",$cpu->{cpu};
    print sprintf "cpu%d_irq.type GAUGE\n",$cpu->{cpu};
    print sprintf "cpu%d_irq.info CPU time spent in irq state\n",$cpu->{cpu};

    print sprintf "cpu%d_softirq.label softirq\n",$cpu->{cpu};
    print sprintf "cpu%d_softirq.draw STACK\n",$cpu->{cpu};
    print sprintf "cpu%d_softirq.type GAUGE\n",$cpu->{cpu};
    print sprintf "cpu%d_softirq.info CPU time spent in softirq state\n",$cpu->{cpu};

    print sprintf "cpu%d_steal.label steal\n",$cpu->{cpu};
    print sprintf "cpu%d_steal.draw STACK\n",$cpu->{cpu};
    print sprintf "cpu%d_steal.type GAUGE\n",$cpu->{cpu};
    print sprintf "cpu%d_steal.info CPU time spent in steal state\n",$cpu->{cpu};

    print sprintf "cpu%d_guest.label guest\n",$cpu->{cpu};
    print sprintf "cpu%d_guest.draw STACK\n",$cpu->{cpu};
    print sprintf "cpu%d_guest.type GAUGE\n",$cpu->{cpu};
    print sprintf "cpu%d_guest.info CPU time spent in guest state\n",$cpu->{cpu};

    print sprintf "cpu%d_guest_nice.label guest_nice\n",$cpu->{cpu};
    print sprintf "cpu%d_guest_nice.draw STACK\n",$cpu->{cpu};
    print sprintf "cpu%d_guest_nice.type GAUGE\n",$cpu->{cpu};
    print sprintf "cpu%d_guest_nice.info CPU time spent in guest_nice state\n",$cpu->{cpu};
  }

  exit 0;
}

print_values();

Quelle: http://www.matija.si/system-administration/2014/04/01/a-munin-plugin-to-monitor-each-cpu-core-separately/

Problembehebung

Falls beim Testen folgende Fehlermeldung erscheint, fehlt das Paket "libjson-perl:

/etc/munin/plugins # munin-run cpu_per_core 
Can't locate JSON.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at /etc/munin/plugins/cpu_per_core line 3.
BEGIN failed--compilation aborted at /etc/munin/plugins/cpu_per_core line 3.

Das Paket kann mit "apt-get install libjson-perl" installiert werden.