Skip to content

Instantly share code, notes, and snippets.

@kazeburo
Created January 8, 2016 08:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kazeburo/13e9a30f1f2bbe60c067 to your computer and use it in GitHub Desktop.
Save kazeburo/13e9a30f1f2bbe60c067 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
use strict;
use warnings;
use Storable;
use JSON;
use File::Spec;
sub cap_cmd {
my ($cmdref) = @_;
pipe my $logrh, my $logwh
or die "Died: failed to create pipe:$!\n";
my $pid = fork;
if ( ! defined $pid ) {
die "Died: fork failed: $!\n";
}
elsif ( $pid == 0 ) {
#child
close $logrh;
open STDOUT, '>&', $logwh
or die "Died: failed to redirect STDOUT\n";
close $logwh;
exec @$cmdref;
die "Died: exec failed: $!\n";
}
close $logwh;
my $result;
while(<$logrh>){
$result .= $_;
}
close $logrh;
while (wait == -1) {}
my $exit_code = $?;
$exit_code = $exit_code >> 8;
return ($result, $exit_code);
}
sub to_byte {
my $s = shift;
my $b = 0;
($s) = ($s =~ /^\s*(.+?)\s*$/); # trim
if ($s =~ /^[0-9]+$/) {
$b = $s;
} elsif ($s =~ /^([0-9]+)\s*([a-zA-Z]+)$/) {
$b = $1;
my $u = lc $2;
if ($u eq 'kb') {
$b = $b * 1024;
} elsif ($u eq 'mb') {
$b = $b * 1024 * 1024;
} elsif ($u eq 'gb') {
$b = $b * 1024 * 1024 * 1024;
} elsif ($u eq 'tb') {
$b = $b * 1024 * 1024 * 1024 * 1024;
} else {
warnf("Unknown unit: %s", $u);
}
} else {
warnf("Failed to convert into as byte: %s", $s);
}
return $b;
}
my $TIME = time;
sub metrix {
my ($key,$val) = @_;
print $key . "\t" . $val . "\t" . $TIME . "\n";
}
sub available_memory {
open my $fh, '<:utf8', '/proc/meminfo' or die "$!\n";
my %meminfo;
while (<$fh>) {
chomp;chomp;
my($key, $val) = split /[\s:]+/, $_, 2;
next unless $key;
$meminfo{$key} = to_byte($val);
}
close $fh;
my $available = $meminfo{MemFree} + $meminfo{Cached} + $meminfo{Inactive};
metrix("linux-lite.memory.avail", $available);
}
sub processors {
my $self = shift;
my $processors = 0;
open my $fh, '<', '/proc/cpuinfo' or die "$!\n";
while (<$fh>) {
$processors++ if m!^processor\s*:!
}
close $fh;
return $processors;
}
sub loadavg {
my $processors = processors();
open my $fh, '<', '/proc/loadavg' or die "$!\n";
my $loadavg = 0;
while (<$fh>) {
if (my @e = split /\s+/) {
$loadavg = $e[0];
last;
}
}
close $fh;
metrix("linux-lite.loadavg.per-cpu",$loadavg / $processors);
}
sub processes {
(my $result,my $exit_code) = cap_cmd(["ps","axwwo","pid,state"]);
my $all = 0;
my $running = 0;
for (split /\n/,$result) {
if ( m!^\s*(\d+)\s+(\w+)$! ) {
$all++;
$running++ if $2 eq "R";
}
}
metrix("lunux-lite.process.all", $all);
metrix("lunux-lite.process.running", $running);
}
sub cpu_usage {
open my $fh, '<', '/proc/stat' or die "$!\n";
my @keys = qw(cpu-user cpu-nice cpu-system cpu-idle cpu-iowait cpu-irq cpu-softirq cpu-steal cpu-guest cpu-guest-nice);
my %cur;
while (<$fh>) {
if (/^cpu\s+/) {
chomp;
my(undef, @t) = split /\s+/;
for my $k (@keys) {
my $v = shift @t;
$cur{$k} = int(defined $v ? $v : 0);
}
last;
}
}
close $fh;
my $prev_file = File::Spec->catfile(File::Spec->tmpdir,"mackerel-plugin-linux-lite-cpu-usage.dat");
if ( ! -f $prev_file ) {
store(\%cur,$prev_file);
return;
}
my $prev = retrieve($prev_file);
my %gap;
my $total = 0;
for my $k (@keys) {
$gap{$k} = (defined $cur{$k} ? $cur{$k} : 0) - (defined $prev->{$k} ? $prev->{$k} : 0);
$gap{$k} = 0 if $gap{$k} < 0;
$total += $gap{$k};
}
for my $k (@keys) {
metrix("linux-lite.cpu-usage.".$k, $gap{$k}/$total*100);
}
store(\%cur,$prev_file);
}
if ( $ENV{MACKEREL_AGENT_PLUGIN_META} ) {
my $meta = {
"graphs" => {
"linux-lite.memory" => {
"label" => 'Available memory',
"unit" => 'byte',
"metrics" => [
{
name => "avail",
lebal => "avaiable memory"
},
]
},
"linux-lite.loadavg" => {
"label" => 'Load Average per CPU',
"unit" => 'float',
"metrics" => [
{
name => "per-cpu",
lebal => "load average"
},
]
},
"linux-lite.process" => {
"label" => 'Number of Processes',
"unit" => 'integer',
"metrics" => [
{
name => "all",
lebal => "all"
},
{
name => "running",
lebal => "running"
},
]
},
"linux-lite.cpu-usage" => {
"label" => 'CPU Usage max 100%',
"unit" => 'float',
"metrics" => [
{
name => "cpu-user",
label => "user",
stacked => JSON::true,
},
{
name => "cpu-nice",
label => "nice",
stacked => JSON::true,
},
{
name => "cpu-system",
label => "system",
stacked => JSON::true,
},
{
name => "cpu-idle",
label => "idle",
stacked => JSON::true,
},
{
name => "cpu-iowait",
label => "iowait",
stacked => JSON::true,
},
{
name => "cpu-irq",
label => "irq",
stacked => JSON::true,
},
{
name => "cpu-softirq",
label => "softirq",
stacked => JSON::true,
},
{
name => "cpu-steal",
label => "steal",
stacked => JSON::true,
},
{
name => "cpu-guest",
label => "guest",
stacked => JSON::true,
},
{
name => "cpu-guest-nice",
label => "guest-nice",
stacked => JSON::true,
}
]
},
}
};
print encode_json($meta) . "\n";
}
else {
available_memory();
loadavg();
processes();
cpu_usage();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment