aboutsummaryrefslogtreecommitdiff
path: root/monitor
diff options
context:
space:
mode:
authorRenato Golin <rengolin@gmail.com>2016-04-26 11:02:23 +0100
committerRenato Golin <rengolin@gmail.com>2016-04-26 11:02:23 +0100
commit94cc104f044261f74fbff3ff587855df1a05f64d (patch)
tree7c6664fdf7e7fab54fea926b1fc6196a09b6540f /monitor
downloadlinaro-scripts-94cc104f044261f74fbff3ff587855df1a05f64d.tar.gz
Initial Commit, moving from dev-private and removing private stuff
Diffstat (limited to 'monitor')
-rw-r--r--monitor/README.txt11
-rwxr-xr-xmonitor/bot-status244
-rw-r--r--monitor/fail.icobin0 -> 1406 bytes
-rw-r--r--monitor/linaro.json86
-rw-r--r--monitor/ok.icobin0 -> 2462 bytes
5 files changed, 341 insertions, 0 deletions
diff --git a/monitor/README.txt b/monitor/README.txt
new file mode 100644
index 0000000..c5cc6e8
--- /dev/null
+++ b/monitor/README.txt
@@ -0,0 +1,11 @@
+Monitoring Tools for LLVM Development
+=====================================
+
+These tools are not meant to be used for development or testing, but to be
+left running on a server or desktop as monitoring for your buildbots. They
+are also meant to be used in conjunction, not as a replacement, to Nagios
+and other hardware-level monitoring tools.
+
+Currently we only have one: bot-monitor, which I keep running on Linaro's
+public server (people.linaro.org) and keep it as a bookmark to quickly check
+the bot status. It's also a helpful bookmark for all bots we care.
diff --git a/monitor/bot-status b/monitor/bot-status
new file mode 100755
index 0000000..f2de0ea
--- /dev/null
+++ b/monitor/bot-status
@@ -0,0 +1,244 @@
+#!/usr/bin/env perl
+
+# This script greps the JSON files for the buildbots on
+# the LLVM official build master by name and prints an
+# HTML page with the links to the bots and the status.
+#
+# Multiple masters can be used, as well as multiple groups of bots
+# and multiple bots per group, all in a json file. See linaro.json
+# in this repository to have an idea how the config file is.
+#
+# Module JSON needs to be installed, either from cpan or packages.
+
+push @INC, `dirname $0`;
+
+use strict;
+use warnings;
+# Core modules
+use File::Temp qw/tempfile/;
+use File::Copy;
+# This is not part of core, but you really *need* it.
+use JSON;
+# This can be replaced by `wget/curl`
+use LWP;
+use LWP::UserAgent;
+# We don't have DateTime everywhere...
+my $date = `date`;
+# DEBUG
+my $DEBUG = 0;
+
+######################################################### Initialisation
+# Option checking
+my $syntax = "$0 config-file.json output-file.html\n";
+die $syntax unless (scalar @ARGV == 2);
+# Read config file
+my ($config, $error) = &read_file($ARGV[0]);
+die $error if ($error);
+($config, $error) = &decode($config);
+die $error if ($error);
+
+# Setup HTML output file
+my $output = $ARGV[1];
+my ($temp, $tempname) = tempfile();
+
+
+######################################################### Main Logic
+# Get status for all bots
+my %bot_cache;
+my $fail = 0;
+foreach my $server (@$config) {
+ next if (defined $server->{'ignore'} and $server->{'ignore'} eq "true");
+ my ($BASE_URL, $BUILDER_URL, $BUILD_URL) =
+ ($server->{'base_url'}, $server->{'builder_url'}, $server->{'build_url'});
+ &debug("Parsing server ".$server->{'name'}."...\n");
+ foreach my $builder (@{$server->{'builders'}}) {
+ &debug(" Parsing builder ".$builder->{'name'}."...\n");
+ foreach my $bot (@{$builder->{'bots'}}) {
+ &debug(" Parsing bot ".$bot->{'name'}."...\n");
+ next if defined $bot_cache{$bot->{'name'}};
+ my $status = &get_status($bot->{'name'}, $BASE_URL, $BUILDER_URL, $BUILD_URL);
+ if (!defined $bot->{'ignore'} or $bot->{'ignore'} ne "true") {
+ $fail = 1 if ($status->{'fail'});
+ } else {
+ &debug(" Ignoring...\n");
+ }
+ &debug($status->{'fail'} ? " FAIL\n" : " PASS\n");
+ $bot_cache{$bot->{'name'}} = $status;
+ }
+ }
+}
+
+# Dump all servers / bots
+foreach my $server (@$config) {
+ next if (defined $server->{'ignore'} and $server->{'ignore'} eq "true");
+ my ($BASE_URL, $BUILDER_URL, $BUILD_URL) =
+ ($server->{'base_url'}, $server->{'builder_url'}, $server->{'build_url'});
+ # Favicon
+ my $favicon = $fail ? "fail.ico" : "ok.ico";
+ print $temp "<link rel=\"shortcut icon\" href=\"$favicon\" type=\"image/x-icon\"/>\n";
+ # Header
+ print $temp "<table cellspacing=1 cellpadding=2>\n";
+ print $temp "<tr><td colspan=5>&nbsp;</td><tr>\n";
+ print $temp "<tr><th colspan=5>$server->{'name'} @ $date</td><tr>\n";
+ ## Main loop
+ foreach my $builder (@{$server->{'builders'}}) {
+ print $temp "<tr><td colspan=5>&nbsp;</td><tr>\n";
+ print $temp "<tr><th colspan=5>$builder->{'name'}</td><tr>\n";
+ print $temp "<tr><th>Buildbot</th><th>Status</th><th>Comments</th>".
+ "<th>Build #</th><th>Commits</th></tr>\n";
+ foreach my $bot (@{$builder->{'bots'}}) {
+ print $temp "<tr>\n";
+ my $status = $bot_cache{$bot->{'name'}};
+ my $url = "$BASE_URL/$BUILDER_URL/$bot->{'name'}";
+ print $temp " <td><a href='$url'>$bot->{'name'}</a></td>\n";
+ if ($status->{'fail'}) {
+ print $temp " <td><font color='red'>FAIL</font></td>\n".
+ " <td>$status->{'fail'}</td>\n";
+ } else {
+ print $temp " <td><font color='green'>PASS</font></td>\n".
+ " <td>&nbsp;</td>\n";
+ }
+ if (defined $status->{'build'} and
+ defined $status->{'from'} and
+ defined $status->{'to'}) {
+ print $temp " <td>$status->{'build'}</td>\n".
+ " <td>$status->{'from'}-$status->{'to'}</td>\n";
+ } else {
+ print $temp " <td colspan=2>&nbsp;</td>\n";
+ }
+ print $temp "</tr>\n";
+ }
+ }
+ # Footer
+ print $temp "</table>\n";
+}
+close $temp;
+
+# Move temp to main (atomic change)
+move($tempname, $output);
+exit;
+
+######################################################### Subs
+
+# GET STATUS: get the status of an individual bot
+# (botname, base url, builder url, build url) -> (status)
+sub get_status() {
+ my ($bot, $BASE_URL, $BUILDER_URL, $BUILD_URL) = @_;
+ my ($err, $contents, $json);
+ my %status;
+
+ # Get buildbot main JSON
+ ($contents, $err) = wget("$BASE_URL/json/$BUILDER_URL/$bot");
+ $status{'fail'} = $err;
+ return \%status if $err;
+ ($json, $err) = decode($contents);
+ $status{'fail'} = $err;
+ return \%status if $err;
+
+ # Find recent builds
+ my $cached_builds = scalar @{$json->{'cachedBuilds'}};
+ my $running_builds = scalar @{$json->{'currentBuilds'}};
+ my $last_build = $json->{'cachedBuilds'}[$cached_builds - $running_builds - 1];
+ return \%status if (not defined $last_build);
+
+ # Get most recent build
+ ($contents, $err) = wget("$BASE_URL/json/$BUILDER_URL/$bot/$BUILD_URL/$last_build");
+ $status{'fail'} = $err;
+ return \%status if $err;
+ ($json, $err) = decode($contents);
+ $status{'fail'} = $err;
+ return \%status if $err;
+
+ # Build number
+ $status{'build'} = $json->{'number'};
+
+ # Status of the last build
+ # "text" : [ "build", "successful" ],
+ # "text" : [ "failed", "svn-llvm" ],
+ my $failed = 0;
+ foreach (@{$json->{'text'}}) {
+ $status{'fail'} .= $_." " if ($failed);
+ $failed = 1 if (/failed|exception/);
+ }
+ $status{'fail'} =~ s/ $//;
+
+ # Commit range
+ # [
+ # 'revision',
+ # '238202',
+ # 'Build'
+ # ],
+ my $max = 0;
+ foreach (@{$json->{'properties'}}) {
+ if ($_->[0] eq 'revision') {
+ $max = $_->[1];
+ last;
+ }
+ }
+ # Min is in the changes' section
+ my $min = $max;
+ foreach (@{$json->{'sourceStamp'}->{'changes'}}) {
+ my $commit = $_->{'revision'};
+ $min = $commit if ($commit < $min);
+ }
+ $status{'from'} = $min;
+ $status{'to'} = $max;
+
+ return \%status;
+}
+
+# WGET: uses LWP to get an URL, returns contents (or error).
+# (url) -> (contents, error)
+sub wget() {
+ my ($url) = @_;
+ my ($contents, $error) = ("", "");
+
+ my $ua = LWP::UserAgent->new;
+ $ua->agent("LLVM BotMonitor/0.1");
+ my $req = HTTP::Request->new(GET => $url);
+ my $res = $ua->request($req);
+
+ if ($res->is_success) {
+ $contents = $res->content;
+ } else {
+ $error = $res->status_line;
+ }
+ return ($contents, $error);
+}
+
+# READ FILE: Reads a local file, returns contents
+# (filename) -> (contents)
+sub read_file() {
+ my ($file) = @_;
+ my ($contents, $error) = ("", "");
+ if (open FH, $file) {
+ while (<FH>) { $contents .= $_; }
+ close FH;
+ } else {
+ $error = "Can't open config file $file: $!";
+ }
+ return ($contents, $error);
+}
+
+# DECODE: Reads contents, returns JSON output (or error)
+# (contents) -> (JSON, error)
+sub decode() {
+ my ($contents) = @_;
+ my ($json, $error) = ("", "");
+ eval { $json = decode_json($contents); };
+ if ($@) {
+ if ($DEBUG) {
+ $error = $@;
+ } else {
+ $error = "JSON error";
+ }
+ }
+ return ($json, $error);
+}
+
+# DEBUG: Prints debug messages if debug enabled
+# (msg) -> ()
+sub debug () {
+ my ($msg) = @_;
+ print STDERR $msg if ($DEBUG);
+}
diff --git a/monitor/fail.ico b/monitor/fail.ico
new file mode 100644
index 0000000..263676d
--- /dev/null
+++ b/monitor/fail.ico
Binary files differ
diff --git a/monitor/linaro.json b/monitor/linaro.json
new file mode 100644
index 0000000..3cdd7ae
--- /dev/null
+++ b/monitor/linaro.json
@@ -0,0 +1,86 @@
+[
+ {
+ "name": "LLVM Lab",
+ "base_url": "http://lab.llvm.org:8011",
+ "builder_url": "builders",
+ "build_url": "builds",
+ "builders": [
+ {
+ "name": "Fast Bots",
+ "bots": [
+ { "name": "clang-cmake-armv7-a15" },
+ { "name": "clang-cmake-thumbv7-a15" },
+ { "name": "clang-cmake-aarch64-quick" },
+ { "name": "clang-cmake-aarch64-42vma" }
+ ]
+ },
+ {
+ "name": "Full Bots (LLVM, Clang, RT)",
+ "bots": [
+ { "name": "clang-cmake-armv7-a15-full" },
+ { "name": "clang-cmake-thumbv7-a15-full-sh" },
+ { "name": "clang-cmake-aarch64-42vma" },
+ { "name": "clang-cmake-aarch64-full" }
+ ]
+ },
+ {
+ "name": "Self Hosting Bots",
+ "bots": [
+ { "name": "clang-cmake-armv7-a15-selfhost" },
+ { "name": "clang-cmake-armv7-a15-selfhost-neon" },
+ { "name": "clang-cmake-thumbv7-a15-full-sh" },
+ { "name": "clang-cmake-aarch64-full" }
+ ]
+ },
+ {
+ "name": "Test-Suite Bots",
+ "bots": [
+ { "name": "clang-cmake-aarch64-quick" },
+ { "name": "clang-cmake-aarch64-full" },
+ { "name": "clang-native-arm-lnt" }
+ ]
+ },
+ {
+ "name": "Library Bots",
+ "bots": [
+ { "name": "libcxx-libcxxabi-arm-linux" }
+ ]
+ },
+ {
+ "name": "Cross-Compilation Bots",
+ "bots": [
+ { "name": "clang-x86_64-darwin13-cross-arm" }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "LLVM Silent Master",
+ "base_url": "http://lab.llvm.org:8014",
+ "builder_url": "builders",
+ "build_url": "builds",
+ "builders": [
+ {
+ "name": "Benchmarking Bots",
+ "bots": [
+ { "name": "clang-native-arm-lnt-perf", "ignore": "true" }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "Linaro Lab",
+ "base_url": "http://buildmaster.tcwglab.linaro.org",
+ "builder_url": "builders",
+ "build_url": "builds",
+ "builders": [
+ {
+ "name": "Prototypes",
+ "bots": [
+ { "name": "clang-cmake-armv7-prototype", "ignore": "true" },
+ { "name": "clang-cmake-aarch64-prototype", "ignore": "true" }
+ ]
+ }
+ ]
+ }
+]
diff --git a/monitor/ok.ico b/monitor/ok.ico
new file mode 100644
index 0000000..1acfa53
--- /dev/null
+++ b/monitor/ok.ico
Binary files differ