Add OpenMetrics HTTP blackhole body#1895
Conversation
|
d2c5b17 to
87e2bc9
Compare
blt
left a comment
There was a problem hiding this comment.
This is looking good. @scottopell give me a ping when it's open for review and I'll have a look.
There was a problem hiding this comment.
Pull request overview
This PR adds a reusable lading_payload::openmetrics generator and wires it into the HTTP blackhole so it can serve a generated Prometheus/OpenMetrics-style text exposition body via a new openmetrics body_variant, avoiding embedding large static response strings in configs.
Changes:
- Added
lading_payload::openmetricsmodule that deterministically precomputes a scrape response body plus tests (unit + proptest). - Extended HTTP blackhole config with
body_variant.openmetricsand precomputes the body duringHttp::new. - Added an example config and documented the new variant in the changelog.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
lading/src/blackhole/http.rs |
Adds openmetrics body variant, deserialization support, and a config test for the new variant. |
lading_payload/src/openmetrics.rs |
Implements deterministic, precomputed text exposition generator with validation and tests. |
lading_payload/src/lib.rs |
Exposes the new openmetrics module and re-exports OpenMetrics. |
examples/lading-openmetrics.yaml |
Provides an example HTTP blackhole configuration serving generated scrape text. |
CHANGELOG.md |
Notes the new HTTP blackhole openmetrics body variant. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| //! `OpenMetrics` text exposition payload. | ||
| //! | ||
| //! This generator builds a deterministic Prometheus text exposition body for | ||
| //! scrape-oriented tests. The body is fully precomputed before serving so that | ||
| //! lading does no payload generation work on request hot paths. |
| fn validate_metric_prefix(prefix: &str) -> Result<(), String> { | ||
| if prefix.is_empty() { | ||
| return Err("metric_name_prefix cannot be empty".to_string()); | ||
| } | ||
| if !prefix | ||
| .chars() | ||
| .all(|ch| ch.is_ascii_alphanumeric() || ch == '_' || ch == ':') | ||
| { | ||
| return Err("metric_name_prefix contains invalid characters".to_string()); | ||
| } | ||
| Ok(()) | ||
| } |
faed763 to
3bfa033
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3bfa0338d2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "counter", | ||
| "Synthetic monotonic request counter.", | ||
| )?; | ||
| for index in 0..config.counters.count { |
There was a problem hiding this comment.
Keep generated counter series unique
With the default config this loop emits 240 counter samples, but the label tuple generated below repeats every 60 indices (for example, index 0 and 60 both produce the same service/region/method/status/route labels) with different values. OpenMetrics defines a metric by a unique LabelSet, and Prometheus/OpenMetrics scrapers reject duplicate samples in one scrape, so the default/example openmetrics response is invalid until these labels are made unique or the count is capped to the generated cardinality.
Useful? React with 👍 / 👎.
| write_build_info(config, &mut body)?; | ||
| sample_count += 1; |
There was a problem hiding this comment.
Append the required OpenMetrics EOF marker
When users serve this generated body as OpenMetrics, for example with Content-Type: application/openmetrics-text, generation stops after build_info and never appends # EOF. The OpenMetrics text format requires expositions to end with EOF, so strict OpenMetrics scrapers/parsers will reject these responses even though the variant is advertised as OpenMetrics; append the EOF line after the final metric.
Useful? React with 👍 / 👎.
| "requests_total", | ||
| "counter", |
There was a problem hiding this comment.
Use an unsuffixed counter family name
For OpenMetrics responses, declaring the family as requests_total makes the emitted samples invalid because a counter's Total sample name must be the family name plus the _total suffix; strict parsers will expect lading_openmetrics_requests_total_total for this TYPE line, not the lading_openmetrics_requests_total samples emitted below. Declare the family as requests (while keeping the sample name suffixed) or emit the required suffixed sample name when serving OpenMetrics text.
Useful? React with 👍 / 👎.
Summary
Adds a reusable lading_payload OpenMetrics module and wires it into the HTTP blackhole as an openmetrics body variant. This lets scrape-based tests serve generated Prometheus/OpenMetrics text bodies without embedding large static YAML strings.
Validation
Local checks run:
Full ci/validate could not run in the workspace because local system dependencies are missing: shellcheck, and all-features checks need FUSE libs that CI installs.
Notes
Example config added in examples/lading-openmetrics.yaml.