diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/.publicApi/Stable/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/.publicApi/Stable/PublicAPI.Shipped.txt index 4b7af046438..30b70382df5 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/.publicApi/Stable/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/.publicApi/Stable/PublicAPI.Shipped.txt @@ -1,12 +1,12 @@ #nullable enable -~OpenTelemetry.Exporter.OtlpExporterOptions.BatchExportProcessorOptions.get -> OpenTelemetry.BatchExportProcessorOptions -~OpenTelemetry.Exporter.OtlpExporterOptions.BatchExportProcessorOptions.set -> void -~OpenTelemetry.Exporter.OtlpExporterOptions.Endpoint.get -> System.Uri -~OpenTelemetry.Exporter.OtlpExporterOptions.Endpoint.set -> void -~OpenTelemetry.Exporter.OtlpExporterOptions.Headers.get -> string -~OpenTelemetry.Exporter.OtlpExporterOptions.Headers.set -> void -~OpenTelemetry.Exporter.OtlpExporterOptions.HttpClientFactory.get -> System.Func -~OpenTelemetry.Exporter.OtlpExporterOptions.HttpClientFactory.set -> void +OpenTelemetry.Exporter.OtlpExporterOptions.BatchExportProcessorOptions.get -> OpenTelemetry.BatchExportProcessorOptions! +OpenTelemetry.Exporter.OtlpExporterOptions.BatchExportProcessorOptions.set -> void +OpenTelemetry.Exporter.OtlpExporterOptions.Endpoint.get -> System.Uri! +OpenTelemetry.Exporter.OtlpExporterOptions.Endpoint.set -> void +OpenTelemetry.Exporter.OtlpExporterOptions.Headers.get -> string? +OpenTelemetry.Exporter.OtlpExporterOptions.Headers.set -> void +OpenTelemetry.Exporter.OtlpExporterOptions.HttpClientFactory.get -> System.Func! +OpenTelemetry.Exporter.OtlpExporterOptions.HttpClientFactory.set -> void ~OpenTelemetry.Exporter.OtlpMetricExporter.OtlpMetricExporter(OpenTelemetry.Exporter.OtlpExporterOptions options) -> void ~OpenTelemetry.Exporter.OtlpTraceExporter.OtlpTraceExporter(OpenTelemetry.Exporter.OtlpExporterOptions options) -> void ~override OpenTelemetry.Exporter.OtlpMetricExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index d5d71920bd0..e88f15d58dd 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -35,6 +35,10 @@ ExponentialHistograms. ([#5397](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5397)) +* Setting `Endpoint` or `HttpClientFactory` properties on `OtlpExporterOptions` + to `null` will now result in an `ArgumentNullException` being thrown. + ([#5434](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5434)) + ## 1.7.0 Released 2023-Dec-08 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs index 0cffd50806c..0523b12d99a 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs @@ -1,6 +1,8 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +#nullable enable + using System.Diagnostics; using System.Reflection; #if NETFRAMEWORK @@ -10,7 +12,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenTelemetry.Internal; -using OpenTelemetry.Metrics; using OpenTelemetry.Trace; namespace OpenTelemetry.Exporter; @@ -38,7 +39,8 @@ public class OtlpExporterOptions private const string UserAgentProduct = "OTel-OTLP-Exporter-Dotnet"; - private Uri endpoint; + private Uri? endpoint; + private Func? httpClientFactory; /// /// Initializes a new instance of the class. @@ -66,7 +68,7 @@ internal OtlpExporterOptions( this.ApplyConfiguration(configuration, configurationType); - this.HttpClientFactory = this.DefaultHttpClientFactory = () => + this.DefaultHttpClientFactory = () => { return new HttpClient { @@ -74,16 +76,41 @@ internal OtlpExporterOptions( }; }; - this.BatchExportProcessorOptions = defaultBatchOptions; + this.BatchExportProcessorOptions = defaultBatchOptions!; } /// - /// Gets or sets the target to which the exporter is going to send telemetry. - /// Must be a valid Uri with scheme (http or https) and host, and - /// may contain a port and path. The default value is - /// * http://localhost:4317 for - /// * http://localhost:4318 for . + /// Gets or sets the target to which the exporter is going to send + /// telemetry. /// + /// + /// Notes: + /// + /// When setting the value must be a valid with scheme (http or https) and host, and may contain a + /// port and path. + /// The default value when not set is based on the property: + /// + /// http://localhost:4317 for . + /// http://localhost:4318 for . + /// + /// When is set to and has + /// not been set the default value (http://localhost:4318) will have + /// a signal-specific path appended. The final default endpoint values will + /// be constructed as: + /// + /// Logging: http://localhost:4318/v1/logs + /// Metrics: http://localhost:4318/v1/metrics + /// Tracing: http://localhost:4318/v1/traces + /// + /// + /// + /// + /// public Uri Endpoint { get @@ -100,24 +127,32 @@ public Uri Endpoint set { + Guard.ThrowIfNull(value); + this.endpoint = value; this.AppendSignalPathToEndpoint = false; } } /// - /// Gets or sets optional headers for the connection. Refer to the - /// specification for information on the expected format for Headers. + /// Gets or sets optional headers for the connection. /// - public string Headers { get; set; } + /// + /// Note: Refer to the + /// OpenTelemetry Specification for details on the format of . + /// + public string? Headers { get; set; } /// - /// Gets or sets the max waiting time (in milliseconds) for the backend to process each batch. The default value is 10000. + /// Gets or sets the max waiting time (in milliseconds) for the backend to + /// process each batch. Default value: 10000. /// public int TimeoutMilliseconds { get; set; } = 10000; /// - /// Gets or sets the the OTLP transport protocol. Supported values: Grpc and HttpProtobuf. + /// Gets or sets the the OTLP transport protocol. /// public OtlpExportProtocol Protocol { get; set; } = DefaultOtlpExportProtocol; @@ -144,27 +179,38 @@ public Uri Endpoint /// /// This is only invoked for the protocol. - /// The default behavior when using the extension is if an The default behavior when using tracing registration extensions is + /// if an IHttpClientFactory /// instance can be resolved through the application then an will be - /// created through the factory with the name "OtlpTraceExporter" - /// otherwise an will be instantiated - /// directly. - /// The default behavior when using the extension is if an will be instantiated directly. + /// The default behavior when using metrics registration extensions is + /// if an IHttpClientFactory /// instance can be resolved through the application then an will be - /// created through the factory with the name "OtlpMetricExporter" - /// otherwise an will be instantiated - /// directly. + /// created through the factory with the name "OtlpMetricExporter" otherwise + /// an will be instantiated directly. + /// + /// The default behavior when using logging registration extensions is an + /// will be instantiated directly. IHttpClientFactory + /// is not currently supported for logging. + /// /// /// - public Func HttpClientFactory { get; set; } + public Func HttpClientFactory + { + get => this.httpClientFactory ?? this.DefaultHttpClientFactory; + set + { + Guard.ThrowIfNull(value); + + this.httpClientFactory = value; + } + } /// /// Gets a value indicating whether or not the signal-specific path should @@ -228,7 +274,7 @@ private static string GetUserAgentString() try { var assemblyVersion = typeof(OtlpExporterOptions).Assembly.GetCustomAttribute(); - var informationalVersion = assemblyVersion.InformationalVersion; + var informationalVersion = assemblyVersion?.InformationalVersion; return string.IsNullOrEmpty(informationalVersion) ? UserAgentProduct : $"{UserAgentProduct}/{informationalVersion}"; } catch (Exception) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs index 85298517f95..1f99374c324 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs @@ -60,7 +60,7 @@ public static OpenTelemetryLoggerOptions AddOtlpExporter( return loggerOptions.AddProcessor(sp => { - var exporterOptions = GetOptions(sp, name, finalOptionsName, OtlpExporterOptions.CreateOtlpExporterOptions); + var exporterOptions = GetOptions(sp, name, finalOptionsName, OtlpExporterOptions.CreateOtlpExporterOptions); var processorOptions = sp.GetRequiredService>().Get(finalOptionsName); @@ -104,7 +104,7 @@ public static OpenTelemetryLoggerOptions AddOtlpExporter( return loggerOptions.AddProcessor(sp => { - var exporterOptions = GetOptions(sp, name, finalOptionsName, OtlpExporterOptions.CreateOtlpExporterOptions); + var exporterOptions = GetOptions(sp, name, finalOptionsName, OtlpExporterOptions.CreateOtlpExporterOptions); var processorOptions = sp.GetRequiredService>().Get(finalOptionsName); diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsTests.cs index 4ba49ec760a..bf55abb4795 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsTests.cs @@ -226,7 +226,7 @@ public void OtlpExporterOptions_EndpointGetterUsesProtocolWhenNull() } [Fact] - public void OtlpExporterOptions_EndpointGetterIgnoresProtocolWhenNotNull() + public void OtlpExporterOptions_EndpointThrowsWhenSetToNull() { var options = new OtlpExporterOptions { Endpoint = new Uri("http://test:8888"), Protocol = OtlpExportProtocol.Grpc }; @@ -243,6 +243,22 @@ public void OtlpExporterOptions_EnvironmentVariableNames() Assert.Equal("OTEL_EXPORTER_OTLP_PROTOCOL", OtlpSpecConfigDefinitions.DefaultProtocolEnvVarName); } + [Fact] + public void OtlpExporterOptions_SettingEndpointToNullResetsAppendSignalPathToEndpoint() + { + var options = new OtlpExporterOptions(OtlpExporterOptionsConfigurationType.Default); + + Assert.Throws(() => options.Endpoint = null); + } + + [Fact] + public void OtlpExporterOptions_HttpClientFactoryThrowsWhenSetToNull() + { + var options = new OtlpExporterOptions(OtlpExporterOptionsConfigurationType.Default); + + Assert.Throws(() => options.HttpClientFactory = null); + } + private static void ClearEnvVars() { foreach (var item in GetOtlpExporterOptionsTestCases()) diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs index 511e2f55876..92720ad0302 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs @@ -101,7 +101,7 @@ public void UserHttpFactoryCalledWhenUsingHttpProtobuf() Assert.Equal(2, invocations); } - options.HttpClientFactory = null; + options.HttpClientFactory = () => null; Assert.Throws(() => { using var exporter = new OtlpLogExporter(options); diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs index 7322c4d90e5..451362ed927 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs @@ -131,12 +131,6 @@ public void UserHttpFactoryCalled() Assert.Equal(2, invocations); } - options.HttpClientFactory = null; - Assert.Throws(() => - { - using var exporter = new OtlpMetricExporter(options); - }); - options.HttpClientFactory = () => null; Assert.Throws(() => { diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs index e3a5ad52b86..527fb5de72b 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs @@ -96,12 +96,6 @@ public void UserHttpFactoryCalled() Assert.Equal(2, invocations); } - options.HttpClientFactory = null; - Assert.Throws(() => - { - using var exporter = new OtlpTraceExporter(options); - }); - options.HttpClientFactory = () => null; Assert.Throws(() => {