Skip to content

PostgreSQL

Collect PostgreSQL server metrics and get curated dashboards and alerts for them with a single import.

PostgreSQL is scraped by an OpenTelemetry Collector running the postgresql receiver, which exports over OTLP to your LeanSignal agent gateway (one per cluster or environment) — never to a remote or third-party endpoint. The gateway keeps full fidelity locally and forwards only the demanded subset to your dataplane. Run one collector that can reach the database; it scrapes backends, commits/rollbacks, cache hits, tuple operations, sizes, and replication.

Metric names follow the standard OTLP → Prometheus normalization (dots become underscores, unit/_total suffixes are added), so postgresql.commits becomes postgresql_commits_total and postgresql.db_size becomes postgresql_db_size_bytes. The demands below are built against those names.

  • A LeanSignal agent gateway deployed and connected — one per cluster or environment. If you haven’t deployed it yet, follow Install the agent (source: LeanSignal/leansignal-agent). It should show as Connected under Agents in the LeanSignal app.
  • Network reachability to the gateway’s OTLP port4317 (gRPC) or 4318 (HTTP). See Agent configuration.
  • An OpenTelemetry Collector that can reach your PostgreSQL server, plus a monitoring database user — both configured in Setup.
  • Editor or admin role in the LeanSignal app (importing a demand creates dashboards and alert rules).

Run an OpenTelemetry Collector (for example otel/opentelemetry-collector-contrib) with the postgresql receiver, exporting OTLP to your LeanSignal agent gateway — not a SaaS endpoint.

Database user and grants (PostgreSQL 10+):

CREATE USER otel WITH PASSWORD 'REDACTED';
GRANT pg_monitor TO otel; -- read pg_stat_* / pg_statio_* views

The receiver opens one connection per database it scrapes; pg_monitor (a default role since PG10) grants read access to the statistics views it needs. Ensure pg_hba.conf allows the collector host to connect.

receivers:
postgresql:
endpoint: postgres:5432
username: otel
password: ${env:POSTGRES_PASSWORD}
databases: [mydb] # list DBs to scrape; empty = all non-template DBs
collection_interval: 30s
tls:
insecure: true # set false + ca_file to verify the server cert
# Extended demand also needs these opt-in metrics enabled:
# metrics:
# postgresql.deadlocks: { enabled: true }
# postgresql.temp_files: { enabled: true }
# postgresql.sequential_scans: { enabled: true }
processors:
resourcedetection:
detectors: [env, system]
system: { hostname_sources: [os] }
batch: {}
exporters:
otlp:
endpoint: leansignal-agent:4317 # per-cluster gateway (use :4318 for HTTP)
tls:
insecure: true # in-cluster plaintext; provide ca_file for TLS
service:
pipelines:
metrics:
receivers: [postgresql]
processors: [resourcedetection, batch]
exporters: [otlp]

A database server produces logs, and its traces come from the clients:

  • Server logs — point a collector filelog receiver at the PostgreSQL log directory (log_destination = stderr with logging_collector = on) and forward OTLP to the gateway; the receiver can run on the gateway itself if it can read the files. Already shipping them with a Promtail/Alloy-style agent? Repoint it at the gateway’s Loki push endpoint (:3500) instead.
  • Query traces — instrument the applications that call PostgreSQL (see the runtime integrations); their database client spans carry db.* attributes, so slow statements show up inside request traces.

PostgreSQL ships as a ready-made demand in three variants. You don’t copy any JSON — in the LeanSignal app go to Demands, press the ˅ arrow on the Add Demand button (the arrow opens the import menu), choose Import from catalog…, and pick the variant. Each variant below lists the slug that identifies its published bundle. See Integrations for the full import flow.

The variants are nested — Standard is a superset of Essential, Extended a superset of Standard. Pick whichever is closest to what you need and treat it as a starting point: after import everything is a normal, editable copy, so retune thresholds, add or drop panels, and adjust queries for your environment — your edits reshape the demand automatically. Start small and re-import a larger variant later if you outgrow it.

The golden signals. 1 dashboard · 4 panels · 3 alerts — backends, connection headroom, transactions, and cache efficiency at a glance.

Import this variant from the catalog. Its demand slug:

Demand slug
postgresql-otel-demand-essential

Dashboard — Active backends, Connection utilization, Transaction rate, and Cache hit ratio.

Alerts (3)

AlertSeverityFires when
PostgreSQL connection saturationcritical> 90% of max_connections for 5m
PostgreSQL low cache hit ratiowarninghit ratio < 95% for 15m
PostgreSQL high rollback ratiowarningrollbacks > 10% for 10m

Review the bundle JSON →

Each variant imports one PostgreSQL dashboard, its panels grouped into collapsible sections. Every dashboard carries an Instance filter (on the instance label), so one import covers the whole fleet — view every instance at once, or focus on one. Legends are sortable tables showing last/mean/max per series, so the outlier instance stands out. Dashboards are demand-driven: importing one tells your agents to forward exactly the timeseries its panels query, and nothing else. Panels are ordinary Perses panels — edit queries, add panels, or retune them after import, and your changes reshape the demand automatically.

Thresholds are conservative starting points — tune them to your workload.

Was this page helpful?