Skip to content

Conversation

@ywwg
Copy link
Contributor

@ywwg ywwg commented Jul 31, 2025

As per the specification: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/prometheus.md#configuration

This is part of a broader effort to unify the behavior of all the touch points between open telemetry metrics and prometheus: prometheus/prometheus#16542

Fixes #6668

@codecov
Copy link

codecov bot commented Jul 31, 2025

Codecov Report

❌ Patch coverage is 79.80769% with 21 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.0%. Comparing base (3342341) to head (943b82a).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
exporters/prometheus/exporter.go 72.0% 15 Missing and 6 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##            main   #7111     +/-   ##
=======================================
- Coverage   83.0%   83.0%   -0.1%     
=======================================
  Files        265     265             
  Lines      24788   24850     +62     
=======================================
+ Hits       20583   20628     +45     
- Misses      3830    3842     +12     
- Partials     375     380      +5     
Files with missing lines Coverage Δ
exporters/prometheus/config.go 100.0% <100.0%> (ø)
exporters/prometheus/exporter.go 84.1% <72.0%> (-2.1%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member

@ArthurSens ArthurSens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First round of review, couldn't find the time to properly test things myself 😬

@ArthurSens
Copy link
Member

Hmmm, something here isn't working with the WithNamespace config option. I tried running the go-contrib's prometheus example, but I've added a replace directive to the go.mod with your branch.

On line 34, I've changed the following:

exporter, err := prometheus.New(prometheus.WithNamespace("my-strange-namespace"), prometheus.WithTranslationStrategy(otlptranslator.UnderscoreEscapingWithSuffixes))

I've run the example and curl'ed the metrics endpoint with the following command:

curl -H 'Accept: application/openmetrics-text;version=1.0.0;escaping=allow-utf-8;q=0.5,application/openmetrics-text;version=0.0.1;q=0.4,text/plain;version=1.0.0;escaping=allow-utf8;q=0.3,text/plain;version=0.0.4;q=0.2,/;q=0.1' localhost:2223/metrics

And I've got UTF-8 characters (see dashes in the namespace):

# HELP "my-strange-namespace_foo_total" a simple counter
# TYPE "my-strange-namespace_foo_total" counter
{"my-strange-namespace_foo_total",A="B",C="D",otel_scope_my_custom_attribute="test",otel_scope_name="go.opentelemetry.io/contrib/examples/prometheus",otel_scope_schema_url="",otel_scope_version=""} 5

@ywwg
Copy link
Contributor Author

ywwg commented Aug 5, 2025

And I've got UTF-8 characters (see dashes in the namespace):

fixed and added test

@ywwg ywwg marked this pull request as ready for review August 5, 2025 20:44
@ywwg ywwg force-pushed the owilliams/config branch from 3ca500d to f002e88 Compare August 5, 2025 20:47
@ywwg
Copy link
Contributor Author

ywwg commented Aug 5, 2025

I do not understand the codespell failure

@ywwg
Copy link
Contributor Author

ywwg commented Aug 5, 2025

oh I figured it out, the error was in a previous CI step.

@ywwg ywwg changed the title start adding support for translation modes prometheus: Add support for setting Translation Strategy config option. Aug 5, 2025
@ArthurSens
Copy link
Member

Alright, tested a few different combinations of translation strategies, content type headers, and whether type/unit suffixes were deduplicated from names or not, and everything seems to work correctly :)

The only thing I'm concerned about now is how this affects the Collector configuration surface. I honestly have no idea how this works 😅

@dmathieu, @jade-guiton-dd, is it safe to deprecate the WithoutUnits option? Will this affect the collector config file format?

@ywwg
Copy link
Contributor Author

ywwg commented Aug 5, 2025

I did note that the prometheus otel endpoint also has a separate flag for counter suffixes, so maybe we do need that one.

@ywwg
Copy link
Contributor Author

ywwg commented Aug 6, 2025

I'm going to proceed assuming we want to keep the WithCounterSuffixes option as non-deprecated, but deprecate WithUnits

@ArthurSens
Copy link
Member

I did note that the prometheus otel endpoint also has a separate flag for counter suffixes, so maybe we do need that one.

Could you share where have you seen this? I don't see it in our configuration page 🤔

@ywwg
Copy link
Contributor Author

ywwg commented Aug 6, 2025

nevermind, I was mistaken -- it's only in the otel-go sdk

@jade-guiton-dd
Copy link

is it safe to deprecate the WithoutUnits option? Will this affect the collector config file format?

The Collector uses go-contrib/otelconf to implement the config schema defined in opentelemetry-configuration.

As long as otelconf keeps its stability promises (by choosing to ignore the deprecation, or by implementing without_units using translation_strategy under the hood), I don't think the Collector's config should be directly affected.

@ywwg
Copy link
Contributor Author

ywwg commented Aug 6, 2025

The Collector uses go-contrib/otelconf to implement the config schema defined in opentelemetry-configuration.

Ah, I haven't seen these before. Is that a user-facing set of structs? Since we are moving toward translation strategies across the board I'd prefer these objects to be in sync with the spec and SDK as well (by adding TranslationStrategy and deprecating WithoutTypeSuffix/WithoutUnits)

@ArthurSens
Copy link
Member

Ah, I haven't seen these before. Is that a user-facing set of structs? Since we are moving toward translation strategies across the board I'd prefer these objects to be in sync with the spec and SDK as well (by adding TranslationStrategy and deprecating WithoutTypeSuffix/WithoutUnits)

It is, this struct turns into the collector config file and will coordinate how the collector internal metrics are exposed

@ArthurSens
Copy link
Member

@pellared, do you happen to have some time to review this PR while David is on PTO? We depend on getting this in to upgrade otel-go and prometheus dependencies in the collector 😅

@pellared
Copy link
Member

@ArthurSens, made a quick review (I am low on time at the moment).

@ywwg
Copy link
Contributor Author

ywwg commented Aug 14, 2025

The problem I'm running in to now is that otel-go, uniquely, has two separate settings for suffixes, type and unit separately, whereas the other projects only have one. This would require a large set of translation strategies (8) to cover all of the permutations implied.

Although in the meetings we have said that the new option (WithTranslationStrategy) should override the old one, I think that's not actually the best way to do it. I think it is ok for a user to say:

"I want underscore escaping with suffixes, disable unit suffixes, disable counter suffixes." This is a bit like "I'd like a hamburger, hold the bun," but it's logically consistent. Although this request is the same as "I want underscore escaping without suffixes," if someone wants to write it this way, they can.

By allowing this, we can allow for "I want underscore escaping with suffixes, disable unit suffixes ONLY," something that the tests check for.

Since there is no way to generate an option that adds suffixes, we don't need to worry about inverse cases ("I want no suffixes, but add suffixes").

I have updated the code accordingly. But note @ArthurSens that this contradicts what we talked about in the spec meeting so we will have to be careful about how we document this.

I am still deprecating the "withoutXSuffixes" options -- people should not use them!

@ArthurSens
Copy link
Member

I have updated the code accordingly. But note @ArthurSens that this contradicts what we talked about in the spec meeting so we will have to be careful about how we document this.

In the spec meeting, we were talking about configuration files. This is a different case.

If something has its Prometheus configuration handled by YAML files, we have no idea what comes first and what comes second when we parse this file. So we can't make assumptions and just say that translation_strategy overrides the others.

We're building a functional builder pattern on this PR that you're working on, and the situation is the complete opposite. Ordering is easy to notice, and making overrides is the hard thing to implement :)

@ywwg
Copy link
Contributor Author

ywwg commented Aug 19, 2025

We're building a functional builder pattern on this PR that you're working on, and the situation is the complete opposite. Ordering is easy to notice, and making overrides is the hard thing to implement :)

Yes, but after working with the code, the situation now is that even in the functional builder, order does not matter. Let me know if the new behavior is still unclear -- it's not quite a matter of one option "overriding" the other.

@ywwg
Copy link
Contributor Author

ywwg commented Aug 22, 2025

status: Waiting for @pellared to come back from PTO for second approval

As per the specification: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/prometheus.md#configuration

This is part of a broader effort to unify the behavior of all the touch points between open telemetry metrics and prometheus: prometheus/prometheus#16542

Fixes open-telemetry#6668

Signed-off-by: Owen Williams <[email protected]>
@ywwg ywwg force-pushed the owilliams/config branch from c790805 to 6fa88d4 Compare August 26, 2025 19:00
@ywwg
Copy link
Contributor Author

ywwg commented Aug 26, 2025

squashed down

@pellared pellared changed the title prometheus: Add support for setting Translation Strategy config option. prometheus: Add support for setting Translation Strategy config option Aug 27, 2025
@ywwg
Copy link
Contributor Author

ywwg commented Aug 27, 2025

merge? all comments resolved, last fixes applied

@dashpole dashpole merged commit d0cab86 into open-telemetry:main Aug 27, 2025
39 of 40 checks passed
@ywwg
Copy link
Contributor Author

ywwg commented Aug 27, 2025

thank you all for your reviews!

@pellared
Copy link
Member

thank you all for your reviews!

Thank you for your contribution

@MrAlias MrAlias mentioned this pull request Aug 29, 2025
@MrAlias MrAlias added this to the v1.38.0 milestone Aug 29, 2025
MrAlias added a commit that referenced this pull request Aug 29, 2025
This release is the last to support [Go 1.23].
The next release will require at least [Go 1.24].

### Added

- Add native histogram exemplar support in
`go.opentelemetry.io/otel/exporters/prometheus`. (#6772)
- Add template attribute functions to the
`go.opentelmetry.io/otel/semconv/v1.34.0` package. (#6939)
  - `ContainerLabel`
  - `DBOperationParameter`
  - `DBSystemParameter`
  - `HTTPRequestHeader`
  - `HTTPResponseHeader`
  - `K8SCronJobAnnotation`
  - `K8SCronJobLabel`
  - `K8SDaemonSetAnnotation`
  - `K8SDaemonSetLabel`
  - `K8SDeploymentAnnotation`
  - `K8SDeploymentLabel`
  - `K8SJobAnnotation`
  - `K8SJobLabel`
  - `K8SNamespaceAnnotation`
  - `K8SNamespaceLabel`
  - `K8SNodeAnnotation`
  - `K8SNodeLabel`
  - `K8SPodAnnotation`
  - `K8SPodLabel`
  - `K8SReplicaSetAnnotation`
  - `K8SReplicaSetLabel`
  - `K8SStatefulSetAnnotation`
  - `K8SStatefulSetLabel`
  - `ProcessEnvironmentVariable`
  - `RPCConnectRPCRequestMetadata`
  - `RPCConnectRPCResponseMetadata`
  - `RPCGRPCRequestMetadata`
  - `RPCGRPCResponseMetadata`
- Add `ErrorType` attribute helper function to the
`go.opentelmetry.io/otel/semconv/v1.34.0` package. (#6962)
- Add `WithAllowKeyDuplication` in `go.opentelemetry.io/otel/sdk/log`
which can be used to disable deduplication for log records. (#6968)
- Add `WithCardinalityLimit` option to configure the cardinality limit
in `go.opentelemetry.io/otel/sdk/metric`. (#6996, #7065, #7081, #7164,
#7165, #7179)
- Add `Clone` method to `Record` in `go.opentelemetry.io/otel/log` that
returns a copy of the record with no shared state. (#7001)
- Add experimental self-observability span and batch span processor
metrics in `go.opentelemetry.io/otel/sdk/trace`. Check the
`go.opentelemetry.io/otel/sdk/trace/internal/x` package documentation
for more information. (#7027, #6393, #7209)
- The `go.opentelemetry.io/otel/semconv/v1.36.0` package. The package
contains semantic conventions from the `v1.36.0` version of the
OpenTelemetry Semantic Conventions. See the [migration
documentation](./semconv/v1.36.0/MIGRATION.md) for information on how to
upgrade from `go.opentelemetry.io/otel/semconv/v1.34.0.`(#7032, #7041)
- Add support for configuring Prometheus name translation using
`WithTranslationStrategy` option in
`go.opentelemetry.io/otel/exporters/prometheus`. The current default
translation strategy when UTF-8 mode is enabled is
`NoUTF8EscapingWithSuffixes`, but a future release will change the
default strategy to `UnderscoreEscapingWithSuffixes` for compliance with
the specification. (#7111)
- Add experimental self-observability log metrics in
`go.opentelemetry.io/otel/sdk/log`. Check the
`go.opentelemetry.io/otel/sdk/log/internal/x` package documentation for
more information. (#7121)
- Add experimental self-observability trace exporter metrics in
`go.opentelemetry.io/otel/exporters/stdout/stdouttrace`. Check the
`go.opentelemetry.io/otel/exporters/stdout/stdouttrace/internal/x`
package documentation for more information. (#7133)
- Support testing of [Go 1.25]. (#7187)
- The `go.opentelemetry.io/otel/semconv/v1.37.0` package. The package
contains semantic conventions from the `v1.37.0` version of the
OpenTelemetry Semantic Conventions. See the [migration
documentation](./semconv/v1.37.0/MIGRATION.md) for information on how to
upgrade from `go.opentelemetry.io/otel/semconv/v1.36.0.`(#7254)

### Changed

- Optimize `TraceIDFromHex` and `SpanIDFromHex` in
`go.opentelemetry.io/otel/sdk/trace`. (#6791)
- Change `AssertEqual` in `go.opentelemetry.io/otel/log/logtest` to
accept `TestingT` in order to support benchmarks and fuzz tests. (#6908)
- Change `DefaultExemplarReservoirProviderSelector` in
`go.opentelemetry.io/otel/sdk/metric` to use `runtime.GOMAXPROCS(0)`
instead of `runtime.NumCPU()` for the `FixedSizeReservoirProvider`
default size. (#7094)

### Fixed

- `SetBody` method of `Record` in `go.opentelemetry.io/otel/sdk/log` now
deduplicates key-value collections (`log.Value` of `log.KindMap` from
`go.opentelemetry.io/otel/log`). (#7002)
- Fix `go.opentelemetry.io/otel/exporters/prometheus` to not append a
suffix if it's already present in metric name. (#7088)
- Fix the `go.opentelemetry.io/otel/exporters/stdout/stdouttrace`
self-observability component type and name. (#7195)
- Fix partial export count metric in
`go.opentelemetry.io/otel/exporters/stdout/stdouttrace`. (#7199)

### Deprecated

- Deprecate `WithoutUnits` and `WithoutCounterSuffixes` options,
preferring `WithTranslationStrategy` instead. (#7111)
- Deprecate support for `OTEL_GO_X_CARDINALITY_LIMIT` environment
variable in `go.opentelemetry.io/otel/sdk/metric`. Use
`WithCardinalityLimit` option instead. (#7166)
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.

[Prometheus] Exporter should support Prometheus translation modes

7 participants