Add Prometheus translation strategy support#8346
Add Prometheus translation strategy support#8346zeitlinger wants to merge 10 commits intoopen-telemetry:mainfrom
Conversation
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #8346 +/- ##
============================================
+ Coverage 90.31% 90.82% +0.50%
- Complexity 7725 8047 +322
============================================
Files 850 899 +49
Lines 23259 24204 +945
Branches 2364 2429 +65
============================================
+ Hits 21007 21983 +976
+ Misses 1528 1470 -58
- Partials 724 751 +27 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
psx95
left a comment
There was a problem hiding this comment.
Also might wanna look at this relevant spec issue: open-telemetry/opentelemetry-specification#5062
| new LinkedBlockingQueue<>(), | ||
| new DaemonThreadFactory("prometheus-http-server")); | ||
| } | ||
| HTTPServer.Builder httpServerBuilder = HTTPServer.builder(); |
There was a problem hiding this comment.
Question: Based on the "Interaction with Translation Strategy" spec, I was expecting to see some content negotiation, basically reading accept headers somewhere.
There was a problem hiding this comment.
let's park this until open-telemetry/opentelemetry-specification#5062 is resolved.
|
|
||
| assertThat(response.status()).isEqualTo(HttpStatus.OK); | ||
| assertThat(response.headers().get(HttpHeaderNames.CONTENT_TYPE)) | ||
| .isEqualTo("application/openmetrics-text; version=1.0.0; charset=utf-8"); |
There was a problem hiding this comment.
Shouldn't the accept header here also have the escaping scheme like shown here?
There was a problem hiding this comment.
let's park this until open-telemetry/opentelemetry-specification#5062 is resolved.
| @@ -239,6 +239,50 @@ void fetchOpenMetrics() { | |||
| + "# EOF\n"); | |||
| } | |||
|
|
|||
There was a problem hiding this comment.
I think there should be more tests that test behavior with other possible escaping schemes?
The spec only mentions two in the examples, but I imagine its because its meant to be non-exhaustive list.
There was a problem hiding this comment.
let's park this until open-telemetry/opentelemetry-specification#5062 is resolved.
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
jack-berg
left a comment
There was a problem hiding this comment.
Some small comments and ideas. Thanks!
| throw new IllegalStateException("Unknown strategy: " + translationStrategy); | ||
| } | ||
|
|
||
| private static MetricMetadata convertMetadataEscapedWithSuffixes(MetricData metricData) { |
There was a problem hiding this comment.
I find these convert methods in the weeds and hard to follow / verify. Going to have to trust that you've done the research.
Could help improve the readability by:
- Computing the MetricMetadata constructor params in a consistent order the same as MetricMetadata accepts (i.e. name, expositionName, originalName, help, unit)
- Using variable names which are the same as the param names of MetricMetadata
- Always using the same constructor overload so its explicit which things we're setting to null
For example, applied to this method it might look like:
private static MetricMetadata convertMetadataEscapedWithSuffixes(MetricData metricData) {
String name = convertLegacyMetricName(metricData.getName());
name = stripReservedMetricSuffixes(name);
String expositionBaseName = name;
String originalName = name;
String help = metricData.getDescription();
Unit unit = PrometheusUnitsHelper.convertUnit(metricData.getUnit());
if (unit != null && !name.endsWith(unit.toString())) {
name = name + "_" + unit;
}
validateNormalizedMetricName(metricData.getName(), name);
return new MetricMetadata(name, expositionBaseName, originalName, help, unit);
}
Something to think about to make it easier for humans to reason about / maintain.
There was a problem hiding this comment.
Applied to convertMetadataEscapedWithSuffixes (consistent ordering, single 5-arg MetricMetadata ctor) per your example. Left the other three strategy methods as-is for now since they read OK to me; happy to apply the same shape across all four if you'd prefer consistency. Commit 957e2e7.
There was a problem hiding this comment.
Hmm... let me think about this more.
- Replace IllegalArgumentException control flow in PrometheusUnitsHelper.sanitizeUnitName with @nullable return; drop the try/catch in unitOrNull. - Extract doConvert helper so convert is just the IAE try/catch boundary. - Inline the getMergeKey ternary at the putOrMerge call site. - Reorder convertMetadataEscapedWithSuffixes for readability and use the explicit 5-arg MetricMetadata constructor. Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Blocked by prometheus/client_java#2100
Summary
TranslationStrategysupport to the Prometheus exporter builder and declarative configclient_javato1.6.1, which provides the released naming support this needsprometheus/otlptranslatorbehavior for invalid characters, repeated underscores, and digit-leading labelsNotes
prometheus/otlptranslatorpreserves labels normalized to__...__; Prometheus Java rejects user labels starting with__, so those labels are collapsed to a valid single-underscore form instead.References
otlptranslator: https://github.com/prometheus/otlptranslatorTest plan
./gradlew :exporters:prometheus:test --tests io.opentelemetry.exporter.prometheus.PrometheusHttpServerTest.fetchOpenMetrics --tests io.opentelemetry.exporter.prometheus.PrometheusHttpServerTest.fetchOpenMetrics_translationStrategyEnablesOm2 --tests io.opentelemetry.exporter.prometheus.PrometheusMetricReaderTest --tests io.opentelemetry.exporter.prometheus.Otel2PrometheusConverterTest --tests io.opentelemetry.exporter.prometheus.internal.PrometheusMetricReaderProviderTest :sdk-extensions:declarative-config:test --tests io.opentelemetry.sdk.autoconfigure.declarativeconfig.MetricReaderFactoryTest.create_PullPrometheusConfiguredResolves #8195