Uh oh!
There was an error while loading. Please reload this page.
feat: compositeValues and exemplarCompliance flags for OM2 writer - #1991
Conversation
- compositeValues=true: write Histogram/GaugeHistogram/Summary as a
single composite-value line per the OM2 spec, e.g.
foo {count:17,sum:324789.3,bucket:[0.1:8,0.25:10,+Inf:17]} st@0.5
GaugeHistogram uses gcount/gsum per spec. Replaces separate _bucket,
_count, _sum, _created lines; created timestamp moves inline as st@.
Exemplar (latest) is appended inline when present.
- exemplarCompliance=true: skip exemplars without a timestamp, as the
OM2 spec mandates timestamps on all exemplars (MUST).
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>When compositeValues=false, OM2 histogram and summary output is identical to OM1 format. Delegate to om1Writer instead of duplicating writeClassicHistogramBuckets, writeNonCompositeSummaryDataPoint, and writeCountAndSum. Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Apply the same delegation pattern as histogram/summary: when exemplarCompliance=false (default), delegate writeScrapeTimestampAndExemplar and writeExemplar to om1Writer. When exemplarCompliance=true, apply the OM2 spec requirement (drop exemplars without timestamps) then delegate the actual writing to om1Writer.writeExemplar. Extracts writeExemplar from om1Writer.writeScrapeTimestampAndExemplar so OM2 can delegate exemplar formatting without duplicating it. Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
4ac4e32 to
f1eba6fCompareThere was a problem hiding this comment.
Pull request overview
This PR adds OM2 feature-flagged behavior to the OpenMetrics 2.0 text writer to support OM2 composite values for distributions and to enforce OM2 exemplar timestamp requirements when requested.
Changes:
- Add
compositeValuesmode to emit Histogram/GaugeHistogram/Summary as single-line OM2 CompositeValue entries (including inlinest@start timestamps and inline exemplars). - Add
exemplarCompliancemode to drop exemplars that lack timestamps (per OM2 MUST requirement). - Refactor OM1 writer helpers (histogram/summary/exemplar writing) to be reusable by the OM2 writer.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/OpenMetrics2TextFormatWriterTest.java | Adds tests covering composite-value output and exemplar-compliance behavior. |
| prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetricsTextFormatWriter.java | Exposes histogram/summary/exemplar helper methods at package scope and factors out writeExemplar(...). |
| prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetrics2TextFormatWriter.java | Implements composite-value rendering and exemplar compliance; delegates non-composite histogram/summary rendering to OM1 writer. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
🤖 I have created a release *beep* *boop* --- ## [1.6.0](v1.5.1...v1.6.0) (2026-04-25) ### Features * Add logic for handling content negotation flag with OM2 ([#1986](#1986)) ([0fa1ad7](0fa1ad7)) * Add OM2 native histogram text output ([#2042](#2042)) ([dec8e5b](dec8e5b)) * add OTel preserve_names for scrape-time suffix handling ([#1956](#1956)) ([f794288](f794288)) * compositeValues and exemplarCompliance flags for OM2 writer ([#1991](#1991)) ([ff48ae8](ff48ae8)) * move suffix handling to scrape time ([#1955](#1955)) ([5a5106c](5a5106c)) * OM2 writer outputs names as provided, no suffix appending ([#1957](#1957)) ([5ce2b57](5ce2b57)) ### Bug Fixes * **deps:** update dependency com.google.guava:guava to v33.6.0-jre ([#2021](#2021)) ([1382693](1382693)) * **deps:** update dependency commons-io:commons-io to v2.22.0 ([#2044](#2044)) ([9e05c1d](9e05c1d)) * **deps:** update dependency io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha to v2.27.0-alpha ([#2022](#2022)) ([30ac534](30ac534)) * **deps:** update dependency io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha to v2.27.0-alpha ([#2023](#2023)) ([2d51a32](2d51a32)) * **deps:** update dependency io.prometheus:prometheus-metrics-bom to v1.5.1 ([#2004](#2004)) ([650ce4b](650ce4b)) * **deps:** update dependency org.apache.tomcat.embed:tomcat-embed-core to v11.0.21 ([#2005](#2005)) ([7a36df7](7a36df7)) * **deps:** update dependency org.springframework.boot:spring-boot-starter-parent to v4.0.5 ([#2006](#2006)) ([0106c18](0106c18)) * **deps:** update dependency org.springframework.boot:spring-boot-starter-parent to v4.0.6 ([#2046](#2046)) ([40a9db8](40a9db8)) * **deps:** update jetty monorepo to v12.1.8 ([#2007](#2007)) ([acab5b2](acab5b2)) * **deps:** update protobuf ([#2024](#2024)) ([8e2214e](8e2214e)) * pass release tag as input to deploy workflow ([#1982](#1982)) ([165c921](165c921)) * pin grafana/otel-lgtm to 0.7.2 in OATs acceptance test ([#1992](#1992)) ([f17ad9a](f17ad9a)) * Relax metric name validation in Dropwizard5 ([#1985](#1985)) ([deb782f](deb782f)) * stabilize flaky timer and thread count tests ([#1973](#1973)) ([ce5867b](ce5867b)) * Tighten OM2 summary and start timestamp output ([#2041](#2041)) ([5699469](5699469)) * trigger Maven deploy from release-please via workflow_dispatch ([#1981](#1981)) ([698f956](698f956)) --- > [!IMPORTANT] > Close and reopen this PR to trigger CI checks. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Fixes#1989
Summary
compositeValues=true: Histogram, GaugeHistogram, and Summary arewritten as a single composite-value line per the OM2 spec:
_bucketlines)gcount/gsumper spec (note: the tracking issuesays "count/sum" but the spec is explicit about
gcount/gsum)st@; no separate_createdline_bucket,_count,_sumlines emittedcompositeValues=false(default), output is unchanged from beforeexemplarCompliance=true: Exemplars without a timestamp are silentlydropped. The OM2 spec mandates that all exemplars MUST have a timestamp.
The 128-char LabelSet limit from OM1 was never enforced in the writer, so
no change needed there.
Test plan
testCompositeHistogram— basic single-line histogram outputtestCompositeHistogramWithLabelsTimestampAndCreated— labels, scrapetimestamp, and
st@start timestamptestCompositeHistogramWithExemplar— exemplar appended inlinetestCompositeGaugeHistogram—gcount/gsumfieldstestCompositeSummary— basic single-line summary outputtestCompositeSummaryWithCreatedAndExemplar—st@+ exemplartestExemplarComplianceSkipsExemplarWithoutTimestamp— compliance modedrops exemplars without timestamps; default mode still emits them