diff --git a/build/Common.nonprod.props b/build/Common.nonprod.props index 28877f3bb99..7bd7554f769 100644 --- a/build/Common.nonprod.props +++ b/build/Common.nonprod.props @@ -28,7 +28,6 @@ [3.13.0,4.0) [2.27.0,3.0) [2.30.0, 3.0) - [2.32.0,3.0) [2.25.0,3.0) [5.2.7,6.0) [5.2.7,6.0) diff --git a/build/Common.props b/build/Common.props index b719ee866a5..b00ef806eac 100644 --- a/build/Common.props +++ b/build/Common.props @@ -24,6 +24,7 @@ [2.3.0,3.0) [3.6.1,4.0) [2.23.0,3.0) + [2.32.0,3.0) [2.25.0,3.0) [2.1.1,6.0) [2.1.1,6.0) diff --git a/examples/AspNetCore/Startup.cs b/examples/AspNetCore/Startup.cs index 3e12b76c0f0..9711826df8e 100644 --- a/examples/AspNetCore/Startup.cs +++ b/examples/AspNetCore/Startup.cs @@ -80,13 +80,18 @@ public void ConfigureServices(IServiceCollection services) })); break; case "otlp": + // Adding the OtlpExporter creates a GrpcChannel. + // This switch must be set before creating a GrpcChannel/HttpClient when calling an insecure gRPC service. + // 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); + services.AddOpenTelemetryTracing((builder) => builder .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(this.Configuration.GetValue("Otlp:ServiceName"))) .AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddOtlpExporter(otlpOptions => { - otlpOptions.Endpoint = this.Configuration.GetValue("Otlp:Endpoint"); + otlpOptions.Endpoint = new Uri(this.Configuration.GetValue("Otlp:Endpoint")); })); break; default: diff --git a/examples/Console/Program.cs b/examples/Console/Program.cs index 8248363a6a0..508bf826a97 100644 --- a/examples/Console/Program.cs +++ b/examples/Console/Program.cs @@ -133,7 +133,7 @@ internal class OpenTracingShimOptions [Verb("otlp", HelpText = "Specify the options required to test OpenTelemetry Protocol (OTLP)")] internal class OtlpOptions { - [Option('e', "endpoint", HelpText = "Target to which the exporter is going to send traces or metrics", Default = "localhost:55680")] + [Option('e', "endpoint", HelpText = "Target to which the exporter is going to send traces or metrics", Default = "http://localhost:55680")] public string Endpoint { get; set; } } diff --git a/examples/Console/TestOtlpExporter.cs b/examples/Console/TestOtlpExporter.cs index 8043ca3844b..656e5ba06e2 100644 --- a/examples/Console/TestOtlpExporter.cs +++ b/examples/Console/TestOtlpExporter.cs @@ -14,6 +14,7 @@ // limitations under the License. // +using System; using OpenTelemetry; using OpenTelemetry.Resources; using OpenTelemetry.Trace; @@ -53,12 +54,17 @@ internal static object Run(string endpoint) private static object RunWithActivitySource(string endpoint) { + // Adding the OtlpExporter creates a GrpcChannel. + // This switch must be set before creating a GrpcChannel/HttpClient when calling an insecure gRPC service. + // 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); + // Enable OpenTelemetry for the sources "Samples.SampleServer" and "Samples.SampleClient" // and use OTLP exporter. using var openTelemetry = Sdk.CreateTracerProviderBuilder() .AddSource("Samples.SampleClient", "Samples.SampleServer") .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("otlp-test")) - .AddOtlpExporter(opt => opt.Endpoint = endpoint) + .AddOtlpExporter(opt => opt.Endpoint = new Uri(endpoint)) .Build(); // The above line is required only in Applications diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/.publicApi/netstandard2.1/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/.publicApi/netstandard2.1/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..846802596aa --- /dev/null +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt @@ -0,0 +1,18 @@ +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporter +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporter.OtlpExporter(OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions options) -> void +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions.BatchExportProcessorOptions.get -> OpenTelemetry.BatchExportProcessorOptions +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions.BatchExportProcessorOptions.set -> void +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions.GrpcChannelOptions.get -> Grpc.Net.Client.GrpcChannelOptions +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions.GrpcChannelOptions.set -> void +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions.Endpoint.get -> System.Uri +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions.Endpoint.set -> void +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions.ExportProcessorType.set -> void +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions.Headers.get -> Grpc.Core.Metadata +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions.Headers.set -> void +OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporterOptions.OtlpExporterOptions() -> void +OpenTelemetry.Trace.OtlpExporterHelperExtensions +override OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporter.Export(in OpenTelemetry.Batch activityBatch) -> OpenTelemetry.ExportResult +override OpenTelemetry.Exporter.OpenTelemetryProtocol.OtlpExporter.OnShutdown(int timeoutMilliseconds) -> bool +static OpenTelemetry.Trace.OtlpExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Trace.TracerProviderBuilder diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index ec369cc8ee8..1b2ce181932 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -8,6 +8,13 @@ * In `OtlpExporterOptions.cs`: Exporter options now include a switch for Batch vs Simple exporter, and settings for batch exporting properties. +* Introduce a `netstandard2.1` build enabling the exporter to use the + [gRPC for .NET](https://github.com/grpc/grpc-dotnet) library instead of the + [gRPC for C#](https://github.com/grpc/grpc/tree/master/src/csharp) library + for .NET Core 3.0+ applications. This required some breaking changes to the + `OtlpExporterOptions`. + ([#1662](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1662)) + ## 1.0.0-rc1.1 Released 2020-Nov-17 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj index e265339da42..34067c518fa 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj @@ -1,14 +1,21 @@  - net452;net46;netstandard2.0 + net452;net46;netstandard2.0;netstandard2.1 OpenTelemetry protocol exporter for OpenTelemetry .NET $(PackageTags);OTLP + + + + + + + + - diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporter.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporter.cs index e875bf64dca..7352aaf8094 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporter.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporter.cs @@ -20,6 +20,9 @@ using System.Linq; using System.Threading.Tasks; using Grpc.Core; +#if NETSTANDARD2_1 +using Grpc.Net.Client; +#endif using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; using OpenTelemetry.Resources; using OtlpCollector = Opentelemetry.Proto.Collector.Trace.V1; @@ -37,7 +40,11 @@ public class OtlpExporter : BaseExporter private const string DefaultServiceName = "OpenTelemetry Exporter"; private readonly OtlpExporterOptions options; +#if NETSTANDARD2_1 + private readonly GrpcChannel channel; +#else private readonly Channel channel; +#endif private readonly OtlpCollector.TraceService.ITraceServiceClient traceClient; private readonly Metadata headers; @@ -65,7 +72,13 @@ internal OtlpExporter(OtlpExporterOptions options, OtlpCollector.TraceService.IT } else { +#if NETSTANDARD2_1 + this.channel = options.GrpcChannelOptions == default + ? GrpcChannel.ForAddress(options.Endpoint) + : GrpcChannel.ForAddress(options.Endpoint, options.GrpcChannelOptions); +#else this.channel = new Channel(options.Endpoint, options.Credentials, options.ChannelOptions); +#endif this.traceClient = new OtlpCollector.TraceService.TraceServiceClient(this.channel); } } @@ -80,6 +93,9 @@ public override ExportResult Export(in Batch activityBatch) this.SetResource(this.ParentProvider.GetResource()); } + // Prevents the exporter's gRPC and HTTP operations from being instrumented. + using var scope = SuppressInstrumentationScope.Begin(); + OtlpCollector.ExportTraceServiceRequest request = new OtlpCollector.ExportTraceServiceRequest(); request.AddBatch(this.ProcessResource, activityBatch); diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs index 694fdbd82a7..a0cbdf4ec8c 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs @@ -14,9 +14,13 @@ // limitations under the License. // +using System; using System.Collections.Generic; using System.Diagnostics; using Grpc.Core; +#if NETSTANDARD2_1 +using Grpc.Net.Client; +#endif namespace OpenTelemetry.Exporter.OpenTelemetryProtocol { @@ -25,12 +29,26 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol /// public class OtlpExporterOptions { +#if NETSTANDARD2_1 + /// + /// Gets or sets the target to which the exporter is going to send traces or metrics. + /// The valid syntax is described at https://github.com/grpc/grpc/blob/master/doc/naming.md. + /// + public Uri Endpoint { get; set; } = new Uri("http://localhost:55680"); +#else /// /// Gets or sets the target to which the exporter is going to send traces or metrics. /// The valid syntax is described at https://github.com/grpc/grpc/blob/master/doc/naming.md. /// public string Endpoint { get; set; } = "localhost:55680"; +#endif +#if NETSTANDARD2_1 + /// + /// Gets or sets the gRPC channel options. + /// + public GrpcChannelOptions GrpcChannelOptions { get; set; } +#else /// /// Gets or sets the client-side channel credentials. Used for creation of a secure channel. /// The default is "insecure". See detais at https://grpc.io/docs/guides/auth/#credential-types. @@ -38,14 +56,15 @@ public class OtlpExporterOptions public ChannelCredentials Credentials { get; set; } = ChannelCredentials.Insecure; /// - /// Gets or sets optional headers for the connection. + /// Gets or sets the gRPC channel options. /// - public Metadata Headers { get; set; } = new Metadata(); + public IEnumerable ChannelOptions { get; set; } +#endif /// - /// Gets or sets the gRPC channel options. + /// Gets or sets optional headers for the connection. /// - public IEnumerable ChannelOptions { get; set; } + public Metadata Headers { get; set; } = new Metadata(); /// /// Gets or sets the export processor type to be used with the OpenTelemetry Protocol Exporter.