diff --git a/plugins/system/cpu_by_process b/plugins/system/cpu_by_process new file mode 100755 index 00000000..f299a087 --- /dev/null +++ b/plugins/system/cpu_by_process @@ -0,0 +1,106 @@ +#!/usr/bin/perl +# +# Copyright 2012 Chris Wilson +# Copyright 2006 Holger Levsen +# +# This plugin monitors ALL processes on a system. No exceptions. It can +# produce very big graphs! But if you want to know where your CPU time +# is going without knowing what to monitor in advance, this can help; +# or in addition to one of the more specific CPU plugins to monitor +# just Apache or MySQL, for example. +# +# It's not obvious what the graph heights actually mean, even to me. +# Each counter is a DERIVE (difference since the last counter reading) +# of the CPU time usage (in seconds) accounted to each process, summed +# by the process name, so all Apache and all MySQL processes are grouped +# together. Processes with no CPU usage at all are ignored. Processes +# that die may not appear on the graph, and anyway their last chunk of +# CPU usage before they died is lost. You could modify this plugin to +# read SAR/psacct records if you care about that. +# +# 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; version 2 dated June, +# 1991. + +#scriptname=`basename $0` +#vsname=`echo $scriptname | perl -ne '/^vserver_proc_VM_(.*)/ and print $1'` + +#if [ "$1" = "suggest" ]; then +# ls -1 /etc/vservers +# exit 0 +#elif [ -z "$vsname" ]; then +# echo "Must be used with a vserver name; try '$0 suggest'" >&2 +# exit 2 +#fi + +use strict; +use warnings; + +my $cmd = "ps -eo time,comm h"; +open PS, "$cmd|" or die "Failed to run ps command: $cmd: $!"; + +# my $header_line = ; +my %total_cpu_by_process; + +while () +{ + my @fields = split; + my $cputime = $fields[0]; + my $process = $fields[1]; + + # remove any / and everything after it from the process name, + # e.g. kworker/0:2 -> kworker + $process =~ s|/.*||; + + # remove any . at the end of the name (why does this appear?) + # $process =~ s|\.$||; + + # change any symbol that's not allowed in a munin variable name to _ + $process =~ tr|a-zA-Z0-9|_|c; + + my @times = split /:/, $cputime; + $cputime = (($times[0] * 60) + $times[1]) * 60 + $times[2]; + $total_cpu_by_process{$process} += $cputime; +} + +foreach my $process (keys %total_cpu_by_process) +{ + # remove all processes with 0 cpu time + if (not $total_cpu_by_process{$process}) + { + delete $total_cpu_by_process{$process}; + } +} + +close(PS); + +if (@ARGV and $ARGV[1] == "config") +{ + print <&2 +# exit 2 +#fi + +use strict; +use warnings; + +my $cmd = "ps -eo maj_flt,comm h"; +open PS, "$cmd|" or die "Failed to run ps command: $cmd: $!"; + +# my $header_line = ; +my %total_by_process; + +while () +{ + my @fields = split; + my $value = $fields[0]; + my $process = $fields[1]; + + # remove any / and everything after it from the process name, + # e.g. kworker/0:2 -> kworker + $process =~ s|/.*||; + + # remove any . at the end of the name (why does this appear?) + # $process =~ s|\.$||; + + # change any symbol that's not allowed in a munin variable name to _ + $process =~ tr|a-zA-Z0-9|_|c; + + $total_by_process{$process} += $value; +} + +foreach my $process (keys %total_by_process) +{ + # remove all processes with 0 faults + if (not $total_by_process{$process}) + { + delete $total_by_process{$process}; + } +} + +close(PS); + +if (@ARGV and $ARGV[1] == "config") +{ + print <