From a28b2691b3a438b83b80ae1b5e0961f716cc92c4 Mon Sep 17 00:00:00 2001 From: phl Date: Sun, 22 Jun 2014 14:43:02 +0200 Subject: [PATCH] adding first version of the plugin for the Jenkins CI Server --- plugins/jenkins/jenkins_ | 154 ++++++++++++++++++ plugins/jenkins/jenkins_nodes_ | 274 +++++++++++++++++++++++++++++++++ 2 files changed, 428 insertions(+) create mode 100644 plugins/jenkins/jenkins_ create mode 100644 plugins/jenkins/jenkins_nodes_ diff --git a/plugins/jenkins/jenkins_ b/plugins/jenkins/jenkins_ new file mode 100644 index 00000000..630d7a0d --- /dev/null +++ b/plugins/jenkins/jenkins_ @@ -0,0 +1,154 @@ +#!/usr/bin/env perl +# -*- perl -*- + +=head1 NAME + +jenkins_ - Plugin for displaying Jenkins Stats + +=head1 INTERPRETATION + +This plugin displays the following charts: + +1) The Status of each Build +2) Number of Jobs in the Build Queue +3) Number of Builds, currently running + +You can set the modes with naming the softlink: + +1) jenkins_results +2) jenkins_queue +3) jenkins_running + +=head1 CONFIGURATION + +This plugin is configurable environment variables. + +env.url Jenkins Host +env.port Jenkins Port +env.context Jenkins Context path +env.user User for the API Tokent +env.apiToken Jenkins API Token (see https://wiki.jenkins-ci.org/display/JENKINS/Authenticating+scripted+clients) + +Example: + +[jenkins_*] +env.url localhost +env.port 4040 +env.context /jenkins +env.user user +env.apiToken aaaa0f6e48b92cbbbbddecdb72dc1dad + + +=head1 AUTHOR + +Philipp Haussleiter (email) + +=head1 LICENSE + +GPLv2 + +=cut + +# MAIN +use warnings; +use strict; +use JSON; +use File::Basename; + +# VARS +my $url = ($ENV{'url'} || 'localhost'); +my $port = ($ENV{'port'} || '4040'); +my $user = ($ENV{'user'} || ''); +my $apiToken = ($ENV{'apiToken'} || ''); +my $context = ($ENV{'context'} || ''); +my $wgetBin = "/usr/bin/wget"; + +my $type = basename($0); +$type =~ s/jenkins_//; + +my %states = ('blue' =>'stable', 'blue_anime' =>'stable', 'yellow'=>'unstable', 'yellow_anime'=>'unstable', 'red'=>'failing', 'red_anime'=>'failing', 'disabled'=>'disabled' ); +my %counts = ('blue' => 0, 'yellow'=>0, 'red'=>0, 'disabled'=>0); + +if ( exists $ARGV[0] and $ARGV[0] eq "config" ) { + if( $type eq "results" ) { + print "graph_args --base 1000 -l 0\n"; + print "graph_title Jenkins Build Results\n"; + print "graph_vlabel Build Results\n"; + print "graph_category Jenkins\n"; + print "graph_info The Graph shows the Status of each Build\n"; + print "build_disabled.draw AREA\n"; + print "build_disabled.label disabled\n"; + print "build_disabled.type GAUGE\n"; + print "build_disabled.colour 8A8A8A\n"; + print "build_failing.draw STACK\n"; + print "build_failing.label failing\n"; + print "build_failing.type GAUGE\n"; + print "build_failing.colour E61217\n"; + print "build_unstable.draw STACK\n"; + print "build_unstable.label unstable\n"; + print "build_unstable.type GAUGE\n"; + print "build_unstable.colour F3E438\n"; + print "build_stable.draw STACK\n"; + print "build_stable.label stable\n"; + print "build_stable.type GAUGE\n"; + print "build_stable.colour 294D99\n"; + exit; + } + if( $type eq "queue" ) { + print "graph_args --base 1000 -l 0\n"; + print "graph_title Jenkins Queue Length\n"; + print "graph_vlabel Number of Jobs in Queue\n"; + print "graph_category Jenkins\n"; + print "graph_info The Graph shows the Number of Jobs in the Build Queue\n"; + print "build_count.label Jobs in Queue\n"; + print "build_count.type GAUGE\n"; + exit; + } + if( $type eq "running" ) { + print "graph_args --base 1000 -l 0\n"; + print "graph_title Jenkins Builds Running\n"; + print "graph_vlabel Builds currently running\n"; + print "graph_category Jenkins\n"; + print "graph_info The Graph shows the Number of Builds, currently running\n"; + print "build_running.label running Builds\n"; + print "build_running.type GAUGE\n"; + exit; + } +} else { + # CODE + my $auth = ( $user ne "" and $apiToken ne "" ? " --auth-no-challenge --user=$user --password=$apiToken" : "" ); + my $cmd = "$wgetBin $auth -qO- $url:$port$context"; + + if( $type eq "results" ) { + my $result = `$cmd/api/json`; + my $parsed = decode_json($result); + foreach my $cur(@{$parsed->{'jobs'}}) { + $counts{$cur->{'color'}} += 1; + } + + foreach my $status (keys %counts) { + print "build_$states{$status}.value $counts{$status}\n"; + } + exit; + } + + if( $type eq "running" ) { + my $count = 0; + my $result = `$cmd/api/json`; + my $parsed = decode_json($result); + foreach my $cur(@{$parsed->{'jobs'}}) { + if( $cur->{'color'} =~ /anime$/ ) { + $count += 1; + } + } + print "build_running.value ", $count, "\n"; + exit; + } + + if( $type eq "queue" ) { + my $result = `$cmd/queue/api/json`; + my $parsed = decode_json($result); + print "build_count.value ", scalar( @{$parsed->{'items'}} ), "\n"; + exit; + } +} diff --git a/plugins/jenkins/jenkins_nodes_ b/plugins/jenkins/jenkins_nodes_ new file mode 100644 index 00000000..e4bf80b5 --- /dev/null +++ b/plugins/jenkins/jenkins_nodes_ @@ -0,0 +1,274 @@ +#!/usr/bin/env perl +# -*- perl -*- + +# MAIN +use warnings; +use strict; +use JSON; +use File::Basename; +use Data::Dumper; + +# VARS +my $url = ($ENV{'url'} || 'localhost'); +my $port = ($ENV{'port'} || '4040'); +my $user = ($ENV{'user'} || ''); +my $apiToken = ($ENV{'apiToken'} || ''); +my $context = ($ENV{'context'} || ''); +my $wgetBin = "/usr/bin/env wget"; + +# mem_sum, mem, swap, ws, tmp, executors, arch +my $type = basename($0); +$type =~ s/jenkins_nodes_//; + +my $auth = ( $user ne "" and $apiToken ne "" ? " --auth-no-challenge --user=$user --password=$apiToken" : "" ); +my $cmd = "$wgetBin $auth -qO- $url:$port$context"; +my $monitor; + +if ( exists $ARGV[0] and $ARGV[0] eq "config" ) { + my $base_config = "graph_category Jenkins\n"; + + if( $type eq "mem_sum" ) { + print $base_config; + print "graph_args --base 1000 -l 0\n"; + print "graph_title Jenkins Memory Summary\n"; + print "graph_vlabel Memory Summary\n"; + print "graph_info The Graph shows the Jenkins Memory Summary\n"; + print "mem_sum_total.draw AREA\n"; + print "mem_sum_total.label availible\n"; + print "mem_sum_total.type GAUGE\n"; + print "mem_sum_used.label used\n"; + print "mem_sum_used.type GAUGE\n"; + } + + if( $type eq "mem" ) { + print $base_config; + print "graph_args --base 1000 -l 0\n"; + print "graph_title available Memory per Node\n"; + print "graph_vlabel available Memory per Node\n"; + print "graph_info The Graph shows the available Physical Memory per Node\n"; + my $lcount = 0; + my $node; + my $result = `$cmd/computer/api/json`; + my $parsed = decode_json($result); + foreach my $cur(@{$parsed->{'computer'}}) { + if( $cur->{'offline'} =~ /false$/ ) { + my $cat = $cur->{'displayName'}; + $cat =~ s/\./\_/g; + if( $lcount > 0 ){ + print $cat,"_mem.draw STACK\n"; + } else { + print $cat,"_mem.draw AREA\n"; + } + print $cat,"_mem.label $cur->{'displayName'}\n"; + print $cat,"_mem.type GAUGE\n"; + $lcount++; + } + } + } + + if( $type eq "ws" ) { + print $base_config; + print "graph_args --base 1000 -l 0\n"; + print "graph_title available Workspace per Node\n"; + print "graph_vlabel available Workspace\n"; + print "graph_info The Graph shows the available Workspace per Node\n"; + my $lcount = 0; + my $node; + my $result = `$cmd/computer/api/json`; + my $parsed = decode_json($result); + foreach my $cur(@{$parsed->{'computer'}}) { + if( $cur->{'offline'} =~ /false$/ ) { + my $cat = $cur->{'displayName'}; + $cat =~ s/\./\_/g; + if( $lcount > 0 ){ + print $cat,"_ws.draw STACK\n"; + } else { + print $cat,"_ws.draw AREA\n"; + } + print $cat,"_ws.label $cur->{'displayName'}\n"; + print $cat,"_ws.type GAUGE\n"; + $lcount++; + } + } + } + + if( $type eq "tmp" ) { + print $base_config; + print "graph_args --base 1000 -l 0\n"; + print "graph_title available TMP Space per Node\n"; + print "graph_vlabel available TMP Space\n"; + print "graph_info The Graph shows the available TMP Space per Node\n"; + my $lcount = 0; + my $node; + my $result = `$cmd/computer/api/json`; + my $parsed = decode_json($result); + foreach my $cur(@{$parsed->{'computer'}}) { + if( $cur->{'offline'} =~ /false$/ ) { + my $cat = $cur->{'displayName'}; + $cat =~ s/\./\_/g; + if( $lcount > 0 ){ + print $cat,"_tmp.draw STACK\n"; + } else { + print $cat,"_tmp.draw AREA\n"; + } + print $cat,"_tmp.label $cur->{'displayName'}\n"; + print $cat,"_tmp.type GAUGE\n"; + $lcount++; + } + } + } + + if( $type eq "arch" ) { + print $base_config; + print "graph_args --base 1000 -l 0\n"; + print "graph_title available Node Architectures\n"; + print "graph_vlabel available Node Architectures\n"; + print "graph_info The Graph shows the available Node Architectures\n"; + my $lcount = 0; + my $result = `$cmd/computer/api/json`; + my $parsed = decode_json($result); + my %archs = (); + my $cat; + foreach my $cur(@{$parsed->{'computer'}}) { + if( $cur->{'offline'} =~ /false$/ ) { + $cat = $cur->{'monitorData'}{'hudson.node_monitors.ArchitectureMonitor'}; + if (exists $archs{$cat} ) {} else { + $archs{$cat} = 0; + } + } + } + foreach my $cur (keys %archs) { + $cat = clean_name($cur); + if( $lcount > 0 ){ + print $cat,".draw STACK\n"; + } else { + print $cat,".draw AREA\n"; + } + print $cat,".label $cur\n"; + print $cat,".type GAUGE\n"; + $lcount++; + } + } + + if( $type eq "executors" ) { + print $base_config; + print "graph_args --base 1000 -l 0\n"; + print "graph_title Jenkins Executors\n"; + print "graph_vlabel Executors\n"; + print "graph_info The Graph shows the Jenkins Executors\n"; + print "executors_offline.label offline\n"; + print "executors_offline.type GAUGE\n"; + print "executors_offline.draw AREA\n"; + print "executors_offline.colour 8A8A8A\n"; + print "executors_busy.label busy\n"; + print "executors_busy.type GAUGE\n"; + print "executors_busy.draw STACK\n"; + print "executors_idle.label idle\n"; + print "executors_idle.type GAUGE\n"; + print "executors_idle.draw STACK\n"; + } + +} else { + # CODE + my $result = `$cmd/computer/api/json`; + my $parsed = decode_json($result); + + if( $type eq "mem_sum" ) { + my $avail_mem = 0; + my $total_mem = 0; + my $used_mem = 0; + foreach my $cur(@{$parsed->{'computer'}}) { + if( $cur->{'offline'} =~ /false$/ ) { + $monitor = $cur->{'monitorData'}{'hudson.node_monitors.SwapSpaceMonitor'}; + $avail_mem += $monitor->{'availablePhysicalMemory'}; + $total_mem += $monitor->{'totalPhysicalMemory'}; + } + } + $used_mem = $total_mem - $avail_mem; + print "mem_sum_total.value $total_mem\n"; + print "mem_sum_used.value $used_mem\n"; + } + + if( $type eq "mem" ) { + my $result = `$cmd/computer/api/json`; + my $parsed = decode_json($result); + foreach my $cur(@{$parsed->{'computer'}}) { + if( $cur->{'offline'} =~ /false$/ ) { + $monitor = $cur->{'monitorData'}{'hudson.node_monitors.SwapSpaceMonitor'}; + my $cat = $cur->{'displayName'}; + $cat =~ s/\./\_/g; + print $cat,"_mem.value ",$monitor->{'availablePhysicalMemory'},"\n"; + } + } + } + + if( $type eq "tmp" ) { + my $result = `$cmd/computer/api/json`; + my $parsed = decode_json($result); + foreach my $cur(@{$parsed->{'computer'}}) { + if( $cur->{'offline'} =~ /false$/ ) { + $monitor = $cur->{'monitorData'}{'hudson.node_monitors.TemporarySpaceMonitor'}; + my $cat = $cur->{'displayName'}; + $cat =~ s/\./\_/g; + print $cat,"_tmp.value ",$monitor->{'size'},"\n"; + } + } + } + + if( $type eq "ws" ) { + my $result = `$cmd/computer/api/json`; + my $parsed = decode_json($result); + foreach my $cur(@{$parsed->{'computer'}}) { + if( $cur->{'offline'} =~ /false$/ ) { + $monitor = $cur->{'monitorData'}{'hudson.node_monitors.DiskSpaceMonitor'}; + my $cat = $cur->{'displayName'}; + $cat =~ s/\./\_/g; + print $cat,"_ws.value ",$monitor->{'size'},"\n"; + } + } + } + + if( $type eq "arch" ) { + my $parsed = decode_json($result); + my %archs = (); + my $cat; + foreach my $cur(@{$parsed->{'computer'}}) { + if( $cur->{'offline'} =~ /false$/ ) { + $cat = $cur->{'monitorData'}{'hudson.node_monitors.ArchitectureMonitor'}; + if (exists $archs{$cat} ) { + $archs{$cat} += 1; + } else { + $archs{$cat} = 1; + } + } + } + foreach my $cur (keys %archs) { + $cat = clean_name($cur); + print $cat,".value ", $archs{$cur}, "\n"; + } + } + + if( $type eq "executors" ) { + my $busyExecutors = $parsed->{'busyExecutors'}; + my $totalExecutors = 0; + my $offlineExecutors = 0; + foreach my $cur(@{$parsed->{'computer'}}) { + $totalExecutors += $cur->{'numExecutors'}; + if( $cur->{'offline'} =~ /true$/ ) { + $offlineExecutors += $cur->{'numExecutors'}; + } + } + print "executors_idle.value ", ($totalExecutors - $busyExecutors - $offlineExecutors), "\n"; + print "executors_busy.value $busyExecutors\n"; + print "executors_offline.value $offlineExecutors\n"; + } +} + +sub clean_name { + my $name = $_[0]; + $name =~ s/\./\_/g; + $name =~ s/\(/\_/g; + $name =~ s/\)/\_/g; + $name =~ s/ //g; + return $name; +} \ No newline at end of file