#! /usr/bin/env perl use strict; use warnings; use utf8; use Hydra::Helper::Nix; use Net::Statsd; use File::Slurper qw(read_text); use JSON::MaybeXS; use Getopt::Long qw(:config gnu_getopt); STDERR->autoflush(1); binmode STDERR, ":encoding(utf8)"; my $config = getHydraConfig(); my $statsdConfig = getStatsdConfig($config); $Net::Statsd::HOST = $statsdConfig->{'host'}; $Net::Statsd::PORT = $statsdConfig->{'port'}; sub gauge { my ($name, $val) = @_; die unless defined $val; Net::Statsd::gauge($name, $val); } sub sendQueueRunnerStats { my $s = `hydra-queue-runner --status`; die "cannot get queue runner stats\n" if $? != 0; my $json = decode_json($s) or die "cannot decode queue runner status"; gauge("hydra.queue.up", $json->{status} eq "up" ? 1 : 0); return if $json->{status} ne "up"; gauge("hydra.queue.steps.active", $json->{nrActiveSteps}); gauge("hydra.queue.steps.building", $json->{nrStepsBuilding}); gauge("hydra.queue.steps.copying_to", $json->{nrStepsCopyingTo}); gauge("hydra.queue.steps.copying_from", $json->{nrStepsCopyingFrom}); gauge("hydra.queue.steps.waiting", $json->{nrStepsWaiting}); gauge("hydra.queue.steps.runnable", $json->{nrRunnableSteps}); gauge("hydra.queue.steps.unfinished", $json->{nrUnfinishedSteps}); gauge("hydra.queue.steps.finished", $json->{nrStepsDone}); gauge("hydra.queue.steps.retries", $json->{nrRetries}); gauge("hydra.queue.steps.unsupported", $json->{nrUnsupportedSteps}); gauge("hydra.queue.steps.max_retries", $json->{maxNrRetries}); if ($json->{nrStepsDone}) { gauge("hydra.queue.steps.avg_total_time", $json->{avgStepTime}); gauge("hydra.queue.steps.avg_build_time", $json->{avgStepBuildTime}); } foreach my $machine (keys %{$json->{machineTypes}}) { my $machineType = $machine =~ s/:|,/_/r; gauge("hydra.queue.$machineType.runnable", $json->{machineTypes}->{$machine}->{runnable}); gauge("hydra.queue.$machineType.running", $json->{machineTypes}->{$machine}->{running}); } gauge("hydra.queue.builds.read", $json->{nrBuildsRead}); gauge("hydra.queue.builds.unfinished", $json->{nrQueuedBuilds}); gauge("hydra.queue.builds.finished", $json->{nrBuildsDone}); gauge("hydra.queue.checks", $json->{nrQueueWakeups}); gauge("hydra.queue.bytes_sent", $json->{bytesSent}); gauge("hydra.queue.bytes_received", $json->{bytesReceived}); gauge("hydra.queue.machines.total", scalar(grep { $_->{enabled} } (values %{$json->{machines}}))); gauge("hydra.queue.machines.in_use", scalar(grep { $_->{currentJobs} > 0 } (values %{$json->{machines}}))); } sub showHelp { print <<EOF; Usage: $0 [--once] Send stats to statsd. The --once flag can be used to send one round of stats and then exit. Example: \$ $0 --once EOF exit 0; } my $once = 0; GetOptions("once" => \$once, "help" => sub { showHelp() } ) or exit 1; while (1) { eval { sendQueueRunnerStats(); 1; } or do { warn "$@"; }; my $meminfo = read_text("/proc/meminfo") // ""; $meminfo =~ m/Dirty:\s*(\d+) kB/; if (defined $1) { my $dirty = $1 / (1024.0 * 1024.0); gauge("hydra.mem.dirty", $dirty); } if ($once) { last; } sleep(30); }