Skip to content

[Exporter.Prometheus] Use snapshot tests for PrometheusSerializer#7354

Merged
martincostello merged 31 commits into
open-telemetry:mainfrom
martincostello:prometheus-verify-tests
Jun 5, 2026
Merged

[Exporter.Prometheus] Use snapshot tests for PrometheusSerializer#7354
martincostello merged 31 commits into
open-telemetry:mainfrom
martincostello:prometheus-verify-tests

Conversation

@martincostello
Copy link
Copy Markdown
Member

@martincostello martincostello commented Jun 2, 2026

Changes

Use Verify snapshots for PrometheusSerializer unit tests instead of brittle text-base Regex matches that do not validate the whole scrape response.

This PR intentionally only changes test code so that the snapshots could be auto-accepted during local development so that whatever is being verified is effectively the same content the previous assertions checked manually (excluding timestamps and span/trace IDs which aren't stable).

Merge requirement checklist

  • CONTRIBUTING guidelines followed (license requirements, nullable enabled, static analysis, etc.)
  • Unit tests added/updated
  • Appropriate CHANGELOG.md files updated for non-trivial changes
  • Changes in public API reviewed (if applicable)

- Emit OpenMetrics scope metadata as a single `otel_scope` metric family with `otel_scope_info` samples instead of repeating metadata for every scope.
- Include instrumentation scope metadata on samples using `otel_scope_*` labels, including scope version, schema URL, and prefixed scope attributes.
- Drop conflicting scope attributes named `name`, `version`, and `schema_url` to avoid collisions with generated scope labels.
Remove Go theme for .NET.
Address Copilot review feedback.
Add more test coverage for patch.
Move additions to the end.
- Fix missing handling for post-normalization collisions.
- Fix metadata conflict handling being bypassed in some cases.
Use canonical values for labels that are `float` or `double` to resolve TODO.
- Ensure `otel_scope_info` is sanitized.
- Fix missing collision handling.
# Conflicts:
#	src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md
#	src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md
#	src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/PrometheusSerializer.cs
Update PrometheusSerializer so scope-tag collisions with point tags now preserve the scope tag’s raw original key through the final merge, which fixes lexicographic value ordering for cases like `z` vs. `otel_scope_z`.
Remove synthetic OpenMetrics `otel_scope`/`otel_scope_info` metadata family.
Use Verify snapshots for `PrometheusSerializer` unit tests.
@github-actions github-actions Bot added pkg:OpenTelemetry.Exporter.Prometheus.AspNetCore Issues related to OpenTelemetry.Exporter.Prometheus.AspNetCore NuGet package pkg:OpenTelemetry.Exporter.Prometheus.HttpListener Issues related to OpenTelemetry.Exporter.Prometheus.HttpListener NuGet package labels Jun 2, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.07%. Comparing base (aee11ba) to head (e5e871c).
⚠️ Report is 3 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #7354      +/-   ##
==========================================
+ Coverage   90.04%   90.07%   +0.03%     
==========================================
  Files         276      276              
  Lines       14283    14283              
==========================================
+ Hits        12861    12866       +5     
+ Misses       1422     1417       -5     
Flag Coverage Δ
unittests-Project-Experimental 89.89% <ø> (-0.08%) ⬇️
unittests-Project-Stable 89.88% <ø> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 2 files with indirect coverage changes

Add snapshots for `PrometheusCollectionManager` tests too.
Use a stable service name to handle cross-platform differences in the test process' name.
@martincostello martincostello marked this pull request as ready for review June 3, 2026 10:53
@martincostello martincostello requested a review from a team as a code owner June 3, 2026 10:53
Copilot AI review requested due to automatic review settings June 3, 2026 10:53
@martincostello martincostello enabled auto-merge June 3, 2026 10:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates Prometheus exporter unit/integration tests from partial regex-based assertions to Verify snapshot testing, improving coverage of full scrape/serialization outputs while scrubbing unstable values (timestamps, span/trace IDs, SDK version).

Changes:

  • Replace brittle string/regex assertions with Verify snapshot assertions across PrometheusSerializer-related tests.
  • Add a shared VerifySettings configuration to normalize/scrub unstable output and standardize snapshot naming/locations.
  • Add and populate .verified.txt snapshot baselines for a broad set of Prometheus/OpenMetrics serialization scenarios.

Reviewed changes

Copilot reviewed 75 out of 75 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test/Shared/XunitContainerFixture{T}.cs Adds IDE0005 suppression around a redundant using in shared fixture code.
test/Shared/EnabledOnDockerPlatformTheoryAttribute.cs Adds IDE0005 suppression around using Xunit; in shared attribute helper.
test/Shared/EnabledOnDockerPlatformFactAttribute.cs Adds IDE0005 suppression around using Xunit; in shared attribute helper.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PromToolCollection.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusSerializerTests.cs Converts many tests to snapshot verification; introduces shared VerifySettings and scrubbing regexes.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusMetricTests.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusIntegrationTests.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusHttpListenerTests.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusHttpListenerMeterProviderBuilderExtensionsTests.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusHeadersParserTests.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusCollectionManagerTests.cs Switches scrape-output assertions to snapshots and stabilizes resource attributes for deterministic target_info.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusCollection.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusAcceptHeaders.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/EventSourceTests.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests.csproj Adds Verify.Xunit and assembly metadata for snapshot directory location.
test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusIntegrationTests.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMiddlewareTests.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMeterProviderBuilderExtensionsTests.cs Removes explicit using Xunit; (relies on implicit/global imports).
test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests.csproj Adds Verify.Xunit and points to shared snapshots directory (path currently OS-specific).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricPrefixesScopeAttributesAndDropsConflictingScopeAttributeNames.Net4_6.verified.txt New snapshot baseline for net46 output variant.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricPrefixesScopeAttributesAndDropsConflictingScopeAttributeNames.DotNet8_0.verified.txt New snapshot baseline for .NET 8 output variant.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricPrefixesScopeAttributesAndDropsConflictingScopeAttributeNames.DotNet9_0.verified.txt New snapshot baseline for .NET 9 output variant.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricPrefixesScopeAttributesAndDropsConflictingScopeAttributeNames.DotNet10_0.verified.txt New snapshot baseline for .NET 10 output variant.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricDropsScopeAttributesWhoseNormalizedNamesConflictWithGeneratedScopeNameAndVersionLabels.verified.txt New snapshot baseline for scope-attribute conflict behavior.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricDropsScopeAttributesWhoseNormalizedNamesConflictWithGeneratedScopeLabels.verified.txt New snapshot baseline for generated scope label conflicts.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricConcatenatesPointTagsThatCollideWithScopeLabels_snapshotName=plain_useOpenMetrics=True.verified.txt New snapshot for point-tag collision behavior (OpenMetrics).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricConcatenatesPointTagsThatCollideWithScopeLabels_snapshotName=plain_useOpenMetrics=False.verified.txt New snapshot for point-tag collision behavior (text format).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricConcatenatesPointTagsThatCollideWithScopeLabels_snapshotName=dots_useOpenMetrics=True.verified.txt New snapshot for dotted-label collision behavior (OpenMetrics).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricConcatenatesPointTagsThatCollideWithScopeLabels_snapshotName=dots_useOpenMetrics=False.verified.txt New snapshot for dotted-label collision behavior (text format).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricConcatenatesCollidingSanitizedLabelValuesInLexicographicOrder.verified.txt New snapshot for sanitized value concatenation ordering.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricConcatenatesCollidingLeadingDigitLabelKeys.verified.txt New snapshot for leading-digit label-key collision behavior.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteMetricConcatenatesCollidingEmptyAndUnderscoreLabelKeys.verified.txt New snapshot for empty/underscore label-key collision behavior.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.WriteHistogramMetricSerializesStaticTagsWithoutPreSerializedTags.verified.txt New snapshot for histogram static-tag serialization behavior.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.SumWithScopeVersion.verified.txt New snapshot for scope version label emission.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.SumWithOpenMetricsFormat.verified.txt New snapshot for OpenMetrics sum formatting.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.SumNonMonotonicDouble.verified.txt New snapshot for non-monotonic sum serialization.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.SumLongSerializesBoundaryValues_value=0.verified.txt New snapshot for long boundary value 0.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.SumLongSerializesBoundaryValues_value=9223372036854775807.verified.txt New snapshot for long boundary value long.MaxValue.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.SumDoubleInfinities.verified.txt New snapshot for +Inf counter serialization.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.OpenMetricsWritesMetricFamiliesContiguously.verified.txt New snapshot ensuring OpenMetrics metric family contiguity.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.OpenMetricsDoesNotReserveOtelScopeMetricFamilyNames.verified.txt New snapshot ensuring otel_scope names are not reserved.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.OpenMetricsDoesNotEmitScopeInfoMetricFamily.verified.txt New snapshot ensuring scope info family is not emitted.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.DuplicateMetricMetadataIsWrittenOncePerScrape.verified.txt New snapshot ensuring metadata appears once per scrape.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.MetricMetadataDiscoveredLaterIsWrittenBeforeSamples.verified.txt New snapshot for late-discovered HELP ordering.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.MetricUnitDiscoveredLaterIsWrittenBeforeSamples.verified.txt New snapshot for late-discovered UNIT ordering.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.MetricHelpAndUnitDiscoveredTogetherLaterAreBothWrittenBeforeSamples.verified.txt New snapshot for combined HELP/UNIT ordering behavior.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.ConflictingMetricTypesAreDroppedFromAScrape.verified.txt New snapshot ensuring conflicting types are dropped.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramZeroDimension.verified.txt New snapshot for zero-dimension histogram output.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramOneDimension.verified.txt New snapshot for one-dimension histogram output.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramTwoDimensions.verified.txt New snapshot for two-dimension histogram output.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramOneDimensionWithOpenMetricsFormat.verified.txt New snapshot for OpenMetrics histogram formatting.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramOneDimensionWithScopeVersion.verified.txt New snapshot for OpenMetrics histogram + scope version.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramWithOpenMetricsFormatEmitsLatestBucketExemplar.verified.txt New snapshot for exemplar selection behavior.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramWithOpenMetricsFormatFiltersSanitizedReservedExemplarTagNames.verified.txt New snapshot for filtering reserved exemplar labels.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramWithOpenMetricsFormatDropsCollidingLeLabelKeys.verified.txt New snapshot for dropping colliding le labels.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramWithNegativeBucketBoundsOmitsSumAndCountWithOpenMetricsFormat.verified.txt New snapshot for negative buckets omitting sum/count in OM format.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramInfinities.verified.txt New snapshot for histogram +Inf sum.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramNaN.verified.txt New snapshot for histogram NaN sum.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramExportsCreatedMetric_useOpenMetrics=True.verified.txt New snapshot for _created emission in OpenMetrics.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramExportsCreatedMetric_useOpenMetrics=False.verified.txt New snapshot ensuring no _created in text format.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.HistogramCreatedMetricSkipsReservedHistogramLabels.verified.txt New snapshot ensuring reserved histogram labels are skipped for created metric.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.CounterExportsCreatedMetric_useOpenMetrics=True.verified.txt New snapshot for counter _created emission in OpenMetrics.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.CounterExportsCreatedMetric_useOpenMetrics=False.verified.txt New snapshot ensuring no counter _created in text format.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.CounterWithOpenMetricsFormatEmitsLatestExemplar.verified.txt New snapshot for counter exemplar emission (latest).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.CounterWithOpenMetricsFormatEmitsExemplarWithoutLabelsWhenOnlyReservedTagNamesAreFiltered.verified.txt New snapshot for empty exemplar label-set after filtering.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.CounterWithOpenMetricsFormatFiltersSanitizedReservedExemplarTagNames.verified.txt New snapshot for reserved exemplar label filtering (counter).
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.CounterWithOpenMetricsFormatDropsExemplarLabelsExceedingLimit.verified.txt New snapshot for dropping overly-long exemplar labels.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.GaugeZeroDimension.verified.txt New snapshot for basic gauge output.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.GaugeZeroDimensionWithDescription.verified.txt New snapshot for gauge HELP emission.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.GaugeZeroDimensionWithUnit.verified.txt New snapshot for gauge UNIT emission.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.GaugeZeroDimensionWithDescriptionAndUnit.verified.txt New snapshot for gauge HELP+UNIT emission.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.GaugeOneDimension.verified.txt New snapshot for labeled gauge output.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.GaugeBoolDimension.verified.txt New snapshot for boolean label value formatting.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.GaugeEmptyDimensionName.verified.txt New snapshot for empty dimension key normalization.
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/snapshots/PrometheusSerializer.GaugeDoubleSubnormal.verified.txt New snapshot for -Inf/+Inf/NaN gauge serialization.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/Shared/XunitContainerFixture{T}.cs Outdated
Comment thread test/Shared/EnabledOnDockerPlatformFactAttribute.cs Outdated
Comment thread test/Shared/EnabledOnDockerPlatformTheoryAttribute.cs Outdated
Remove `async Task` from tests that don't await.
@martincostello martincostello added this pull request to the merge queue Jun 5, 2026
Merged via the queue into open-telemetry:main with commit 4cb15d5 Jun 5, 2026
56 checks passed
@martincostello martincostello deleted the prometheus-verify-tests branch June 5, 2026 04:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg:OpenTelemetry.Exporter.Prometheus.AspNetCore Issues related to OpenTelemetry.Exporter.Prometheus.AspNetCore NuGet package pkg:OpenTelemetry.Exporter.Prometheus.HttpListener Issues related to OpenTelemetry.Exporter.Prometheus.HttpListener NuGet package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants