[Exporter.Prometheus] Fix spec compliance#7491
Conversation
- Do not emit redundant comments for PrometheusText. - Make `Accept` header parsing consistent between implementations.
- Fix incorrect fallback version for OpenMetrics. - Fix incorrect quotation mark escaping for `HELP` metadata.
Add PR number.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7491 +/- ##
==========================================
- Coverage 90.29% 90.29% -0.01%
==========================================
Files 287 288 +1
Lines 15617 15926 +309
==========================================
+ Hits 14102 14380 +278
- Misses 1515 1546 +31
Flags with carried forward coverage won't be shown. Click here to find out more.
|
There was a problem hiding this comment.
Pull request overview
This PR improves Prometheus exporter spec compliance across the HttpListener and ASP.NET Core implementations by aligning content negotiation and tightening text/OpenMetrics exposition output to match their respective specifications.
Changes:
- Removed Prometheus text-format-only “redundant” output (
# UNITlines and# EOFterminator), while keeping# EOFfor OpenMetrics. - Made
Acceptheader parsing consistent between ASP.NET Core middleware and HttpListener negotiation, including correct OpenMetrics default version selection. - Fixed escaping behavior for
# HELPmetadata so OpenMetrics escapes double quotes while Prometheus text does not.
Reviewed changes
Copilot reviewed 28 out of 29 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetric_SerializesMultibyteUtf8MetricNameProvidedByView_escaping=values_useOpenMetrics=False.verified.txt | Updates expected Prometheus text output to omit # UNIT. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetric_SerializesMultibyteUtf8MetricNameProvidedByView_escaping=underscores_useOpenMetrics=False.verified.txt | Updates expected Prometheus text output to omit # UNIT. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetric_SerializesMultibyteUtf8MetricNameProvidedByView_escaping=dots_useOpenMetrics=False.verified.txt | Updates expected Prometheus text output to omit # UNIT. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetric_SerializesMultibyteUtf8MetricNameProvidedByView_escaping=allow-utf-8_useOpenMetrics=False.verified.txt | Updates expected Prometheus text output to omit # UNIT. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.RunWithTextPlainResponseAndMeterTags.verified.text | Updates expected Prometheus text output to omit # UNIT and # EOF. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.RunWithTextPlainResponse.verified.text | Updates expected Prometheus text output to omit # UNIT and # EOF. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.RunHttpServerWithNoAcceptHeaderAndMeterTags.verified.text | Updates expected Prometheus text output to omit # UNIT and # EOF. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.RunHttpServerWithNoAcceptHeader.verified.text | Updates expected Prometheus text output to omit # UNIT and # EOF. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.MetricUnitDiscoveredLaterIsWrittenBeforeSamples.verified.txt | Updates expected Prometheus text output to omit # UNIT and # EOF. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.MetricMetadataDiscoveredLaterIsWrittenBeforeSamples.verified.txt | Updates expected Prometheus text output to omit # EOF. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.MetricHelpAndUnitDiscoveredTogetherLaterAreBothWrittenBeforeSamples.verified.txt | Updates expected Prometheus text output to omit # UNIT and # EOF. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.GaugeZeroDimensionWithUnit.verified.txt | Updates expected Prometheus text output to omit # UNIT. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.GaugeZeroDimensionWithDescriptionAndUnit.verified.txt | Updates expected Prometheus text output to omit # UNIT. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.ExponentialHistogramsAreIgnored.verified.txt | Updates expected Prometheus text output to omit # EOF. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.DuplicateMetricMetadataIsWrittenOncePerScrape.verified.txt | Updates expected Prometheus text output to omit # UNIT and # EOF. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.BufferSizeIncreasesWithLotOfMetrics.verified.text | Updates large expected Prometheus text output to omit repeated # UNIT and trailing # EOF. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusSerializerTests.cs | Adds/adjusts unit tests for HELP quote escaping and Prometheus-vs-OpenMetrics UNIT behavior. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusHttpListenerTests.cs | Updates integration expectations for OpenMetrics 1.0.0 content-type (incl. escaping) and removes Prometheus # UNIT/# EOF. |
| test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusAcceptHeaders.cs | Expands Accept-header test cases to validate OpenMetrics 1.0.0 fallback and escaping defaults. |
| test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusIntegrationTests.cs | Updates assertions to no longer expect # EOF in responses and still require newline termination. |
| test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMiddlewareTests.cs | Updates expected payload/content-type to match new negotiation and Prometheus text output rules. |
| src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/Shared/Serialization/TextFormatSerializer.cs | Makes EOF/unit writing format-specific and routes HELP through escaping logic that can optionally escape quotes. |
| src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/Shared/Serialization/PrometheusTextSerializer.cs | Disables UNIT emission and HELP-quote escaping for Prometheus text format. |
| src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/Shared/Serialization/OpenMetricsSerializer.cs | Ensures OpenMetrics HELP escapes quotes and output terminates with # EOF. |
| src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/Shared/PrometheusCollectionManager.cs | Uses the negotiated serializer to write EOF (or not) appropriately. |
| src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/PrometheusHeadersParser.cs | Fixes OpenMetrics negotiation fallback to 1.0.0 and keeps behavior aligned with escaping requirements. |
| src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md | Adds Unreleased entries describing the spec compliance fixes. |
| src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMiddleware.cs | Aligns ASP.NET Core Accept parsing with HttpListener rules (q parsing, OpenMetrics fallback, stable preference selection). |
| src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md | Adds Unreleased entries describing the spec compliance fixes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Changes
Fix some minor findings from checking the Prometheus exporters against the specifications with Claude and Copilot:
Acceptheader parsing consistent between AspNetCore and HttpListener implementations.HELPmetadata.Merge requirement checklist
CHANGELOG.mdfiles updated for non-trivial changesChanges in public API reviewed (if applicable)