Add aurora_replica_status collector#1311
Conversation
Add the first Amazon Aurora PostgreSQL collector, with the supporting Aurora detection infrastructure on the instance struct. - instance.isAurora bool field, set by setup() via a one-shot SELECT aurora_version() (sync.Once, one probe per process) - aurora_replica_status collector exposes replica lag, replay latency, and pending read IOs from aurora_replica_status(). Gated on instance.isAurora — on non-Aurora servers returns ErrNoData. - Disabled by default; opt-in via --collector.aurora_replica_status. First in a series of per-collector PRs splitting prometheus-community#1308 as requested by @sysadmind. Signed-off-by: Pavel K <megativ3@gmail.com>
|
hi @SuperQ @sysadmind |
|
@SuperQ @sysadmind guys, sorry for pushing but any luck you have a chance to review this one? |
…ction-and-replica-status
ArthurSens
left a comment
There was a problem hiding this comment.
Disclaimer, I'm not a maintainer of postgres_exporter, I'm just trying to unload a bit of their review load :)
|
|
||
| * [CHANGE] ... | ||
| * [FEATURE] ... | ||
| * [FEATURE] Add `aurora_replica_status` collector for Amazon Aurora PostgreSQL, with Aurora auto-detection on the `instance` struct. |
There was a problem hiding this comment.
| * [FEATURE] Add `aurora_replica_status` collector for Amazon Aurora PostgreSQL, with Aurora auto-detection on the `instance` struct. | |
| * [FEATURE] Add `aurora_replica_status` collector for Amazon Aurora PostgreSQL. |
The second part of the phrase seems like implementation details; the postgres_exporter end-user doesn't care what an "instance struct" is
|
|
||
| var ( | ||
| auroraReplicaLagDesc = prometheus.NewDesc( | ||
| prometheus.BuildFQName(namespace, auroraReplicaSubsystem, "lag_milliseconds"), |
There was a problem hiding this comment.
prometheus recommends using base units for metric units. We have a few examples of other collectors doing this transformation, like pg_setting and pg_stat_statements
There was a problem hiding this comment.
agreed. This should be converted.
| []string{"server_id"}, nil, | ||
| ) | ||
| auroraReplayLatencyDesc = prometheus.NewDesc( | ||
| prometheus.BuildFQName(namespace, auroraReplicaSubsystem, "replay_latency_microseconds"), |
| db, err := sql.Open("postgres", dsn) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| db.Close() |
There was a problem hiding this comment.
asking without thinking too much... could the aurora detection be made here? If I understand it correctly, this runs only once and never again. So if we made the detection here, it would make the sync.Once shenanigans unecessary
There was a problem hiding this comment.
I'm probably missing context too since I'm not a maintainer of this exporter, but I'm wondering why version detection isn't made here either
There was a problem hiding this comment.
We also have the option to do detection where we do PostgreSQL instance version checks.
| type auroraProbe struct { | ||
| once sync.Once | ||
| isAurora bool | ||
| } | ||
|
|
||
| type instance struct { | ||
| dsn string | ||
| db *sql.DB | ||
| version semver.Version | ||
|
|
||
| // isAurora is set by setup() via the shared auroraProbe (one-shot | ||
| // SELECT aurora_version() per process). Aurora-specific collectors | ||
| // gate on this field; on non-Aurora servers they short-circuit to | ||
| // ErrNoData. | ||
| isAurora bool | ||
| auroraProbe *auroraProbe | ||
| } |
There was a problem hiding this comment.
why isAurora set in both instance and auroraProbe? Seems like instance has access to two fields that have the same meaning/value
There was a problem hiding this comment.
I don't think we need both. I think it's complicated and doesn't add much value.
| if i.auroraProbe != nil { | ||
| i.auroraProbe.once.Do(func() { | ||
| i.auroraProbe.isAurora = detectAurora(i.db) | ||
| }) | ||
| i.isAurora = i.auroraProbe.isAurora | ||
| } |
There was a problem hiding this comment.
I don't see this sync.Once protection against the query that detects version. I'm not sure if I'm missing something, but looks like an overcomplication....?
| // auroraReplicaStatusCollector exposes metrics from Aurora PostgreSQL's | ||
| // aurora_replica_status() function. Disabled by default because the function | ||
| // only exists on Aurora. | ||
| const auroraReplicaSubsystem = "aurora_replica" |
There was a problem hiding this comment.
I think it's unintuitive for the subsystem and the collector name below to be different. Someone runs --collector.aurora_replica_status but the metrics are aurora_replace_*. These should match. Based on the table name, they should both be aurora_replica_status.
| }() | ||
|
|
||
| // writer: 1 metric (pending_read_ios), reader: 3 metrics → 4 total | ||
| expected := 4 |
There was a problem hiding this comment.
This only validates that we had 4 metrics, not what they were. It's incomplete.
| non-Aurora server they silently emit no data. | ||
|
|
||
| * `[no-]collector.aurora_replica_status` | ||
| Replica lag, replay latency, pending read IOs from `aurora_replica_status()`. (default: disabled) |
There was a problem hiding this comment.
I think calling out each metric here makes it easy to miss when the collector changes.
Summary
First PR in a series splitting #1308 (Aurora support) into one-PR-per-collector as requested by @sysadmind.
This PR adds:
Aurora auto-detection infrastructure on
instancestruct. Mirrors the existingversionfield pattern (per @SuperQ feedback). On everysetup(), a one-shotSELECT aurora_version()runs viasync.Once— exactly one probe per process lifetime. The result is cached ininstance.isAuroraand read by Aurora-specific collectors.aurora_replica_statuscollector. Exposes the values from Aurora'saurora_replica_status()built-in: replica lag (per server), replay latency, and pending read IOs. Disabled by default (--collector.aurora_replica_status); on non-Aurora servers it short-circuits toErrNoDatacleanly.Test plan
go build ./...,go vet ./...,go test ./...clean.emits metrics; per-process
aurora_version()probe fires exactly once.ErrNoDatasilently; no error logs.
Follow-up PRs in the series will add the remaining 8 Aurora collectors on top of this infrastructure.