Skip to content

feat(foundations): use foundations-metrics as the macro backend + expose a foundations-metrics facade - #240

Draft
ethanolchik wants to merge 44 commits into
cloudflare:mainfrom
ethanolchik:metrics/runtime
Draft

feat(foundations): use foundations-metrics as the macro backend + expose a foundations-metrics facade#240
ethanolchik wants to merge 44 commits into
cloudflare:mainfrom
ethanolchik:metrics/runtime

Conversation

@ethanolchik

@ethanolchik ethanolchik commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

PR Description: metrics/runtime

Overview

This PR completes the foundations-metrics crate and integrates it into the foundations telemetry facade. It adds histograms, exemplars, collection, encoding, validation, info metrics, and custom metrics support. The foundations crate gains a new foundations-metrics-backend feature flag (enabled by default) that swaps the legacy prometheus-client/prometools stack for the new implementation while keeping existing call sites source-compatible.

New Metric Types

  • Histograms: Added Histogram (classic buckets), TimeHistogram (seconds-scaled), and NativeHistogram (zero-threshold / bucket-factor configuration).
  • Exemplars: Added CounterWithExemplar, HistogramWithExemplars, and NativeHistogramWithExemplars for trace-context exemplars.
  • Info metrics: Added InfoMetric trait and report_info() for persistent build/process metadata.
  • Custom metrics: Exposed EncodeMetric and EncodeMetricValue so users can define their own metric types and register them via NamedMetric and Family.

Collection & Encoding

  • Added collect() and CollectionOptions to walk the global registry and emit MetricFamily protobuf messages.
  • Implemented encode_to_text (OpenMetrics) and encode_to_protobuf (length-delimited Prometheus protobuf).
  • Added Accept-header content negotiation in the telemetry server (see Behaviour Changes).
  • Fixed service-label deduplication: the service label is now decided from its first occurrence.
  • Media ranges with an unparseable q weight are now dropped rather than treated as q=1.0.

Behaviour Changes

/metrics previously ignored Accept entirely and always returned
application/openmetrics-text; version=1.0.0; charset=utf-8. That is still what every
scraper that sends no Accept, or that accepts text, receives — so the common path is
unchanged. Two cases now behave differently:

  • Unsatisfiable Accept returns 406 Not Acceptable instead of text. For example
    Accept: application/json,text/html, or a malformed q on the only supplied range.
    OpenMetrics text is always servable, so a 406 can only mean the client refused text;
    serving text to a client that said it cannot parse text hides a misconfiguration
    instead of surfacing it.
  • Protobuf is only offered when it can carry the whole exposition. ExtraProducer
    is a text-only extension point, so while any extra producer is registered the server
    withholds protobuf and serves text. This is all-or-nothing: one registered producer
    disables protobuf for the whole process. A protobuf-only client in that state gets a
    406 rather than a silently truncated exposition.

Protobuf availability is a runtime capability evaluated per scrape, not a setting; no
MetricsSettings field was added. Note that native histograms are not representable in
OpenMetrics text, so a process with both native histograms and an extra producer cannot
export the full set in either format.

Validation & UTF-8

  • Added validation pipeline for metric names, label names, and values before encoding.
  • Added UTF-8 support with automatic OpenMetrics quoting when needed.

Foundations Integration

  • Refactored foundations-macros to register metrics through a backend-agnostic shim, so #[metrics] and #[info_metric] work with either backend.
  • Deprecated add_extra_producer / ExtraProducer in favor of structured EncodeMetric registration.
  • Preserved the legacy backend behind the disabled foundations-metrics-backend feature.

Crate Readiness

  • Added description fields to foundations-metrics and foundations-metrics-registry so they are publishable on crates.io.
  • Added crate README.md with migration guide off the telemetry facade.
  • Added tests for format negotiation, info metrics, custom metrics, and UTF-8 fixture output.

Add owned fixed-bucket storage, direct protobuf encoding, and support for the legacy HistogramBuilder API (only classic histograms in this commit).
Choose to pre-sort histogram buckets over a sorted boolean variable.

Also satisfies cargo clippy & cargo fmt
… names

Legacy metric and label names must match Prometheus' name grammars. Names outside these grammars cause Prometheus to reject the scrape, and the grammars exclude non-ASCII characters.

Foundations now quotes label names and uses OpenMetrics' quoted metric-name syntax when required. This allows UTF-8 and other nonstandard names without affecting legacy compatibility.
Add registerable counter, classic histogram, and native histogram
types that retain exemplars alongside observations.

Support typed and legacy label sets, Family usage, OpenMetrics text,
and Prometheus protobuf encoding. Validate exemplars during collection
and report serialisation failures as non-fatal diagnostics.
@ethanolchik ethanolchik changed the title Metrics/runtime feat(foundations): use foundations-metrics as the macro backend + expose a foundations-metrics facade Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant