diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleExporterMetricsExtensions.cs b/src/OpenTelemetry.Exporter.Console/ConsoleExporterMetricsExtensions.cs index 0c35b81bdea..fad30a68841 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleExporterMetricsExtensions.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleExporterMetricsExtensions.cs @@ -97,14 +97,11 @@ private static MeterProviderBuilder AddConsoleExporter( var metricExporter = new ConsoleMetricExporter(exporterOptions); - if (metricReaderOptions.MetricReaderType == (MetricReaderType)(-1)) - { - metricReaderOptions.MetricReaderType = MetricReaderType.Manual; - } - var metricReader = metricReaderOptions.MetricReaderType == MetricReaderType.Manual ? new BaseExportingMetricReader(metricExporter) - : new PeriodicExportingMetricReader(metricExporter, metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds); + : new PeriodicExportingMetricReader( + metricExporter, + metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds ?? -1); metricReader.Temporality = metricReaderOptions.Temporality; return builder.AddReader(metricReader); diff --git a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterMetricsExtensions.cs b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterMetricsExtensions.cs index b43d602df8d..7f5c4465023 100644 --- a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterMetricsExtensions.cs +++ b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterMetricsExtensions.cs @@ -81,14 +81,11 @@ private static MeterProviderBuilder AddInMemoryExporter( var metricExporter = new InMemoryExporter(exportedItems); - if (metricReaderOptions.MetricReaderType == (MetricReaderType)(-1)) - { - metricReaderOptions.MetricReaderType = MetricReaderType.Manual; - } - var metricReader = metricReaderOptions.MetricReaderType == MetricReaderType.Manual ? new BaseExportingMetricReader(metricExporter) - : new PeriodicExportingMetricReader(metricExporter, metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds); + : new PeriodicExportingMetricReader( + metricExporter, + metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds ?? -1); metricReader.Temporality = metricReaderOptions.Temporality; return builder.AddReader(metricReader); diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index 907d5f7f093..74fdd033608 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +* Fixed OTLP metric exporter to default to a periodic 60 second export cycle. + A bug was introduced in #2717 that caused the OTLP metric export to default + to a manual export cycle (i.e., requiring an explicit flush). A workaround + for this bug has been provided + [here](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2979#issuecomment-1061060541). + ([#2982](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2982)) + ## 1.2.0-rc3 Released 2022-Mar-04 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs index 118c1e89808..89bf04a8d30 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs @@ -25,6 +25,8 @@ namespace OpenTelemetry.Metrics /// public static class OtlpMetricExporterExtensions { + private const int DefaultExportIntervalMilliseconds = 60000; + /// /// Adds to the using default options. /// @@ -102,14 +104,11 @@ private static MeterProviderBuilder AddOtlpExporter( var metricExporter = new OtlpMetricExporter(exporterOptions); - if (metricReaderOptions.MetricReaderType == (MetricReaderType)(-1)) - { - metricReaderOptions.MetricReaderType = MetricReaderType.Periodic; - } - var metricReader = metricReaderOptions.MetricReaderType == MetricReaderType.Manual ? new BaseExportingMetricReader(metricExporter) - : new PeriodicExportingMetricReader(metricExporter, metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds); + : new PeriodicExportingMetricReader( + metricExporter, + metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds ?? DefaultExportIntervalMilliseconds); metricReader.Temporality = metricReaderOptions.Temporality; return builder.AddReader(metricReader); diff --git a/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt index 4305ae25fd5..91d679d8b85 100644 --- a/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt @@ -103,7 +103,7 @@ OpenTelemetry.Metrics.PeriodicExportingMetricReader OpenTelemetry.Metrics.PeriodicExportingMetricReader.PeriodicExportingMetricReader(OpenTelemetry.BaseExporter exporter, int exportIntervalMilliseconds = 60000, int exportTimeoutMilliseconds = 30000) -> void OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.PeriodicExportingMetricReaderOptions() -> void -OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds.get -> int +OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds.get -> int? OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds.set -> void OpenTelemetry.ReadOnlyTagCollection OpenTelemetry.ReadOnlyTagCollection.Count.get -> int diff --git a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 4305ae25fd5..91d679d8b85 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -103,7 +103,7 @@ OpenTelemetry.Metrics.PeriodicExportingMetricReader OpenTelemetry.Metrics.PeriodicExportingMetricReader.PeriodicExportingMetricReader(OpenTelemetry.BaseExporter exporter, int exportIntervalMilliseconds = 60000, int exportTimeoutMilliseconds = 30000) -> void OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.PeriodicExportingMetricReaderOptions() -> void -OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds.get -> int +OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds.get -> int? OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds.set -> void OpenTelemetry.ReadOnlyTagCollection OpenTelemetry.ReadOnlyTagCollection.Count.get -> int diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index e2c59c126ff..5cfd6d278e2 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +* The `PeriodicExportingMetricReader` now accepts an + `ExportIntervalMilliseconds` of `-1` indicating an infinite export interval + period. + ([#2982](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2982)) + ## 1.2.0-rc3 Released 2022-Mar-04 diff --git a/src/OpenTelemetry/Metrics/MetricReaderOptions.cs b/src/OpenTelemetry/Metrics/MetricReaderOptions.cs index d9fe24b909d..0ca01e8b285 100644 --- a/src/OpenTelemetry/Metrics/MetricReaderOptions.cs +++ b/src/OpenTelemetry/Metrics/MetricReaderOptions.cs @@ -21,9 +21,6 @@ namespace OpenTelemetry.Metrics; /// public class MetricReaderOptions { - private const MetricReaderType MetricReaderTypeUnspecified = (MetricReaderType)(-1); - private MetricReaderType metricReaderType = MetricReaderTypeUnspecified; - /// /// Gets or sets the AggregationTemporality used for Histogram /// and Sum metrics. @@ -31,25 +28,9 @@ public class MetricReaderOptions public AggregationTemporality Temporality { get; set; } = AggregationTemporality.Cumulative; /// - /// Gets or sets the to use. Defaults to MetricReaderType.Manual. + /// Gets or sets the to use. Defaults to MetricReaderType.Periodic. /// - public MetricReaderType MetricReaderType - { - get - { - if (this.metricReaderType == MetricReaderTypeUnspecified) - { - this.metricReaderType = MetricReaderType.Manual; - } - - return this.metricReaderType; - } - - set - { - this.metricReaderType = value; - } - } + public MetricReaderType MetricReaderType { get; set; } = MetricReaderType.Periodic; /// /// Gets or sets the options. Ignored unless MetricReaderType is Periodic. diff --git a/src/OpenTelemetry/Metrics/PeriodicExportingMetricReader.cs b/src/OpenTelemetry/Metrics/PeriodicExportingMetricReader.cs index c820f748907..40300d001e5 100644 --- a/src/OpenTelemetry/Metrics/PeriodicExportingMetricReader.cs +++ b/src/OpenTelemetry/Metrics/PeriodicExportingMetricReader.cs @@ -50,7 +50,8 @@ public PeriodicExportingMetricReader( int exportTimeoutMilliseconds = DefaultExportTimeoutMilliseconds) : base(exporter) { - Guard.ThrowIfOutOfRange(exportIntervalMilliseconds, min: 1); + Guard.ThrowIfInvalidTimeout(exportIntervalMilliseconds); + Guard.ThrowIfZero(exportIntervalMilliseconds); Guard.ThrowIfOutOfRange(exportTimeoutMilliseconds, min: 0); if ((this.SupportedExportModes & ExportModes.Push) != ExportModes.Push) diff --git a/src/OpenTelemetry/Metrics/PeriodicExportingMetricReaderOptions.cs b/src/OpenTelemetry/Metrics/PeriodicExportingMetricReaderOptions.cs index af1df534cdc..1a2efa19bed 100644 --- a/src/OpenTelemetry/Metrics/PeriodicExportingMetricReaderOptions.cs +++ b/src/OpenTelemetry/Metrics/PeriodicExportingMetricReaderOptions.cs @@ -19,8 +19,8 @@ namespace OpenTelemetry.Metrics public class PeriodicExportingMetricReaderOptions { /// - /// Gets or sets the metric export interval in milliseconds. The default value is 60000. + /// Gets or sets the metric export interval in milliseconds. /// - public int ExportIntervalMilliseconds { get; set; } = 60000; + public int? ExportIntervalMilliseconds { get; set; } } } diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs index e64595179b0..4c6260d4f02 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs @@ -30,8 +30,40 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests { - public class OtlpMetricsExporterTests + public class OtlpMetricsExporterTests : Http2UnencryptedSupportTests { + [Fact] + public void TestAddOtlpExporter_SetsCorrectMetricReaderDefaults() + { + if (Environment.Version.Major == 3) + { + // Adding the OtlpExporter creates a GrpcChannel. + // This switch must be set before creating a GrpcChannel when calling an insecure HTTP/2 endpoint. + // See: https://docs.microsoft.com/aspnet/core/grpc/troubleshoot#call-insecure-grpc-services-with-net-core-client + AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); + } + + var meterProvider = Sdk.CreateMeterProviderBuilder() + .AddOtlpExporter() + .Build(); + + var bindingFlags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance; + + var metricReader = typeof(MetricReader) + .Assembly + .GetType("OpenTelemetry.Metrics.MeterProviderSdk") + .GetField("reader", bindingFlags) + .GetValue(meterProvider) as PeriodicExportingMetricReader; + + Assert.NotNull(metricReader); + + var exportIntervalMilliseconds = (int)typeof(PeriodicExportingMetricReader) + .GetField("exportIntervalMilliseconds", bindingFlags) + .GetValue(metricReader); + + Assert.Equal(60000, exportIntervalMilliseconds); + } + [Fact] public void UserHttpFactoryCalled() {