Files
rbizos ffe0b67b81 model/textparse: implement OM2 scrape format (#18606)
* adding OM2 scrape parsing

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* Renaming native histogram buckets

Also adding test case for omitted buckets / span

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* better test unknown metrics

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* Enforcing examplar timestamp and remove requirement on unit suffix

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* adding test exemplar above previous limit

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* supporting having both native and classic histograms if both provided

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* adding benchmarks for the diff between om1 and om2

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* reusing the label builder

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* using an iter for splitting composite field

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* fixing native histogram parsing

Before we would not check if buckets are floats or not, this ensures
that we don't miss some edgecases

Also adding test coverage on the different cases

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* reduce allocations in composite value parsing

- converts parseBuckets/parseQuantile to iterators
- reusing pending series
Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* fixing native histograms format

renamed correctly the gauge histogram
om encode  buckets as positive absolutes count in stead of delta

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* Update model/textparse/testdata/alltypes.bench.om2.txt

Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com>
Signed-off-by: rbizos <58781501+rbizos@users.noreply.github.com>

* Update model/textparse/testdata/alltypes.bench.om2.txt

Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com>
Signed-off-by: rbizos <58781501+rbizos@users.noreply.github.com>

* Update model/textparse/testdata/alltypes.bench.om2.txt

Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com>
Signed-off-by: rbizos <58781501+rbizos@users.noreply.github.com>

* Update model/textparse/testdata/alltypes.bench.om2.txt

Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com>
Signed-off-by: rbizos <58781501+rbizos@users.noreply.github.com>

* Update model/textparse/testdata/alltypes.bench.om2.txt

Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com>
Signed-off-by: rbizos <58781501+rbizos@users.noreply.github.com>

* Moving handwritten code from lex to parse

There was some leftover manual code on top of generated code

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* Fixing type and unit labels

- added tests covering each types
- fixing missing type and unit for composite metrics
- fixed unit not being cleaned between metrics families

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* Fixing bucket ordering for test data

added an explicit unit test to cover the unorder case

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* Reset Type and unit with any metadata

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* reusing parsingLVals for examplars

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* reused ParserOptions in stead of dedicated type

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* fail on missing fields for NH

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* fixing wrong link

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* reject duplicated st

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* Fixing conflicting Series return for composite metrics

Reused the logic from protobuf that suffers the same issue

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* Update model/textparse/openmetrics2parse_test.go

Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com>
Signed-off-by: rbizos <58781501+rbizos@users.noreply.github.com>

* Adding UTF-8 validation in labels and metadata

also fixed a small mistake in the tests where the input was updated but
not the test expected value

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* Making metrics name parsing stricter

- metric name must not be empty
- metric name without explicite __name__ must be first

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* simplify native histogram parsing using schema

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* Force ordering in buckets for histograms

also fixed some texts using om1 data

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* reseting properly when seeing a new metric

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* adding missing gsum/gcount metrics for classic gauge histograms

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* making composite parsing reject unknown and duplicate field

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* reject invalid schema

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* fix invalid metric name/label parsing

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* adding strict validation of zero_threshold

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* making stricter composite value validation

- enforcing +inf bucket for legacy histograms
- enforce the presence of requeired field
- force composite for types that require them

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* fixing timestamp ts order + summary quantile order

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* adding stricter validation of statesets

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* rejecting NaN counters

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* model/textparse: fix failing OM2 NaN counter test

The "counter sample value must not be NaN" case declared MetricFamily
"foo" via `# TYPE foo counter` but sampled `foo_total`. OpenMetrics 2.0
removes implicit suffix stripping and requires a Metric name to exactly
match its MetricFamily name, so `foo_total` is treated as a different
family. The parser therefore resets the type to Unknown, the counter
NaN guard is skipped, NaN is accepted, and the test reaches EOF instead
of the expected error.

Declare the family as `foo_total` so the name matches and the guard is
exercised. This makes `go test ./model/textparse/` pass again.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>

* model/textparse: make OM2 benchmark fixtures spec-compliant

Several counters in the OM2 benchmark fixtures declared their
MetricFamily via `# TYPE`/`# HELP`/`# UNIT` using a name without the
`_total` suffix (e.g. `cache_hits`, `http_requests`) while sampling the
`_total` name. OpenMetrics 2.0 removes implicit suffix stripping and
requires a Metric name to exactly match its MetricFamily name, so those
samples were treated as a different, metadata-less family and parsed as
untyped (Unknown) instead of counters.

Align the metadata names with the sampled `_total` names so the
fixtures are valid OM2 and the counters parse as counters. Histogram,
summary, gauge, info and stateset families already matched and are
unchanged; histograms.bench.om2.txt needed no changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>

* model/textparse: make OM2 unit-test snippets spec-compliant

Several inline test snippets used OpenMetrics 1.0 naming conventions
that are invalid under OpenMetrics 2.0, which removes implicit suffix
stripping and requires a Metric name to exactly match its MetricFamily
name:

- Counters declared as `# TYPE foo counter` / `# TYPE requests counter`
  while sampling `foo_total` / `requests_total`. The mismatch made the
  parser treat the samples as a different, untyped family. Align the
  descriptor name with the `_total` sample.
- The Info family `ii` did not end in `_info`; the spec mandates
  Info MetricFamily names MUST end in `_info`. Rename to `ii_info`.

Expected entries are updated accordingly. The affected error cases
still exercise the same errors (timestamp handling, missing exemplar
timestamp), which are independent of the metric type.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>

* model/textparse: test OM2 type resolution by metric/family name match

Add a table-driven test contrasting the two OM2 naming outcomes under
the exact-match rule (implicit suffix stripping is removed):

- A sample whose name only suffix-extends the declared family
  (`foo_total` under `# TYPE foo counter`) does not belong to that
  family and is parsed as untyped (no __type__ label).
- A sample whose name matches the descriptor exactly
  (`foo_total` under `# TYPE foo_total counter`) keeps the declared
  type, exposing __type__="counter".

The existing family-reset test only covered a wholly unrelated
undeclared name, not this OM1-style suffix case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>

* adding a feature flag to activate OM2 support

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>

* chore: pin OpenMetrics testdata fixtures to LF line endings

Windows checkout (core.autocrlf=true) rewrites the new OM1/OM2
benchmark testdata fixtures to CRLF. The OpenMetrics/OM2 parsers
treat "\r" as part of the token, which turns "counter" into
"counter\r" and fails type validation, breaking
TestOM1OM2BenchPairsEquivalent on the "Go tests on Windows" CI job.

Pin these fixtures to LF via .gitattributes so checkout no longer
mangles them.

Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>

---------

Signed-off-by: Raphael Bizos <r.bizos@criteo.com>
Signed-off-by: rbizos <58781501+rbizos@users.noreply.github.com>
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
Signed-off-by: r.bizos <r.bizos@criteo.com>
2026-08-27 10:10:19 +02:00

7 lines
321 B
Plaintext

web/api/v1/testdata/openapi_golden.yaml linguist-generated
# Ensure OpenMetrics test fixtures keep LF line endings on checkout.
# The parsers reject "\r" as part of tokens (OpenMetrics/OM2 text format is
# LF-only), so CRLF-mangled fixtures break parsing on Windows checkouts.
model/textparse/testdata/*.txt text eol=lf