Skip to content

pgBouncer support #319

@keithf4

Description

@keithf4

Is your feature request related to a problem? Please describe.

Working on converting our query set from our existing exporter and one of the things that even the previous one did not support was being able to connect to pgBouncer (https://www.pgbouncer.org/) to collect its statistics. I did run across another PostgreSQL exporter that supported this, but it's lack of TLS is why we couldn't use it: https://github.com/Vonng/pg_exporter. It didn't allow custom queries for bouncer, but maybe could use it as a reference to see how they did it?

Describe the solution you'd like
Be able to target a pgbouncer instance and connect to its special pgbouncer database to be able to run the SHOW commands. Don't need built in query support and happy to just be able to use our own custom collector.

I know the issue in the other exporter we use was that it always tries to run some queries that are not possible in pgbouncer's admin connection. There's a very limited set of commands available there, so would likely need some sort of flag or mode to detect it's making this connection. That special database is always called pgbouncer so could possible do what Vonng did and detect the database name? Here's the debug output when I try to use the example collector below:

Sep 15 15:16:16 cd-dc1-pgbouncer1 sql_exporter[15886]: ts=2023-09-15T19:16:16.598Z caller=klog.go:108 level=warn func=Warningf msg="Starting SQL exporter (version=0.11.1, branch=HEAD, revision=6293d4bc7ffe9531c06779c49d9003b8c92082aa) (go=go1.20.5, platform=linux/amd64, user=jenkins@build-rhel8.packaging.crunchydata.com, date=20230710-16:15:54, tags=netgo)"
Sep 15 15:16:16 cd-dc1-pgbouncer1 sql_exporter[15886]: ts=2023-09-15T19:16:16.598Z caller=klog.go:84 level=debug func=Infof msg="Loading configuration from /etc/sql_exporter/sql_exporter.yml"
Sep 15 15:16:16 cd-dc1-pgbouncer1 sql_exporter[15886]: ts=2023-09-15T19:16:16.598Z caller=klog.go:84 level=debug func=Infof msg="Loaded collector 'crunchy_pgbouncer' from /etc/sql_exporter/crunchy_pgbouncer_collector.yml"
Sep 15 15:16:16 cd-dc1-pgbouncer1 sql_exporter[15886]: ts=2023-09-15T19:16:16.598Z caller=klog.go:96 level=warn func=Warning msg="Listening on 0.0.0.0:9399"
Sep 15 15:16:16 cd-dc1-pgbouncer1 sql_exporter[15886]: ts=2023-09-15T19:16:16.599Z caller=tls_config.go:274 level=info msg="Listening on" address=[::]:9399
Sep 15 15:16:16 cd-dc1-pgbouncer1 sql_exporter[15886]: ts=2023-09-15T19:16:16.599Z caller=tls_config.go:277 level=info msg="TLS is disabled." http2=false address=[::]:9399
Sep 15 15:16:22 cd-dc1-pgbouncer1 sql_exporter[15886]: ts=2023-09-15T19:16:22.092Z caller=klog.go:84 level=debug func=Infof msg="[job=\"pgbouncer_targets\", target=\"pgbouncer\"] Database handle successfully opened with 'postgres' driver"
Sep 15 15:16:22 cd-dc1-pgbouncer1 pgbouncer[15731]: invalid command ';', use SHOW HELP;
Sep 15 15:16:22 cd-dc1-pgbouncer1 pgbouncer[15731]: C-0x5616bfca7260: pgbouncer/ccp_monitoring@127.0.0.1:54596 pooler error: invalid command ';', use SHOW HELP;
Sep 15 15:16:22 cd-dc1-pgbouncer1 pgbouncer[15731]: invalid command ';', use SHOW HELP;
Sep 15 15:16:22 cd-dc1-pgbouncer1 pgbouncer[15731]: C-0x5616bfca74c0: pgbouncer/ccp_monitoring@127.0.0.1:54606 pooler error: invalid command ';', use SHOW HELP;
Sep 15 15:16:22 cd-dc1-pgbouncer1 pgbouncer[15731]: invalid command ';', use SHOW HELP;
Sep 15 15:16:22 cd-dc1-pgbouncer1 pgbouncer[15731]: C-0x5616bfca7260: pgbouncer/ccp_monitoring@127.0.0.1:54612 pooler error: invalid command ';', use SHOW HELP;
Sep 15 15:16:22 cd-dc1-pgbouncer1 pgbouncer[15731]: invalid command ';', use SHOW HELP;
Sep 15 15:16:22 cd-dc1-pgbouncer1 pgbouncer[15731]: C-0x5616bfca74c0: pgbouncer/ccp_monitoring@127.0.0.1:54620 pooler error: invalid command ';', use SHOW HELP;
Sep 15 15:16:22 cd-dc1-pgbouncer1 sql_exporter[15886]: ts=2023-09-15T19:16:22.136Z caller=klog.go:84 level=debug func=Infof msg="Error gathering metrics: [from Gatherer #1] [job=\"pgbouncer_targets\", target=\"pgbouncer\"] driver: bad connection"

Our current work around is this extension that uses the dblink fdw to loop back a connection to pgbouncer from within the database.

https://github.com/CrunchyData/pgbouncer_fdw

It works, but it has limitations and would be much simpler to just be able to run an exporter directly on the pgbouncer instance.

Below is a sample config and collector file to just try and collect the SHOW DATABASE output. pgBouncer supports standard libpq connection strings and the SHOW commands just return a normal table format, so hopefully it works ok otherwise and may not be too much trouble?

Appreciate your time!

# The target(s) to monitor and the list of collectors to execute
#
jobs:
  - job_name: pgbouncer_targets
    collectors: [crunchy_pgbouncer]
    static_configs:
        - targets:
            pgbouncer: 'pg://ccp_monitoring@127.0.0.1:6432/pgbouncer?sslmode=disable'

# Collector definition files.
# Glob patterns are supported (see <https://pkg.go.dev/path/filepath#Match> for syntax).
collector_files:
  - "/etc/sql_exporter/crunchy_pgbouncer_collector.yml"
collector_name: crunchy_pgbouncer

metrics:
  - metric_name: ccp_pgbouncer_databases_pool_size
    type: gauge
    help: "Maximum number of server connections"
    values: [pool_size]
    key_labels:
      - name
      - host
      - port
      - database
      - force_user
      - pool_mode
    query_ref: ccp_pgbouncer_databases

  - metric_name: ccp_pgbouncer_databases_min_pool_size
    type: gauge
    help: "Minimum number of server connections"
    values: [min_pool_size]
    key_labels:
      - name
      - host
      - port
      - database
      - force_user
      - pool_mode
    query_ref: ccp_pgbouncer_databases

  - metric_name: ccp_pgbouncer_databases_reserve_pool
    type: gauge
    help: "Maximum number of additional connections for this database"
    values: [reserve_pool]
    key_labels:
      - name
      - host
      - port
      - database
      - force_user
      - pool_mode
    query_ref: ccp_pgbouncer_databases

  - metric_name: ccp_pgbouncer_databases_max_connections
    type: gauge
    help: "Maximum number of allowed connections for this database, as set by max_db_connections, either globally or per database"
    values: [max_connections]
    key_labels:
      - name
      - host
      - port
      - database
      - force_user
      - pool_mode
    query_ref: ccp_pgbouncer_databases


  - metric_name: ccp_pgbouncer_databases_current_connections
    type: gauge
    help: "Current number of connections for this database"
    values: [current_connections]
    key_labels:
      - name
      - host
      - port
      - database
      - force_user
      - pool_mode
    query_ref: ccp_pgbouncer_databases

  - metric_name: ccp_pgbouncer_databases_paused
    type: gauge
    help: "1 if this database is currently paused, else 0"
    values: [paused]
    key_labels:
      - name
      - host
      - port
      - database
      - force_user
      - pool_mode
    query_ref: ccp_pgbouncer_databases

  - metric_name: ccp_pgbouncer_databases_disabled
    type: gauge
    help: "1 if this database is currently disabled, else 0"
    values: [disabled]
    key_labels:
      - name
      - host
      - port
      - database
      - force_user
      - pool_mode
    query_ref: ccp_pgbouncer_databases


########## QUERIES ##########
queries:
  - query_name: ccp_pgbouncer_databases
    query: |
      SHOW DATABASES;

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions