diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln
index cea58bc408a..1b3928c1163 100644
--- a/OpenTelemetry.sln
+++ b/OpenTelemetry.sln
@@ -305,7 +305,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "experimental-apis", "experi
ProjectSection(SolutionItems) = preProject
docs\diagnostics\experimental-apis\OTEL1000.md = docs\diagnostics\experimental-apis\OTEL1000.md
docs\diagnostics\experimental-apis\OTEL1001.md = docs\diagnostics\experimental-apis\OTEL1001.md
- docs\diagnostics\experimental-apis\OTEL1003.md = docs\diagnostics\experimental-apis\OTEL1003.md
docs\diagnostics\experimental-apis\OTEL1004.md = docs\diagnostics\experimental-apis\OTEL1004.md
docs\diagnostics\experimental-apis\README.md = docs\diagnostics\experimental-apis\README.md
EndProjectSection
diff --git a/build/Common.props b/build/Common.props
index b625439458e..c1a4874c57f 100644
--- a/build/Common.props
+++ b/build/Common.props
@@ -13,7 +13,7 @@
all
low
- $(NoWarn);OTEL1000;OTEL1001;OTEL1002;OTEL1003;OTEL1004
+ $(NoWarn);OTEL1000;OTEL1001;OTEL1002;OTEL1004
diff --git a/docs/diagnostics/experimental-apis/OTEL1003.md b/docs/diagnostics/experimental-apis/OTEL1003.md
deleted file mode 100644
index 5f62f03575f..00000000000
--- a/docs/diagnostics/experimental-apis/OTEL1003.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# OpenTelemetry .NET Diagnostic: OTEL1003
-
-## Overview
-
-This is an Experimental API diagnostic covering the following API:
-
-* `MetricStreamConfiguration.CardinalityLimit.get`
-* `MetricStreamConfiguration.CardinalityLimit.set`
-
-Experimental APIs may be changed or removed in the future.
-
-## Details
-
-From the specification:
-
-> The cardinality limit for an aggregation is defined in one of three ways:
->
-> 1. A view with criteria matching the instrument an aggregation is created for
-> has an `aggregation_cardinality_limit` value defined for the stream, that
-> value SHOULD be used.
-> 2. If there is no matching view, but the `MetricReader` defines a default
-> cardinality limit value based on the instrument an aggregation is created
-> for, that value SHOULD be used.
-> 3. If none of the previous values are defined, the default value of 2000
-> SHOULD be used.
-
-We are exposing these APIs experimentally until the specification declares them
-stable.
-
-### Setting cardinality limit for a specific Metric via the View API
-
-The OpenTelemetry Specification defines the [cardinality
-limit](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#cardinality-limits)
-of a metric can be set by the matching view.
-
-```csharp
-using var meterProvider = Sdk.CreateMeterProviderBuilder()
- .AddView(
- instrumentName: "MyFruitCounter",
- new MetricStreamConfiguration { CardinalityLimit = 10 })
- .Build();
-```
-
-### Setting cardinality limit for a specific MetricReader
-
-[This is not currently supported by OpenTelemetry
-.NET.](https://github.com/open-telemetry/opentelemetry-dotnet/issues/5331)
diff --git a/docs/diagnostics/experimental-apis/README.md b/docs/diagnostics/experimental-apis/README.md
index 6c581030b4c..daa80d34b38 100644
--- a/docs/diagnostics/experimental-apis/README.md
+++ b/docs/diagnostics/experimental-apis/README.md
@@ -27,12 +27,6 @@ Description: Logs Bridge API
Details: [OTEL1001](./OTEL1001.md)
-### OTEL1003
-
-Description: MetricStreamConfiguration CardinalityLimit Support
-
-Details: [OTEL1003](./OTEL1003.md)
-
### OTEL1004
Description: ExemplarReservoir Support
@@ -58,3 +52,11 @@ Description: Metrics Exemplar Support
Details: [OTEL1002](https://github.com/open-telemetry/opentelemetry-dotnet/blob/b8ea807bae1a5d9b0f3d6d23b1e1e10f5e096a25/docs/diagnostics/experimental-apis/OTEL1002.md)
Released stable: `1.9.0`
+
+### OTEL1003
+
+Description: MetricStreamConfiguration CardinalityLimit Support
+
+Details: [OTEL1003](https://github.com/open-telemetry/opentelemetry-dotnet/blob/9f41eadf03f3dcc5e76c686b61fb39849f046312/docs/diagnostics/experimental-apis/OTEL1003.md)
+
+Released stable: `1.10.0`
diff --git a/docs/metrics/customizing-the-sdk/README.md b/docs/metrics/customizing-the-sdk/README.md
index 8aaeef19fad..560149e20e6 100644
--- a/docs/metrics/customizing-the-sdk/README.md
+++ b/docs/metrics/customizing-the-sdk/README.md
@@ -403,9 +403,8 @@ metrics managed by a given `MeterProvider`, use the
> [!CAUTION]
> `MeterProviderBuilder.SetMaxMetricPointsPerMetricStream` is marked `Obsolete`
- in pre-release builds and has been replaced by
- `MetricStreamConfiguration.CardinalityLimit`. For details see:
- [OTEL1003](../../diagnostics/experimental-apis/OTEL1003.md).
+ in stable builds since 1.10.0 and has been replaced by
+ `MetricStreamConfiguration.CardinalityLimit`.
```csharp
using var meterProvider = Sdk.CreateMeterProviderBuilder()
@@ -421,11 +420,6 @@ To set the [cardinality limit](../README.md#cardinality-limits) for an
individual metric, use the `MetricStreamConfiguration.CardinalityLimit` property
on the View API:
-> [!NOTE]
-> `MetricStreamConfiguration.CardinalityLimit` is an experimental API only
- available in pre-release builds. For details see:
- [OTEL1003](../../diagnostics/experimental-apis/OTEL1003.md).
-
```csharp
var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("MyCompany.MyProduct.MyLibrary")
diff --git a/src/OpenTelemetry/.publicApi/Experimental/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/Experimental/PublicAPI.Unshipped.txt
index a6594de1a9c..7c9a6d046ae 100644
--- a/src/OpenTelemetry/.publicApi/Experimental/PublicAPI.Unshipped.txt
+++ b/src/OpenTelemetry/.publicApi/Experimental/PublicAPI.Unshipped.txt
@@ -17,8 +17,6 @@ OpenTelemetry.Metrics.FixedSizeExemplarReservoir.Capacity.get -> int
OpenTelemetry.Metrics.FixedSizeExemplarReservoir.FixedSizeExemplarReservoir(int capacity) -> void
OpenTelemetry.Metrics.FixedSizeExemplarReservoir.UpdateExemplar(int exemplarIndex, in OpenTelemetry.Metrics.ExemplarMeasurement measurement) -> void
OpenTelemetry.Metrics.FixedSizeExemplarReservoir.UpdateExemplar(int exemplarIndex, in OpenTelemetry.Metrics.ExemplarMeasurement measurement) -> void
-OpenTelemetry.Metrics.MetricStreamConfiguration.CardinalityLimit.get -> int?
-OpenTelemetry.Metrics.MetricStreamConfiguration.CardinalityLimit.set -> void
OpenTelemetry.Metrics.MetricStreamConfiguration.ExemplarReservoirFactory.get -> System.Func?
OpenTelemetry.Metrics.MetricStreamConfiguration.ExemplarReservoirFactory.set -> void
override sealed OpenTelemetry.Metrics.FixedSizeExemplarReservoir.Collect() -> OpenTelemetry.Metrics.ReadOnlyExemplarCollection
diff --git a/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt
index 7dc29c7de2d..5f0fd41cd26 100644
--- a/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt
+++ b/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt
@@ -1,3 +1,5 @@
+OpenTelemetry.Metrics.MetricStreamConfiguration.CardinalityLimit.get -> int?
+OpenTelemetry.Metrics.MetricStreamConfiguration.CardinalityLimit.set -> void
OpenTelemetry.OpenTelemetrySdk
OpenTelemetry.OpenTelemetrySdk.Dispose() -> void
OpenTelemetry.OpenTelemetrySdk.LoggerProvider.get -> OpenTelemetry.Logs.LoggerProvider!
diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md
index 0f2bbd74d7c..6e33534e9c5 100644
--- a/src/OpenTelemetry/CHANGELOG.md
+++ b/src/OpenTelemetry/CHANGELOG.md
@@ -6,6 +6,11 @@ Notes](../../RELEASENOTES.md).
## Unreleased
+* The experimental APIs previously covered by `OTEL1003`
+ (`MetricStreamConfiguration.CardinalityLimit`) will now be part of the public
+ API and supported in stable builds.
+ ([#5926](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5926))
+
* Promoted overflow attribute from experimental to stable and removed the
`OTEL_DOTNET_EXPERIMENTAL_METRICS_EMIT_OVERFLOW_ATTRIBUTE` environment variable.
diff --git a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderExtensions.cs b/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderExtensions.cs
index 2808cfa51d4..1a5c1d950c3 100644
--- a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderExtensions.cs
+++ b/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderExtensions.cs
@@ -238,9 +238,7 @@ public static MeterProviderBuilder SetMaxMetricStreams(this MeterProviderBuilder
/// .
/// Maximum number of metric points allowed per metric stream.
/// The supplied for chaining.
-#if EXPOSE_EXPERIMENTAL_FEATURES
- [Obsolete("Use MetricStreamConfiguration.CardinalityLimit via the AddView API instead. This method will be removed in a future version.")]
-#endif
+ [Obsolete("Use MetricStreamConfiguration.CardinalityLimit via the AddView API instead. This method is marked as obsolete in version 1.10.0 and will be removed in a future version.")]
public static MeterProviderBuilder SetMaxMetricPointsPerMetricStream(this MeterProviderBuilder meterProviderBuilder, int maxMetricPointsPerMetricStream)
{
Guard.ThrowIfOutOfRange(maxMetricPointsPerMetricStream, min: 1);
diff --git a/src/OpenTelemetry/Metrics/View/MetricStreamConfiguration.cs b/src/OpenTelemetry/Metrics/View/MetricStreamConfiguration.cs
index cc36941ce68..cf5e06661a0 100644
--- a/src/OpenTelemetry/Metrics/View/MetricStreamConfiguration.cs
+++ b/src/OpenTelemetry/Metrics/View/MetricStreamConfiguration.cs
@@ -98,14 +98,11 @@ public string[]? TagKeys
}
}
-#if EXPOSE_EXPERIMENTAL_FEATURES
///
/// Gets or sets a positive integer value defining the maximum number of
/// data points allowed for the metric managed by the view.
///
///
- /// WARNING: This is an experimental API which might change or
- /// be removed in the future. Use at your own risk.
/// Spec reference: Cardinality
/// limits.
@@ -116,14 +113,7 @@ public string[]? TagKeys
/// If not set the default
/// MeterProvider cardinality limit of 2000 will apply.
///
-#if NET
- [Experimental(DiagnosticDefinitions.CardinalityLimitExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)]
-#endif
- public
-#else
- internal
-#endif
- int? CardinalityLimit
+ public int? CardinalityLimit
{
get => this.cardinalityLimit;
set
diff --git a/src/Shared/DiagnosticDefinitions.cs b/src/Shared/DiagnosticDefinitions.cs
index 75ed3187d70..f6b449352ff 100644
--- a/src/Shared/DiagnosticDefinitions.cs
+++ b/src/Shared/DiagnosticDefinitions.cs
@@ -9,10 +9,10 @@ internal static class DiagnosticDefinitions
public const string LoggerProviderExperimentalApi = "OTEL1000";
public const string LogsBridgeExperimentalApi = "OTEL1001";
- public const string CardinalityLimitExperimentalApi = "OTEL1003";
public const string ExemplarReservoirExperimentalApi = "OTEL1004";
/* Definitions which have been released stable:
public const string ExemplarExperimentalApi = "OTEL1002";
+ public const string CardinalityLimitExperimentalApi = "OTEL1003";
*/
}
diff --git a/test/OpenTelemetry.Tests/Metrics/MetricViewTests.cs b/test/OpenTelemetry.Tests/Metrics/MetricViewTests.cs
index 10eb9709842..50c9be30d31 100644
--- a/test/OpenTelemetry.Tests/Metrics/MetricViewTests.cs
+++ b/test/OpenTelemetry.Tests/Metrics/MetricViewTests.cs
@@ -1093,7 +1093,7 @@ public void ViewConflict_OneInstrument_DifferentDescription()
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CardinalityLimitofMatchingViewTakesPrecedenceOverMeterProvider(bool setDefault)
+ public void CardinalityLimitOfMatchingViewTakesPrecedenceOverMeterProvider(bool setDefault)
{
using var meter = new Meter(Utils.GetCurrentMethodName());
var exportedItems = new List();