Development
Categories:
The project intentionally keeps most monitoring logic in YAML and a smaller execution engine in Go. Changes therefore fall into two paths: collector work and exporter-runtime work. Both paths should keep the merged configs, tests, documentation, and release metadata aligned.
Repository Layout
| Path | Purpose |
|---|---|
exporter/ |
CLI parsing, URL/config loading, planning, execution, metrics, health state, HTTP handlers, tests |
config/ |
58 ordered collector definition files for PostgreSQL 10-19+ and pgBouncer |
pg_exporter.yml |
Generated monolithic default config (make conf) |
legacy/config/ |
Collector definitions for PostgreSQL 9.1-9.6 |
legacy/pg_exporter.yml |
Generated legacy monolithic config (make conf9) |
docs/design/ |
Authoritative design notes such as snapshot histogram semantics |
monitor/ |
Grafana dashboards and database initialization helper |
package/ |
systemd environment/unit files and package scripts |
.goreleaser.yml |
Cross-platform archives, RPM/DEB packages, checksums, Docker images, and GitHub Release |
Toolchain
The current go.mod declares Go 1.26.5. For a normal development build:
git clone https://github.com/pgsty/pg_exporter.git
cd pg_exporter
go mod download
make build
./pg_exporter --version
The binary is built with CGO disabled for release artifacts. make build is suitable for local development; GoReleaser supplies version, branch, revision, and build-date metadata for official artifacts.
Test Before and After a Change
go test ./...
go test -race ./...
# Confirm all supported PostgreSQL and pgBouncer branches remain coverable,
# and that config structure, metric names, labels, and histograms are valid.
go test ./exporter/...
The test suite includes config coverage through PostgreSQL 19, PostgreSQL 9 legacy coverage, concurrency/reload behavior, HTTP route validation, label and metric-name validation, predicate caching, and snapshot histogram acceptance.
For a runtime change, also cross-build the supported release targets or use:
make goreleaser-build
Change or Add a Collector
- Choose the numeric group and a unique top-level branch name.
- Set
nameto the stable metric namespace when multiple version/role branches should emit one metric family. - Write SQL with an explicit result-column list.
- Add
min_version/max_version, role tags, fact tags, and predicates as narrowly as required. - Declare every returned column exactly once under
metrics. - Pick
ttl,timeout,fatal, andskipbased on operational cost and failure impact. - Run config tests, regenerate the merged file, and inspect the diff.
- Test the query as the monitoring role against every relevant server version and role.
- Update Bundled Collectors and release notes when the public metric surface changes.
Use config/0000-doc.yml as the executable schema reference.
Column rules
LABELbecomes a Prometheus label; avoid unbounded or sensitive values.GAUGEis for values that can move in either direction.COUNTERis for monotonically increasing source values (resets still occur on server restart/stat reset).HISTOGRAMbuilds a snapshot distribution from SQL rows. Its_bucket,_count, and_sumseries are gauges that may decrease; do not applyrate()orincrease().DISCARDvalidates/ignores a result column without exporting it.rename,default, andscalechange the emitted name/value semantics and need compatibility review.
le is reserved when a collector contains a histogram. Metric and label names are validated while loading the configuration so invalid names fail before scraping.
Regenerate Configs
make conf # config/*.yml -> pg_exporter.yml
make conf9 # legacy/config/*.yml -> legacy/pg_exporter.yml
git diff -- pg_exporter.yml legacy/pg_exporter.yml
Generated files are committed artifacts. CI checks that they exactly match the ordered source files; never edit only the monolithic output.
Exercise a Collector Locally
# Syntax/schema only; no target required
./pg_exporter --config=./config --dry-run
# Build a target-specific plan and exit
PG_EXPORTER_URL='postgres://monitor@localhost/postgres' \
./pg_exporter --config=./config --explain
# Run, inspect the plan and observe timing/errors
PG_EXPORTER_URL='postgres://monitor@localhost/postgres' \
./pg_exporter --config=./config --log.level=debug
curl localhost:9630/explain
curl localhost:9630/stat
Test zero-row results as well as populated results. Since v1.4.1, a missing configured LABEL column rejects the collector result atomically, including when the query happens to return no rows.
Release Pipeline
GoReleaser produces:
- Linux, macOS, and Windows archives;
- RPM and DEB packages;
- SHA256
checksums.txt; - amd64/arm64 Docker images and multi-architecture manifests;
- a GitHub Release for the tag.
The release version is injected into exporter.Version. Keep the fallback version, Makefile version, README badge, package metadata, and documentation parameter aligned before tagging. Validate the tag, Release object, checksums, package contents, container manifests, and install behavior as separate layers.
Documentation Workflow
The standalone documentation repository can import the authoritative Pigsty module pages and split the consolidated history with:
python3 bin/sync_pg_exporter_content.py \
--pigsty-io /path/to/pigsty.io \
--pigsty-cc /path/to/pigsty.cc \
--output ./content
The generated core pages are then supplemented by standalone-only guides such as this page, compatibility, security, collectors, and troubleshooting. Run the site warning-strict build and link checker before publishing.
Contributions are licensed under Apache 2.0. Open changes and issues at pgsty/pg_exporter.