Merge pull request #252800 from 1000101/prometheus-pgbouncer-exporter

prometheus-pgbouncer-exporter: init at 0.7.0
This commit is contained in:
Mario Rodas 2023-10-07 06:37:06 -05:00 committed by GitHub
commit 5103716b44
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 237 additions and 6 deletions

View file

@ -58,6 +58,7 @@ let
"nut"
"openldap"
"openvpn"
"pgbouncer"
"php-fpm"
"pihole"
"postfix"
@ -312,6 +313,25 @@ in
Please specify either 'services.prometheus.exporters.nextcloud.passwordFile' or
'services.prometheus.exporters.nextcloud.tokenFile'
'';
} {
assertion = cfg.pgbouncer.enable -> (
(cfg.pgbouncer.connectionStringFile != null || cfg.pgbouncer.connectionString != "")
);
message = ''
PgBouncer exporter needs either connectionStringFile or connectionString configured"
'';
} {
assertion = cfg.pgbouncer.enable -> (
config.services.pgbouncer.ignoreStartupParameters != null && builtins.match ".*extra_float_digits.*" config.services.pgbouncer.ignoreStartupParameters != null
);
message = ''
Prometheus PgBouncer exporter requires including `extra_float_digits` in services.pgbouncer.ignoreStartupParameters
Example:
services.pgbouncer.ignoreStartupParameters = extra_float_digits;
See https://github.com/prometheus-community/pgbouncer_exporter#pgbouncer-configuration
'';
} {
assertion = cfg.sql.enable -> (
(cfg.sql.configFile == null) != (cfg.sql.configuration == null)
@ -350,12 +370,24 @@ in
`openFirewall' is set to `true'!
'';
})) ++ config.services.prometheus.exporters.assertions;
warnings = [(mkIf (config.services.prometheus.exporters.idrac.enable && config.services.prometheus.exporters.idrac.configurationPath != null) ''
Configuration file in `services.prometheus.exporters.idrac.configurationPath` may override
`services.prometheus.exporters.idrac.listenAddress` and/or `services.prometheus.exporters.idrac.port`.
Consider using `services.prometheus.exporters.idrac.configuration` instead.
''
)] ++ config.services.prometheus.exporters.warnings;
warnings = [
(mkIf (config.services.prometheus.exporters.idrac.enable && config.services.prometheus.exporters.idrac.configurationPath != null) ''
Configuration file in `services.prometheus.exporters.idrac.configurationPath` may override
`services.prometheus.exporters.idrac.listenAddress` and/or `services.prometheus.exporters.idrac.port`.
Consider using `services.prometheus.exporters.idrac.configuration` instead.
''
)
(mkIf
(cfg.pgbouncer.enable && cfg.pgbouncer.connectionString != "") ''
config.services.prometheus.exporters.pgbouncer.connectionString is insecure. Use connectionStringFile instead.
''
)
(mkIf
(cfg.pgbouncer.enable && config.services.pgbouncer.authType != "any") ''
Admin user (with password or passwordless) MUST exist in the services.pgbouncer.authFile if authType other than any is used.
''
)
] ++ config.services.prometheus.exporters.warnings;
}] ++ [(mkIf config.services.minio.enable {
services.prometheus.exporters.minio.minioAddress = mkDefault "http://localhost:9000";
services.prometheus.exporters.minio.minioAccessKey = mkDefault config.services.minio.accessKey;

View file

@ -0,0 +1,145 @@
{ config, lib, pkgs, options }:
with lib;
let
cfg = config.services.prometheus.exporters.pgbouncer;
in
{
port = 9127;
extraOpts = {
telemetryPath = mkOption {
type = types.str;
default = "/metrics";
description = lib.mdDoc ''
Path under which to expose metrics.
'';
};
connectionString = mkOption {
type = types.str;
default = "";
example = "postgres://admin:@localhost:6432/pgbouncer?sslmode=require";
description = lib.mdDoc ''
Connection string for accessing pgBouncer.
NOTE: You MUST keep pgbouncer as database name (special internal db)!!!
NOTE: Admin user (with password or passwordless) MUST exist
in the services.pgbouncer.authFile if authType other than any is used.
WARNING: this secret is stored in the world-readable Nix store!
Use {option}`connectionStringFile` instead.
'';
};
connectionStringFile = mkOption {
type = types.nullOr types.path;
default = null;
example = "/run/keys/pgBouncer-connection-string";
description = lib.mdDoc ''
File that contains pgBouncer connection string in format:
postgres://admin:@localhost:6432/pgbouncer?sslmode=require
NOTE: You MUST keep pgbouncer as database name (special internal db)!!!
NOTE: Admin user (with password or passwordless) MUST exist
in the services.pgbouncer.authFile if authType other than any is used.
{option}`connectionStringFile` takes precedence over {option}`connectionString`
'';
};
pidFile = mkOption {
type = types.nullOr types.str;
default = null;
description = lib.mdDoc ''
Path to PgBouncer pid file.
If provided, the standard process metrics get exported for the PgBouncer
process, prefixed with 'pgbouncer_process_...'. The pgbouncer_process exporter
needs to have read access to files owned by the PgBouncer process. Depends on
the availability of /proc.
https://prometheus.io/docs/instrumenting/writing_clientlibs/#process-metrics.
'';
};
webSystemdSocket = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Use systemd socket activation listeners instead of port listeners (Linux only).
'';
};
logLevel = mkOption {
type = types.enum ["debug" "info" "warn" "error" ];
default = "info";
description = lib.mdDoc ''
Only log messages with the given severity or above.
'';
};
logFormat = mkOption {
type = types.enum ["logfmt" "json"];
default = "logfmt";
description = lib.mdDoc ''
Output format of log messages. One of: [logfmt, json]
'';
};
webConfigFile = mkOption {
type = types.nullOr types.path;
default = null;
description = lib.mdDoc ''
Path to configuration file that can enable TLS or authentication.
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [ ];
description = lib.mdDoc ''
Extra commandline options when launching Prometheus.
'';
};
};
serviceOpts = {
after = [ "pgbouncer.service" ];
serviceConfig = let
startScript = pkgs.writeShellScriptBin "pgbouncer-start" "${concatStringsSep " " ([
"${pkgs.prometheus-pgbouncer-exporter}/bin/pgbouncer_exporter"
"--web.listen-address ${cfg.listenAddress}:${toString cfg.port}"
"--pgBouncer.connectionString ${if cfg.connectionStringFile != null then
"$(head -n1 ${cfg.connectionStringFile})" else "${escapeShellArg cfg.connectionString}"}"
]
++ optionals (cfg.telemetryPath != null) [
"--web.telemetry-path ${escapeShellArg cfg.telemetryPath}"
]
++ optionals (cfg.pidFile != null) [
"--pgBouncer.pid-file= ${escapeShellArg cfg.pidFile}"
]
++ optionals (cfg.logLevel != null) [
"--log.level ${escapeShellArg cfg.logLevel}"
]
++ optionals (cfg.logFormat != null) [
"--log.format ${escapeShellArg cfg.logFormat}"
]
++ optionals (cfg.webSystemdSocket != false) [
"--web.systemd-socket ${escapeShellArg cfg.webSystemdSocket}"
]
++ optionals (cfg.webConfigFile != null) [
"--web.config.file ${escapeShellArg cfg.webConfigFile}"
]
++ cfg.extraFlags)}";
in
{
ExecStart = "${startScript}/bin/pgbouncer-start";
};
};
}

View file

@ -966,6 +966,36 @@ let
'';
};
pgbouncer = {
exporterConfig = {
enable = true;
connectionString = "postgres://admin:@localhost:6432/pgbouncer?sslmode=disable";
};
metricProvider = {
services.postgresql.enable = true;
services.pgbouncer = {
# https://github.com/prometheus-community/pgbouncer_exporter#pgbouncer-configuration
ignoreStartupParameters = "extra_float_digits";
enable = true;
listenAddress = "*";
databases = { postgres = "host=/run/postgresql/ port=5432 auth_user=postgres dbname=postgres"; };
authType = "any";
maxClientConn = 99;
};
};
exporterTest = ''
wait_for_unit("postgresql.service")
wait_for_unit("pgbouncer.service")
wait_for_unit("prometheus-pgbouncer-exporter.service")
wait_for_open_port(9127)
succeed("curl -sSf http://localhost:9127/metrics | grep 'pgbouncer_up 1'")
succeed(
"curl -sSf http://localhost:9127/metrics | grep 'pgbouncer_config_max_client_connections 99'"
)
'';
};
php-fpm = {
nodeName = "php_fpm";
exporterConfig = {

View file

@ -0,0 +1,23 @@
{ lib, buildGoModule, fetchFromGitHub }:
buildGoModule rec {
pname = "pgbouncer-exporter";
version = "0.7.0";
src = fetchFromGitHub {
owner = "prometheus-community";
repo = "pgbouncer_exporter";
rev = "v${version}";
sha256 = "sha256-2N8FaGk6AU39j4q22B2Om5E7BeR7iw9drl3PTOBO2kg=";
};
vendorSha256 = "sha256-2aaUlOokqYkjMpcM12mU+O+N09/mDPlIrJ4Z1iXJAyk=";
meta = with lib; {
description = "Prometheus exporter for PgBouncer";
homepage = "https://github.com/prometheus-community/pgbouncer_exporter";
license = licenses.mit;
maintainers = with maintainers; [ _1000101 ];
platforms = platforms.linux;
};
}

View file

@ -27339,6 +27339,7 @@ with pkgs;
prometheus-nut-exporter = callPackage ../servers/monitoring/prometheus/nut-exporter.nix { };
prometheus-openldap-exporter = callPackage ../servers/monitoring/prometheus/openldap-exporter.nix { } ;
prometheus-openvpn-exporter = callPackage ../servers/monitoring/prometheus/openvpn-exporter.nix { };
prometheus-pgbouncer-exporter = callPackage ../servers/monitoring/prometheus/pgbouncer-exporter.nix { };
prometheus-php-fpm-exporter = callPackage ../servers/monitoring/prometheus/php-fpm-exporter.nix { };
prometheus-pihole-exporter = callPackage ../servers/monitoring/prometheus/pihole-exporter.nix { };
prometheus-postfix-exporter = callPackage ../servers/monitoring/prometheus/postfix-exporter.nix { };