diff --git a/doc/manual/src/configuration.md b/doc/manual/src/configuration.md index 170287da..d051c00a 100644 --- a/doc/manual/src/configuration.md +++ b/doc/manual/src/configuration.md @@ -79,6 +79,22 @@ By default, Hydra will send stats to statsd at `localhost:8125`. Point Hydra to ``` +hydra-notify's Prometheus service +--------------------------------- + +hydra-notify supports running a Prometheus webserver for metrics. The +exporter does not run unless a listen address and port are specified +in the hydra configuration file, as below: + +```conf + + + listen_address = 127.0.0.1 + port = 9199 + + +``` + Using LDAP as authentication backend (optional) ----------------------------------------------- diff --git a/doc/manual/src/monitoring/README.md b/doc/manual/src/monitoring/README.md index 65872352..67fb3961 100644 --- a/doc/manual/src/monitoring/README.md +++ b/doc/manual/src/monitoring/README.md @@ -13,3 +13,11 @@ $ curl --header "Accept: application/json" http://localhost:63333/queue-runner-s ... JSON payload ... ``` +## Notification Daemon + +The `hydra-notify` process can expose Prometheus metrics for plugin execution. See +[hydra-notify's Prometheus service](../configuration.md#hydra-notifys-prometheus-service) +for details on enabling and configuring the exporter. + +The notification exporter exposes metrics on a per-plugin, per-event-type basis: execution +durations, frequency, successes, and failures. diff --git a/src/lib/Hydra/Helper/Nix.pm b/src/lib/Hydra/Helper/Nix.pm index 7ab4ab60..ac0e54cf 100644 --- a/src/lib/Hydra/Helper/Nix.pm +++ b/src/lib/Hydra/Helper/Nix.pm @@ -70,6 +70,29 @@ sub getStatsdConfig { } } +sub getHydraNotifyPrometheusConfig { + my ($config) = @_; + my $cfg = $config->{hydra_notify}; + + if (!defined($cfg) || ref $cfg ne "HASH") { + return undef; + } + + my $cfg = $cfg->{prometheus}; + if (!defined($cfg) || ref $cfg ne "HASH") { + return undef; + } + + if (defined($cfg->{"listen_address"}) && defined($cfg->{"port"})) { + return { + "listen_address" => $cfg->{'listen_address'}, + "port" => $cfg->{'port'}, + }; + } + + return undef; +} + sub getBaseUrl { my ($config) = @_; diff --git a/src/script/hydra-notify b/src/script/hydra-notify index f64b5d72..9242d68f 100755 --- a/src/script/hydra-notify +++ b/src/script/hydra-notify @@ -14,30 +14,34 @@ use Parallel::ForkManager; use Prometheus::Tiny::Shared; use Time::HiRes qw( gettimeofday tv_interval ); -my $prom = Prometheus::Tiny::Shared->new; - -my $fork_manager = Parallel::ForkManager->new(1 ); -$fork_manager->start_child("metrics_exporter", sub { - my $server = HTTP::Server::PSGI->new( - host => "127.0.0.1", - port => 9091, - timeout => 5, - ); - - $server->run($prom->psgi); -}); - STDERR->autoflush(1); STDOUT->autoflush(1); binmode STDERR, ":encoding(utf8)"; +my $config = getHydraConfig(); + +my $prom = Prometheus::Tiny::Shared->new; + +my $promCfg = Hydra::Helper::Nix::getHydraNotifyPrometheusConfig($config); +if (defined($promCfg)) { + my $fork_manager = Parallel::ForkManager->new(1); + $fork_manager->start_child("metrics_exporter", sub { + my $server = HTTP::Server::PSGI->new( + host => $promCfg->{"listen_address"}, + port => $promCfg->{"port"}, + timeout => 1, + ); + + $server->run($prom->psgi); + }); +} + my $queued_only; GetOptions( "queued-only" => \$queued_only ) or exit 1; -my $config = getHydraConfig(); my $db = Hydra::Model::DB->new(); diff --git a/t/Config/hydra-notify.t b/t/Config/hydra-notify.t new file mode 100644 index 00000000..7fc8aa63 --- /dev/null +++ b/t/Config/hydra-notify.t @@ -0,0 +1,87 @@ +use strict; +use Setup; + +my %ctx = test_init(hydra_config => q| + + + listen_address = 127.0.0.1 + port = 9199 + + +|); + +require Hydra::Helper::Nix; +use Test2::V0; + +is(Hydra::Helper::Nix::getHydraNotifyPrometheusConfig(Hydra::Helper::Nix::getHydraConfig()), { + 'listen_address' => "127.0.0.1", + 'port' => 9199 +}, "Reading specific configuration from the hydra.conf works"); + + +is(Hydra::Helper::Nix::getHydraNotifyPrometheusConfig({ + "hydra_notify" => ":)" +}), undef, "Invalid (hydra_notify is a string) configuration options are undef"); + +is(Hydra::Helper::Nix::getHydraNotifyPrometheusConfig({ + "hydra_notify" => [] +}), undef, "Invalid (hydra_notify is a list) configuration options are undef"); + +is(Hydra::Helper::Nix::getHydraNotifyPrometheusConfig({ + "hydra_notify" => {} +}), undef, "Invalid (hydra_notify is an empty hash) configuration options are undef"); + +is(Hydra::Helper::Nix::getHydraNotifyPrometheusConfig({ + "hydra_notify" => { + "prometheus" => ":)" + } +}), undef, "Invalid (hydra_notify.prometheus is a string) configuration options are undef"); + +is(Hydra::Helper::Nix::getHydraNotifyPrometheusConfig({ + "hydra_notify" => { + "prometheus" => {} + } +}), undef, "Invalid (hydra_notify.prometheus is an empty hash) configuration options are undef"); + +is(Hydra::Helper::Nix::getHydraNotifyPrometheusConfig({ + "hydra_notify" => { + "prometheus" => { + "listen_address" => "0.0.0.0" + } + } +}), undef, "Invalid (hydra_notify.prometheus.port is missing) configuration options are undef"); + +is(Hydra::Helper::Nix::getHydraNotifyPrometheusConfig({ + "hydra_notify" => { + "prometheus" => { + "port" => 1234 + } + } +}), undef, "Invalid (hydra_notify.prometheus.listen_address is missing) configuration options are undef"); + +is(Hydra::Helper::Nix::getHydraNotifyPrometheusConfig({ + "hydra_notify" => { + "prometheus" => { + "listen_address" => "127.0.0.1", + "port" => 1234 + } + } +}), { + "listen_address" => "127.0.0.1", + "port" => 1234 +}, "Fully specified hydra_notify.prometheus config is valid and returned"); + +is(Hydra::Helper::Nix::getHydraNotifyPrometheusConfig({ + "hydra_notify" => { + "prometheus" => { + "listen_address" => "127.0.0.1", + "port" => 1234, + "extra_keys" => "meh", + } + } +}), { + "listen_address" => "127.0.0.1", + "port" => 1234 +}, "extra configuration in hydra_notify.prometheus is not returned"); + +done_testing;