Skip to content

Monitor PostgreSQL with OpenTelemetry

Osuite monitors PostgreSQL through the OpenTelemetry Collector’s postgresql receiver, which queries the server’s statistics views and exports metrics over OTLP. The metrics share resource attributes with your application telemetry, so a slow query in APM can be traced to connection saturation or bloat on the database underneath it.

  • A reachable PostgreSQL server (9.6 or later).
  • A monitoring user that can read the statistics views.

Create a least-privilege user and grant it read access to the built-in monitoring role:

CREATE USER otel WITH PASSWORD 'a-strong-password';
GRANT pg_monitor TO otel;

Export the password to the environment the Collector runs in so it stays out of the config file:

Terminal window
export POSTGRESQL_PASSWORD='a-strong-password'
  1. Add the postgresql receiver, the otlp/osuite exporter, and a metrics pipeline that wires them together. Pick the tab that matches where your Collector runs — only the receiver endpoint changes.

    receivers:
    postgresql:
    endpoint: localhost:5432
    transport: tcp
    username: otel
    password: ${env:POSTGRESQL_PASSWORD}
    databases:
    - mydb
    collection_interval: 30s
    tls:
    insecure: true
    processors:
    batch:
    resourcedetection:
    exporters:
    otlp/osuite:
    endpoint: ingest.<region>.osuite.io:443
    headers:
    x-osuite-ingest-token: <your-ingest-token>
    service:
    pipelines:
    metrics:
    receivers: [postgresql]
    processors: [batch, resourcedetection]
    exporters: [otlp/osuite]
  2. Start the Collector. On Docker and Kubernetes, the Collector and PostgreSQL must share a network so the endpoint resolves.

What you should see

Metrics named postgresql.* appear in Dashboards → Explore metrics within a minute, tagged with the host or pod the Collector runs on.

MetricDescriptionUnit
postgresql.backendsActive client backends1
postgresql.commitsTransactions committed1
postgresql.rollbacksTransactions rolled back1
postgresql.blocks_readDisk blocks read1
postgresql.db_sizeDatabase disk usageBy
postgresql.database.countNumber of user databases{databases}
postgresql.connection.maxConfigured maximum client connections{connections}
postgresql.index.scansIndex scans on a table{scans}
postgresql.bgwriter.buffers.writesBuffers written by the background writer{buffers}
postgresql.bgwriter.checkpoint.countCheckpoints performed{checkpoints}

Enable per-table and per-index metrics, replication delay, and WAL age with the receiver’s optional metric toggles when you need them.

Once metrics arrive, build a PostgreSQL dashboard in the dashboard builder from the series above. Alerts in Osuite are PromQL-based — see Alerts. Useful starting conditions: connection headroom (postgresql.backends approaching postgresql.connection.max), a rising postgresql.rollbacks rate, and unbounded postgresql.db_size growth.

  • Authentication failed — confirm the otel user exists, the password matches POSTGRESQL_PASSWORD, and pg_hba.conf permits the Collector’s source address.
  • No postgresql.* metrics — confirm the databases list names databases that exist and that pg_monitor was granted.

No data in Osuite after a few minutes? Work through these checks.

  • Endpoint — confirm the exporter targets exactly ingest.<region>.osuite.io:443 for your region, over TLS.
  • Token — confirm the ingest header carries a valid <your-ingest-token> and has not been rotated.
  • Pipeline — confirm the signal you expect (traces, logs, or metrics) is wired into an active pipeline with the otlp/osuite exporter attached.
  • Export errors — check the application or Collector logs for OTLP export failures (auth, DNS, TLS, connection refused).
  • Network — confirm the host has outbound access to the ingest endpoint on port 443.
  • Timing — allow up to a minute for the first data to appear before assuming a failure.

Still stuck? Ask the Investigation Agent or contact support.