summary refs log tree commit diff
diff options
context:
space:
mode:
authorMario Rodas <marsam@users.noreply.github.com>2023-10-07 06:37:06 -0500
committerGitHub <noreply@github.com>2023-10-07 06:37:06 -0500
commit5103716b448a737cdfaae50382c53834026ab670 (patch)
tree42335dcab95b7f2918f9247eec1a773a7d5cbc9a
parentf3051b014ed9608bbeb4a3197f58d80df517e514 (diff)
parent3b094812b1c00da15129b629fe4a2fc8159d687d (diff)
downloadnixpkgs-5103716b448a737cdfaae50382c53834026ab670.tar
nixpkgs-5103716b448a737cdfaae50382c53834026ab670.tar.gz
nixpkgs-5103716b448a737cdfaae50382c53834026ab670.tar.bz2
nixpkgs-5103716b448a737cdfaae50382c53834026ab670.tar.lz
nixpkgs-5103716b448a737cdfaae50382c53834026ab670.tar.xz
nixpkgs-5103716b448a737cdfaae50382c53834026ab670.tar.zst
nixpkgs-5103716b448a737cdfaae50382c53834026ab670.zip
Merge pull request #252800 from 1000101/prometheus-pgbouncer-exporter
prometheus-pgbouncer-exporter: init at 0.7.0
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters.nix44
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix145
-rw-r--r--nixos/tests/prometheus-exporters.nix30
-rw-r--r--pkgs/servers/monitoring/prometheus/pgbouncer-exporter.nix23
-rw-r--r--pkgs/top-level/all-packages.nix1
5 files changed, 237 insertions, 6 deletions
diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix
index 1d06893bf1d..b4236242905 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters.nix
@@ -58,6 +58,7 @@ let
     "nut"
     "openldap"
     "openvpn"
+    "pgbouncer"
     "php-fpm"
     "pihole"
     "postfix"
@@ -313,6 +314,25 @@ in
           '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;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix b/nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix
new file mode 100644
index 00000000000..9e55cadae52
--- /dev/null
+++ b/nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix
@@ -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";
+      };
+  };
+}
diff --git a/nixos/tests/prometheus-exporters.nix b/nixos/tests/prometheus-exporters.nix
index 7db7fdf13eb..8369d6a497a 100644
--- a/nixos/tests/prometheus-exporters.nix
+++ b/nixos/tests/prometheus-exporters.nix
@@ -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 = {
diff --git a/pkgs/servers/monitoring/prometheus/pgbouncer-exporter.nix b/pkgs/servers/monitoring/prometheus/pgbouncer-exporter.nix
new file mode 100644
index 00000000000..2eba38f65b1
--- /dev/null
+++ b/pkgs/servers/monitoring/prometheus/pgbouncer-exporter.nix
@@ -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;
+  };
+}
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 600517900c3..4106ade2e09 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -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 { };