From 65ca360f9157b2c43484370410c5fc54cf62933f Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Thu, 18 Jul 2024 14:24:39 -0700 Subject: [PATCH 1/9] Scratch out ExportProcessorFactory. --- .../OtlpLogExporterHelperExtensions.cs | 13 +-- .../OtlpTraceExporterHelperExtensions.cs | 11 +-- src/OpenTelemetry/ConcurrencyModes.cs | 33 +++++++ src/OpenTelemetry/ExportProcessorFactory.cs | 87 +++++++++++++++++++ .../SimpleMultithreadedExportProcessor.cs | 32 +++++++ ...pleMultithreadedActivityExportProcessor.cs | 26 ++++++ 6 files changed, 186 insertions(+), 16 deletions(-) create mode 100644 src/OpenTelemetry/ConcurrencyModes.cs create mode 100644 src/OpenTelemetry/ExportProcessorFactory.cs create mode 100644 src/OpenTelemetry/SimpleMultithreadedExportProcessor.cs create mode 100644 src/OpenTelemetry/Trace/Processor/SimpleMultithreadedActivityExportProcessor.cs diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs index 42faf425356..d4d6ec6685a 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs @@ -317,18 +317,13 @@ internal static BaseProcessor BuildOtlpLogExporter( if (processorOptions!.ExportProcessorType == ExportProcessorType.Simple) { - return new SimpleLogRecordExportProcessor(otlpExporter); + return ExportProcessorFactory.CreateSimpleExportProcessor(otlpExporter); } else { - var batchOptions = processorOptions.BatchExportProcessorOptions; - - return new BatchLogRecordExportProcessor( - otlpExporter, - batchOptions.MaxQueueSize, - batchOptions.ScheduledDelayMilliseconds, - batchOptions.ExporterTimeoutMilliseconds, - batchOptions.MaxExportBatchSize); + return ExportProcessorFactory.CreateBatchExportProcessor( + processorOptions.BatchExportProcessorOptions, + otlpExporter); } } diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs index 3a18b3da423..0389d48a05b 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs @@ -145,16 +145,13 @@ internal static BaseProcessor BuildOtlpExporterProcessor( if (exportProcessorType == ExportProcessorType.Simple) { - return new SimpleActivityExportProcessor(otlpExporter); + return ExportProcessorFactory.CreateSimpleExportProcessor(otlpExporter); } else { - return new BatchActivityExportProcessor( - otlpExporter, - batchExportProcessorOptions!.MaxQueueSize, - batchExportProcessorOptions.ScheduledDelayMilliseconds, - batchExportProcessorOptions.ExporterTimeoutMilliseconds, - batchExportProcessorOptions.MaxExportBatchSize); + return ExportProcessorFactory.CreateBatchExportProcessor( + batchExportProcessorOptions!, + otlpExporter); } } } diff --git a/src/OpenTelemetry/ConcurrencyModes.cs b/src/OpenTelemetry/ConcurrencyModes.cs new file mode 100644 index 00000000000..6bdbdba448d --- /dev/null +++ b/src/OpenTelemetry/ConcurrencyModes.cs @@ -0,0 +1,33 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +namespace OpenTelemetry; + +[Flags] +public enum ConcurrencyModes : byte +{ + /* + 0 0 0 0 0 0 0 0 + | | | | | | | | + | | | | | | | +--- Reentrant + | | | | | | +----- Multithreaded + | | | | | +------- (reserved) + | | | | +--------- (reserved) + | | | +----------- (reserved) + | | +------------- (reserved) + | +--------------- (reserved) + +----------------- (reserved) + */ + + /// + /// Reentrant, the component can be invoked recursively without resulting + /// a deadlock or infinite loop. + /// + Reentrant = 0b1, + + /// + /// Multithreaded, the component can be invoked concurrently across + /// multiple threads. + /// + Multithreaded = 0b10, +} diff --git a/src/OpenTelemetry/ExportProcessorFactory.cs b/src/OpenTelemetry/ExportProcessorFactory.cs new file mode 100644 index 00000000000..5e59845b07b --- /dev/null +++ b/src/OpenTelemetry/ExportProcessorFactory.cs @@ -0,0 +1,87 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using System.Diagnostics; +using OpenTelemetry.Internal; +using OpenTelemetry.Logs; +using OpenTelemetry.Trace; + +namespace OpenTelemetry; + +public static class ExportProcessorFactory + where T : class +{ + public static BaseExportProcessor CreateBatchExportProcessor( + BatchExportProcessorOptions options, + BaseExporter exporter) + { + Guard.ThrowIfNull(options); + Guard.ThrowIfNull(exporter); + + if (typeof(T) == typeof(Activity)) + { + return (BaseExportProcessor)(object)new BatchActivityExportProcessor( + (BaseExporter)(object)exporter, + options.MaxQueueSize, + options.ScheduledDelayMilliseconds, + options.ExporterTimeoutMilliseconds, + options.MaxExportBatchSize); + } + else if (typeof(T) == typeof(LogRecord)) + { + return (BaseExportProcessor)(object)new BatchLogRecordExportProcessor( + (BaseExporter)(object)exporter, + options.MaxQueueSize, + options.ScheduledDelayMilliseconds, + options.ExporterTimeoutMilliseconds, + options.MaxExportBatchSize); + } + else + { + throw new NotSupportedException($"Building batch export processors for type '{typeof(T)}' is not supported"); + } + } + + public static BaseExportProcessor CreateSimpleExportProcessor( + BaseExporter exporter, + ConcurrencyModes concurrencyMode = ConcurrencyModes.Reentrant) + { + Guard.ThrowIfNull(exporter); + + if (!concurrencyMode.HasFlag(ConcurrencyModes.Reentrant)) + { + throw new NotSupportedException("Non-reentrant simple export processors are not currently supported."); + } + + if (typeof(T) == typeof(Activity)) + { + if (concurrencyMode.HasFlag(ConcurrencyModes.Multithreaded)) + { + return (BaseExportProcessor)(object)new SimpleMultithreadedActivityExportProcessor( + (BaseExporter)(object)exporter); + } + else + { + return (BaseExportProcessor)(object)new SimpleActivityExportProcessor( + (BaseExporter)(object)exporter); + } + } + else if (typeof(T) == typeof(LogRecord)) + { + if (concurrencyMode.HasFlag(ConcurrencyModes.Multithreaded)) + { + return (BaseExportProcessor)(object)new SimpleMultithreadedExportProcessor( + (BaseExporter)(object)exporter); + } + else + { + return (BaseExportProcessor)(object)new SimpleLogRecordExportProcessor( + (BaseExporter)(object)exporter); + } + } + else + { + throw new NotSupportedException($"Building simple export processors for type '{typeof(T)}' is not supported"); + } + } +} diff --git a/src/OpenTelemetry/SimpleMultithreadedExportProcessor.cs b/src/OpenTelemetry/SimpleMultithreadedExportProcessor.cs new file mode 100644 index 00000000000..c33299cbba5 --- /dev/null +++ b/src/OpenTelemetry/SimpleMultithreadedExportProcessor.cs @@ -0,0 +1,32 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using OpenTelemetry.Internal; + +namespace OpenTelemetry; + +internal class SimpleMultithreadedExportProcessor : BaseExportProcessor + where T : class +{ + /// + /// Initializes a new instance of the class. + /// + /// Exporter instance. + public SimpleMultithreadedExportProcessor(BaseExporter exporter) + : base(exporter) + { + } + + /// + protected override void OnExport(T data) + { + try + { + this.exporter.Export(new Batch(data)); + } + catch (Exception ex) + { + OpenTelemetrySdkEventSource.Log.SpanProcessorException(nameof(this.OnExport), ex); + } + } +} diff --git a/src/OpenTelemetry/Trace/Processor/SimpleMultithreadedActivityExportProcessor.cs b/src/OpenTelemetry/Trace/Processor/SimpleMultithreadedActivityExportProcessor.cs new file mode 100644 index 00000000000..6b34219cd37 --- /dev/null +++ b/src/OpenTelemetry/Trace/Processor/SimpleMultithreadedActivityExportProcessor.cs @@ -0,0 +1,26 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using System.Diagnostics; + +namespace OpenTelemetry.Trace; + +internal sealed class SimpleMultithreadedActivityExportProcessor : SimpleMultithreadedExportProcessor +{ + public SimpleMultithreadedActivityExportProcessor( + BaseExporter exporter) + : base(exporter) + { + } + + /// + protected override void OnExport(Activity data) + { + if (!data.Recorded) + { + return; + } + + base.OnExport(data); + } +} From 114b8ee10170a5bb1f92ec100af0dafe7a2dce91 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Mon, 22 Jul 2024 15:21:11 -0700 Subject: [PATCH 2/9] Updates. --- .../extending-the-sdk/LoggerExtensions.cs | 18 -- .../extending-the-sdk/MyExporterExtensions.cs | 39 +++++ docs/logs/extending-the-sdk/README.md | 11 +- docs/trace/customizing-the-sdk/README.md | 34 ++-- .../extending-the-sdk/MyExporterExtensions.cs | 18 +- docs/trace/extending-the-sdk/README.md | 5 + .../ConsoleExporterHelperExtensions.cs | 14 +- .../ConsoleExporterLoggingExtensions.cs | 15 +- .../InMemoryExporterHelperExtensions.cs | 3 +- .../InMemoryExporterLoggingExtensions.cs | 9 +- .../Builder/OtlpExporterBuilder.cs | 27 +-- .../OtlpLogExporterHelperExtensions.cs | 55 +++--- .../OtlpTraceExporterHelperExtensions.cs | 58 ++++--- .../ZipkinExporterHelperExtensions.cs | 56 ++++--- .../BatchExportProcessorOptions.cs | 20 +++ src/OpenTelemetry/ConcurrencyModes.cs | 5 +- .../ConcurrencyModesAttribute.cs | 27 +++ src/OpenTelemetry/ExportProcessorFactory.cs | 87 ---------- .../LoggerProviderBuilderExtensions.cs | 157 ++++++++++++++++++ .../ILogger/OpenTelemetryLoggerOptions.cs | 33 +++- .../ILogger/OpenTelemetryLoggingExtensions.cs | 3 + .../LogRecordExportProcessorFactory.cs | 54 ++++++ .../LogRecordExportProcessorOptions.cs | 3 + .../TracerProviderBuilderExtensions.cs | 157 ++++++++++++++++++ .../ActivityExportProcessorFactory.cs | 55 ++++++ .../ActivityExportProcessorOptions.cs | 3 + .../IntegrationTest/IntegrationTests.cs | 29 ++-- 27 files changed, 754 insertions(+), 241 deletions(-) delete mode 100644 docs/logs/extending-the-sdk/LoggerExtensions.cs create mode 100644 docs/logs/extending-the-sdk/MyExporterExtensions.cs create mode 100644 src/OpenTelemetry/ConcurrencyModesAttribute.cs delete mode 100644 src/OpenTelemetry/ExportProcessorFactory.cs create mode 100644 src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorFactory.cs create mode 100644 src/OpenTelemetry/Trace/Processor/ActivityExportProcessorFactory.cs diff --git a/docs/logs/extending-the-sdk/LoggerExtensions.cs b/docs/logs/extending-the-sdk/LoggerExtensions.cs deleted file mode 100644 index 7476d833334..00000000000 --- a/docs/logs/extending-the-sdk/LoggerExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -using OpenTelemetry; -using OpenTelemetry.Logs; - -internal static class LoggerExtensions -{ - public static OpenTelemetryLoggerOptions AddMyExporter(this OpenTelemetryLoggerOptions options) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - return options.AddProcessor(new BatchLogRecordExportProcessor(new MyExporter())); - } -} diff --git a/docs/logs/extending-the-sdk/MyExporterExtensions.cs b/docs/logs/extending-the-sdk/MyExporterExtensions.cs new file mode 100644 index 00000000000..d257f8d920b --- /dev/null +++ b/docs/logs/extending-the-sdk/MyExporterExtensions.cs @@ -0,0 +1,39 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using OpenTelemetry.Logs; + +internal static class MyExporterExtensions +{ + public static LoggerProviderBuilder AddMyExporter( + this LoggerProviderBuilder builder) + => AddMyExporter(builder, name: null); + + public static LoggerProviderBuilder AddMyExporter( + this LoggerProviderBuilder builder, + string? name) + { + return builder.AddBatchExportProcessor( + name, + new MyExporter()); + } + + public static OpenTelemetryLoggerOptions AddMyExporter( + this OpenTelemetryLoggerOptions options) + => AddMyExporter(options, name: null); + + public static OpenTelemetryLoggerOptions AddMyExporter( + this OpenTelemetryLoggerOptions options, + string? name) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + ((IDeferredLoggerProviderBuilder)options).Configure( + (sp, builder) => builder.AddBatchExportProcessor(name, new MyExporter())); + + return options; + } +} diff --git a/docs/logs/extending-the-sdk/README.md b/docs/logs/extending-the-sdk/README.md index 55ea13dfaf4..0eeacc528fc 100644 --- a/docs/logs/extending-the-sdk/README.md +++ b/docs/logs/extending-the-sdk/README.md @@ -53,8 +53,10 @@ A demo exporter which simply writes log records to the console is shown [here](./MyExporter.cs). Apart from the exporter itself, you should also provide extension methods as -shown [here](./LoggerExtensions.cs). This allows users to add the Exporter to -the `OpenTelemetryLoggerOptions` as shown in the example [here](./Program.cs). +shown [here](./MyExporterExtensions.cs). This allows users to add the exporter +to the `OpenTelemetryLoggerOptions` (as shown in the example +[here](./Program.cs)) or to a `LoggerProviderBuilder` using the `WithLogging` +extension in `OpenTelemetry.Extensions.Hosting`. ## Processor @@ -64,6 +66,11 @@ OpenTelemetry .NET SDK has provided the following built-in processors: * [CompositeProcessor<T>](../../../src/OpenTelemetry/CompositeProcessor.cs) * [SimpleExportProcessor<T>](../../../src/OpenTelemetry/SimpleExportProcessor.cs) +> [!NOTE] +> As of `1.10.0` it is recommended to use the `LoggerProviderBuilder` +> `AddBatchExportProcessor` or `AddSimpleExportProcessor` helper extension +> methods to create batch and/or simple processors. + Custom processors can be implemented to cover more scenarios: * Processors should inherit from `OpenTelemetry.BaseProcessor` (which diff --git a/docs/trace/customizing-the-sdk/README.md b/docs/trace/customizing-the-sdk/README.md index d78ed1cd569..64d7411d858 100644 --- a/docs/trace/customizing-the-sdk/README.md +++ b/docs/trace/customizing-the-sdk/README.md @@ -253,18 +253,32 @@ writing custom processors. #### Exporter Configuration -The snippet below shows how to add export processors to the provider before it +The snippets below shows how to add export processors to the provider before it is built. -```csharp -using OpenTelemetry; -using OpenTelemetry.Trace; - -var tracerProvider = Sdk.CreateTracerProviderBuilder() - .AddProcessor(new BatchActivityExportProcessor(new MyExporter1())) - .AddProcessor(new SimpleActivityExportProcessor(new MyExporter2())) - .Build(); -``` +* Using 1.10.0 or newer + + ```csharp + using OpenTelemetry; + using OpenTelemetry.Trace; + + var tracerProvider = Sdk.CreateTracerProviderBuilder() + .AddBatchExportProcessor(new MyExporter1()) + .AddSimpleExportProcessor(new MyExporter2()) + .Build(); + ``` + +* Using 1.9.0 or older + + ```csharp + using OpenTelemetry; + using OpenTelemetry.Trace; + + var tracerProvider = Sdk.CreateTracerProviderBuilder() + .AddProcessor(new BatchActivityExportProcessor(new MyExporter1())) + .AddProcessor(new SimpleActivityExportProcessor(new MyExporter2())) + .Build(); + ``` It is also common for exporters to provide their own extensions to simplify registration. The snippet below shows how to add the diff --git a/docs/trace/extending-the-sdk/MyExporterExtensions.cs b/docs/trace/extending-the-sdk/MyExporterExtensions.cs index b317591fc5f..43306605790 100644 --- a/docs/trace/extending-the-sdk/MyExporterExtensions.cs +++ b/docs/trace/extending-the-sdk/MyExporterExtensions.cs @@ -1,18 +1,20 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -using OpenTelemetry; using OpenTelemetry.Trace; internal static class MyExporterExtensions { - public static TracerProviderBuilder AddMyExporter(this TracerProviderBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } + public static TracerProviderBuilder AddMyExporter( + this TracerProviderBuilder builder) + => AddMyExporter(builder, name: null); - return builder.AddProcessor(new BatchActivityExportProcessor(new MyExporter())); + public static TracerProviderBuilder AddMyExporter( + this TracerProviderBuilder builder, + string? name) + { + return builder.AddBatchExportProcessor( + name, + new MyExporter()); } } diff --git a/docs/trace/extending-the-sdk/README.md b/docs/trace/extending-the-sdk/README.md index 00f72ddec09..d6e46894702 100644 --- a/docs/trace/extending-the-sdk/README.md +++ b/docs/trace/extending-the-sdk/README.md @@ -244,6 +244,11 @@ OpenTelemetry .NET SDK has provided the following built-in processors: * [CompositeProcessor<T>](../../../src/OpenTelemetry/CompositeProcessor.cs) * [SimpleExportProcessor<T>](../../../src/OpenTelemetry/SimpleExportProcessor.cs) +> [!NOTE] +> As of `1.10.0` it is recommended to use the `TracerProviderBuilder` +> `AddBatchExportProcessor` or `AddSimpleExportProcessor` helper extension +> methods to create batch and/or simple processors. + Custom processors can be implemented to cover more scenarios: * Processors should inherit from `OpenTelemetry.BaseProcessor` (which diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs index b79aa0d9ed9..8479c80fcb2 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs @@ -48,11 +48,13 @@ public static TracerProviderBuilder AddConsoleExporter( builder.ConfigureServices(services => services.Configure(name, configure)); } - return builder.AddProcessor(sp => - { - var options = sp.GetRequiredService>().Get(name); - - return new SimpleActivityExportProcessor(new ConsoleActivityExporter(options)); - }); + return builder.AddSimpleExportProcessor( + name, + static (sp, name) => + { + var options = sp.GetRequiredService>().Get(name); + + return new ConsoleActivityExporter(options); + }); } } diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleExporterLoggingExtensions.cs b/src/OpenTelemetry.Exporter.Console/ConsoleExporterLoggingExtensions.cs index 80c767343b7..bd357182764 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleExporterLoggingExtensions.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleExporterLoggingExtensions.cs @@ -73,14 +73,17 @@ public static LoggerProviderBuilder AddConsoleExporter( if (configure != null) { - loggerProviderBuilder.ConfigureServices(services => services.Configure(name, configure)); + loggerProviderBuilder.ConfigureServices( + services => services.Configure(name, configure)); } - return loggerProviderBuilder.AddProcessor(sp => - { - var options = sp.GetRequiredService>().Get(name); + return loggerProviderBuilder.AddSimpleExportProcessor( + name, + static (sp, name) => + { + var options = sp.GetRequiredService>().Get(name); - return new SimpleLogRecordExportProcessor(new ConsoleLogRecordExporter(options)); - }); + return new ConsoleLogRecordExporter(options); + }); } } diff --git a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterHelperExtensions.cs index 3940a846bc3..475052dfe61 100644 --- a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterHelperExtensions.cs @@ -20,6 +20,7 @@ public static TracerProviderBuilder AddInMemoryExporter(this TracerProviderBuild Guard.ThrowIfNull(builder); Guard.ThrowIfNull(exportedItems); - return builder.AddProcessor(new SimpleActivityExportProcessor(new InMemoryExporter(exportedItems))); + return builder.AddSimpleExportProcessor( + new InMemoryExporter(exportedItems)); } } diff --git a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterLoggingExtensions.cs b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterLoggingExtensions.cs index 19b2079921e..dfd0bc1a4b1 100644 --- a/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterLoggingExtensions.cs +++ b/src/OpenTelemetry.Exporter.InMemory/InMemoryExporterLoggingExtensions.cs @@ -24,8 +24,10 @@ public static OpenTelemetryLoggerOptions AddInMemoryExporter( var logExporter = BuildExporter(exportedItems); - return loggerOptions.AddProcessor( - new SimpleLogRecordExportProcessor(logExporter)); + ((IDeferredLoggerProviderBuilder)loggerOptions).Configure( + (sp, builder) => builder.AddSimpleExportProcessor(logExporter)); + + return loggerOptions; } /// @@ -43,8 +45,7 @@ public static LoggerProviderBuilder AddInMemoryExporter( var logExporter = BuildExporter(exportedItems); - return loggerProviderBuilder.AddProcessor( - new SimpleLogRecordExportProcessor(logExporter)); + return loggerProviderBuilder.AddSimpleExportProcessor(logExporter); } private static InMemoryExporter BuildExporter(ICollection exportedItems) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs index e20062b0e9e..be8a6e4fdfe 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs @@ -200,17 +200,19 @@ there but that may change in the future so it is handled { var builderOptions = GetBuilderOptionsAndValidateRegistrations(sp, name!); - var processor = OtlpLogExporterHelperExtensions.BuildOtlpLogExporter( + var processorOptions = builderOptions.LogRecordExportProcessorOptions + ?? throw new InvalidOperationException("LogRecordExportProcessorOptions were missing with logging enabled"); + + processorOptions.PipelineWeight = DefaultProcessorPipelineWeight; + + OtlpLogExporterHelperExtensions.AddOtlpLogExporter( sp, + logging, builderOptions.LoggingOptionsInstance.ApplyDefaults(builderOptions.DefaultOptionsInstance), - builderOptions.LogRecordExportProcessorOptions ?? throw new InvalidOperationException("LogRecordExportProcessorOptions were missing with logging enabled"), builderOptions.SdkLimitOptions, builderOptions.ExperimentalOptions, + processorOptions.ExportProcessorType, skipUseOtlpExporterRegistrationCheck: true); - - processor.PipelineWeight = DefaultProcessorPipelineWeight; - - logging.AddProcessor(processor); }); services!.ConfigureOpenTelemetryMeterProvider( @@ -232,20 +234,19 @@ there but that may change in the future so it is handled { var builderOptions = GetBuilderOptionsAndValidateRegistrations(sp, name!); - var processorOptions = builderOptions.ActivityExportProcessorOptions ?? throw new InvalidOperationException("ActivityExportProcessorOptions were missing with tracing enabled"); + var processorOptions = builderOptions.ActivityExportProcessorOptions + ?? throw new InvalidOperationException("ActivityExportProcessorOptions were missing with tracing enabled"); + + processorOptions.PipelineWeight = DefaultProcessorPipelineWeight; - var processor = OtlpTraceExporterHelperExtensions.BuildOtlpExporterProcessor( + OtlpTraceExporterHelperExtensions.AddOtlpTraceExporter( sp, + tracing, builderOptions.TracingOptionsInstance.ApplyDefaults(builderOptions.DefaultOptionsInstance), builderOptions.SdkLimitOptions, builderOptions.ExperimentalOptions, processorOptions.ExportProcessorType, - processorOptions.BatchExportProcessorOptions, skipUseOtlpExporterRegistrationCheck: true); - - processor.PipelineWeight = DefaultProcessorPipelineWeight; - - tracing.AddProcessor(processor); }); static OtlpExporterBuilderOptions GetBuilderOptionsAndValidateRegistrations(IServiceProvider sp, string name) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs index d4d6ec6685a..adf0c819c9c 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs @@ -56,7 +56,7 @@ public static OpenTelemetryLoggerOptions AddOtlpExporter( var finalOptionsName = name ?? Options.DefaultName; - return loggerOptions.AddProcessor(sp => + ((IDeferredLoggerProviderBuilder)loggerOptions).Configure((sp, builder) => { var exporterOptions = GetOptions(sp, name, finalOptionsName, OtlpExporterOptions.CreateOtlpExporterOptions); @@ -64,13 +64,16 @@ public static OpenTelemetryLoggerOptions AddOtlpExporter( configure?.Invoke(exporterOptions); - return BuildOtlpLogExporter( + AddOtlpLogExporter( sp, + builder, exporterOptions, - processorOptions, GetOptions(sp, Options.DefaultName, Options.DefaultName, (sp, c, n) => new SdkLimitOptions(c)), - GetOptions(sp, name, finalOptionsName, (sp, c, n) => new ExperimentalOptions(c))); + GetOptions(sp, name, finalOptionsName, (sp, c, n) => new ExperimentalOptions(c)), + processorOptions.ExportProcessorType); }); + + return loggerOptions; } /// @@ -102,7 +105,7 @@ public static OpenTelemetryLoggerOptions AddOtlpExporter( var finalOptionsName = name ?? Options.DefaultName; - return loggerOptions.AddProcessor(sp => + ((IDeferredLoggerProviderBuilder)loggerOptions).Configure((sp, builder) => { var exporterOptions = GetOptions(sp, name, finalOptionsName, OtlpExporterOptions.CreateOtlpExporterOptions); @@ -110,13 +113,16 @@ public static OpenTelemetryLoggerOptions AddOtlpExporter( configureExporterAndProcessor?.Invoke(exporterOptions, processorOptions); - return BuildOtlpLogExporter( + AddOtlpLogExporter( sp, + builder, exporterOptions, - processorOptions, GetOptions(sp, Options.DefaultName, Options.DefaultName, (sp, c, n) => new SdkLimitOptions(c)), - GetOptions(sp, name, finalOptionsName, (sp, c, n) => new ExperimentalOptions(c))); + GetOptions(sp, name, finalOptionsName, (sp, c, n) => new ExperimentalOptions(c)), + processorOptions.ExportProcessorType); }); + + return loggerOptions; } /// @@ -173,7 +179,7 @@ public static LoggerProviderBuilder AddOtlpExporter( services.AddOtlpExporterLoggingServices(); }); - return builder.AddProcessor(sp => + return builder.ConfigureBuilder((sp, builder) => { OtlpExporterOptions exporterOptions; @@ -202,12 +208,13 @@ public static LoggerProviderBuilder AddOtlpExporter( // instance. var sdkLimitOptions = sp.GetRequiredService>().CurrentValue; - return BuildOtlpLogExporter( + AddOtlpLogExporter( sp, + builder, exporterOptions, - sp.GetRequiredService>().Get(finalOptionsName), sdkLimitOptions, - sp.GetRequiredService>().Get(finalOptionsName)); + sp.GetRequiredService>().Get(finalOptionsName), + sp.GetRequiredService>().Get(finalOptionsName).ExportProcessorType); }); } @@ -229,7 +236,7 @@ public static LoggerProviderBuilder AddOtlpExporter( builder.ConfigureServices(services => services.AddOtlpExporterLoggingServices()); - return builder.AddProcessor(sp => + return builder.ConfigureBuilder((sp, builder) => { OtlpExporterOptions exporterOptions; @@ -260,27 +267,29 @@ public static LoggerProviderBuilder AddOtlpExporter( // instance. var sdkLimitOptions = sp.GetRequiredService>().CurrentValue; - return BuildOtlpLogExporter( + AddOtlpLogExporter( sp, + builder, exporterOptions, - processorOptions, sdkLimitOptions, - sp.GetRequiredService>().Get(finalOptionsName)); + sp.GetRequiredService>().Get(finalOptionsName), + processorOptions.ExportProcessorType); }); } - internal static BaseProcessor BuildOtlpLogExporter( + internal static void AddOtlpLogExporter( IServiceProvider serviceProvider, + LoggerProviderBuilder builder, OtlpExporterOptions exporterOptions, - LogRecordExportProcessorOptions processorOptions, SdkLimitOptions sdkLimitOptions, ExperimentalOptions experimentalOptions, + ExportProcessorType exportProcessorType, bool skipUseOtlpExporterRegistrationCheck = false, Func, BaseExporter>? configureExporterInstance = null) { Debug.Assert(serviceProvider != null, "serviceProvider was null"); + Debug.Assert(builder != null, "builder was null"); Debug.Assert(exporterOptions != null, "exporterOptions was null"); - Debug.Assert(processorOptions != null, "processorOptions was null"); Debug.Assert(sdkLimitOptions != null, "sdkLimitOptions was null"); Debug.Assert(experimentalOptions != null, "experimentalOptions was null"); @@ -315,15 +324,13 @@ internal static BaseProcessor BuildOtlpLogExporter( otlpExporter = configureExporterInstance(otlpExporter); } - if (processorOptions!.ExportProcessorType == ExportProcessorType.Simple) + if (exportProcessorType == ExportProcessorType.Simple) { - return ExportProcessorFactory.CreateSimpleExportProcessor(otlpExporter); + builder!.AddSimpleExportProcessor(otlpExporter); } else { - return ExportProcessorFactory.CreateBatchExportProcessor( - processorOptions.BatchExportProcessorOptions, - otlpExporter); + builder!.AddBatchExportProcessor(otlpExporter); } } diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs index 0389d48a05b..59edb13fc49 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs @@ -58,9 +58,31 @@ public static TracerProviderBuilder AddOtlpExporter( } services.AddOtlpExporterTracingServices(); + + services + .AddOptions(name) + .Configure>( + (exporterOptions, batchOptionsMonitor) => + { + var defaultBatchOptions = batchOptionsMonitor.Get(name); + + var exporterBatchOptions = exporterOptions.BatchExportProcessorOptions; + if (exporterBatchOptions != null + && exporterBatchOptions != defaultBatchOptions) + { + // Note: By default + // OtlpExporterOptions.BatchExportProcessorOptions + // is set to BatchExportActivityProcessorOptions + // retrieved from DI. But users may change it via + // public setter so this code makes sure any changes + // are reflected on the DI instance so the call to + // AddBatchExportProcessor picks them up. + exporterBatchOptions.ApplyTo(defaultBatchOptions); + } + }); }); - return builder.AddProcessor(sp => + return builder.ConfigureBuilder((sp, builder) => { OtlpExporterOptions exporterOptions; @@ -89,45 +111,31 @@ public static TracerProviderBuilder AddOtlpExporter( // instance. var sdkLimitOptions = sp.GetRequiredService>().CurrentValue; - return BuildOtlpExporterProcessor( + AddOtlpTraceExporter( sp, + builder, exporterOptions, sdkLimitOptions, - sp.GetRequiredService>().Get(finalOptionsName)); + sp.GetRequiredService>().Get(finalOptionsName), + exporterOptions.ExportProcessorType); }); } - internal static BaseProcessor BuildOtlpExporterProcessor( - IServiceProvider serviceProvider, - OtlpExporterOptions exporterOptions, - SdkLimitOptions sdkLimitOptions, - ExperimentalOptions experimentalOptions, - Func, BaseExporter>? configureExporterInstance = null) - => BuildOtlpExporterProcessor( - serviceProvider, - exporterOptions, - sdkLimitOptions, - experimentalOptions, - exporterOptions.ExportProcessorType, - exporterOptions.BatchExportProcessorOptions ?? new BatchExportActivityProcessorOptions(), - skipUseOtlpExporterRegistrationCheck: false, - configureExporterInstance: configureExporterInstance); - - internal static BaseProcessor BuildOtlpExporterProcessor( + internal static void AddOtlpTraceExporter( IServiceProvider serviceProvider, + TracerProviderBuilder builder, OtlpExporterOptions exporterOptions, SdkLimitOptions sdkLimitOptions, ExperimentalOptions experimentalOptions, ExportProcessorType exportProcessorType, - BatchExportProcessorOptions batchExportProcessorOptions, bool skipUseOtlpExporterRegistrationCheck = false, Func, BaseExporter>? configureExporterInstance = null) { Debug.Assert(serviceProvider != null, "serviceProvider was null"); + Debug.Assert(builder != null, "builder was null"); Debug.Assert(exporterOptions != null, "exporterOptions was null"); Debug.Assert(sdkLimitOptions != null, "sdkLimitOptions was null"); Debug.Assert(experimentalOptions != null, "experimentalOptions was null"); - Debug.Assert(batchExportProcessorOptions != null, "batchExportProcessorOptions was null"); if (!skipUseOtlpExporterRegistrationCheck) { @@ -145,13 +153,11 @@ internal static BaseProcessor BuildOtlpExporterProcessor( if (exportProcessorType == ExportProcessorType.Simple) { - return ExportProcessorFactory.CreateSimpleExportProcessor(otlpExporter); + builder!.AddSimpleExportProcessor(otlpExporter); } else { - return ExportProcessorFactory.CreateBatchExportProcessor( - batchExportProcessorOptions!, - otlpExporter); + builder!.AddBatchExportProcessor(otlpExporter); } } } diff --git a/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs index ca858c649ab..a81fb8b9fec 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs @@ -4,7 +4,6 @@ #if NETFRAMEWORK using System.Net.Http; #endif -using System.Diagnostics; using System.Reflection; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -51,7 +50,7 @@ public static TracerProviderBuilder AddZipkinExporter( name ??= Options.DefaultName; - builder.ConfigureServices(services => + return builder.ConfigureServices(services => { if (configure != null) { @@ -62,24 +61,44 @@ public static TracerProviderBuilder AddZipkinExporter( (sp, configuration, name) => new ZipkinExporterOptions( configuration, sp.GetRequiredService>().Get(name))); - }); - return builder.AddProcessor(sp => - { - var options = sp.GetRequiredService>().Get(name); + services + .AddOptions(name) + .Configure>( + (exporterOptions, batchOptionsMonitor) => + { + var defaultBatchOptions = batchOptionsMonitor.Get(name); - return BuildZipkinExporterProcessor(builder, options, sp); + var exporterBatchOptions = exporterOptions.BatchExportProcessorOptions; + if (exporterBatchOptions != null + && exporterBatchOptions != defaultBatchOptions) + { + // Note: By default + // ZipkinExporterOptions.BatchExportProcessorOptions is + // set to BatchExportActivityProcessorOptions retrieved + // from DI. But users may change it via public setter so + // this code makes sure any changes are reflected on the + // DI instance so the call to AddBatchExportProcessor + // picks them up. + exporterBatchOptions.ApplyTo(defaultBatchOptions); + } + }); + + services.ConfigureOpenTelemetryTracerProvider( + (sp, builder) => AddZipkinExporter(sp, builder, name)); }); } - private static BaseProcessor BuildZipkinExporterProcessor( + private static void AddZipkinExporter( + IServiceProvider serviceProvider, TracerProviderBuilder builder, - ZipkinExporterOptions options, - IServiceProvider serviceProvider) + string name) { - if (options.HttpClientFactory == ZipkinExporterOptions.DefaultHttpClientFactory) + var exporterOptions = serviceProvider.GetRequiredService>().Get(name); + + if (exporterOptions.HttpClientFactory == ZipkinExporterOptions.DefaultHttpClientFactory) { - options.HttpClientFactory = () => + exporterOptions.HttpClientFactory = () => { Type httpClientFactoryType = Type.GetType("System.Net.Http.IHttpClientFactory, Microsoft.Extensions.Http", throwOnError: false); if (httpClientFactoryType != null) @@ -104,20 +123,15 @@ private static BaseProcessor BuildZipkinExporterProcessor( }; } - var zipkinExporter = new ZipkinExporter(options); + var zipkinExporter = new ZipkinExporter(exporterOptions); - if (options.ExportProcessorType == ExportProcessorType.Simple) + if (exporterOptions.ExportProcessorType == ExportProcessorType.Simple) { - return new SimpleActivityExportProcessor(zipkinExporter); + builder.AddSimpleExportProcessor(zipkinExporter); } else { - return new BatchActivityExportProcessor( - zipkinExporter, - options.BatchExportProcessorOptions.MaxQueueSize, - options.BatchExportProcessorOptions.ScheduledDelayMilliseconds, - options.BatchExportProcessorOptions.ExporterTimeoutMilliseconds, - options.BatchExportProcessorOptions.MaxExportBatchSize); + builder.AddBatchExportProcessor(zipkinExporter); } } } diff --git a/src/OpenTelemetry/BatchExportProcessorOptions.cs b/src/OpenTelemetry/BatchExportProcessorOptions.cs index 67345e9715c..a3611b24247 100644 --- a/src/OpenTelemetry/BatchExportProcessorOptions.cs +++ b/src/OpenTelemetry/BatchExportProcessorOptions.cs @@ -1,6 +1,8 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +using OpenTelemetry.Internal; + namespace OpenTelemetry; /// @@ -29,4 +31,22 @@ public class BatchExportProcessorOptions /// Gets or sets the maximum batch size of every export. It must be smaller or equal to MaxQueueLength. The default value is 512. /// public int MaxExportBatchSize { get; set; } = BatchExportProcessor.DefaultMaxExportBatchSize; + + /// + /// Applies the settings for the current instance onto another instance. + /// + /// . + public void ApplyTo(BatchExportProcessorOptions other) + { + Guard.ThrowIfNull(other); + + if (other != this) + { + other.MaxQueueSize = this.MaxQueueSize; + other.ScheduledDelayMilliseconds = this.ScheduledDelayMilliseconds; + other.ExporterTimeoutMilliseconds = this.ExporterTimeoutMilliseconds; + other.MaxExportBatchSize = this.MaxExportBatchSize; + } + } } diff --git a/src/OpenTelemetry/ConcurrencyModes.cs b/src/OpenTelemetry/ConcurrencyModes.cs index 6bdbdba448d..f7d7c6da1cd 100644 --- a/src/OpenTelemetry/ConcurrencyModes.cs +++ b/src/OpenTelemetry/ConcurrencyModes.cs @@ -1,8 +1,11 @@ -// Copyright The OpenTelemetry Authors +// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 namespace OpenTelemetry; +/// +/// Describes the concurrency mode of an OpenTelemetry component. +/// [Flags] public enum ConcurrencyModes : byte { diff --git a/src/OpenTelemetry/ConcurrencyModesAttribute.cs b/src/OpenTelemetry/ConcurrencyModesAttribute.cs new file mode 100644 index 00000000000..af1234789c7 --- /dev/null +++ b/src/OpenTelemetry/ConcurrencyModesAttribute.cs @@ -0,0 +1,27 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +namespace OpenTelemetry; + +/// +/// An attribute for declaring the supported of an OpenTelemetry component. +/// +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] +public sealed class ConcurrencyModesAttribute : Attribute +{ + private readonly ConcurrencyModes supportedConcurrencyModes; + + /// + /// Initializes a new instance of the class. + /// + /// . + public ConcurrencyModesAttribute(ConcurrencyModes supported) + { + this.supportedConcurrencyModes = supported; + } + + /// + /// Gets the supported . + /// + public ConcurrencyModes Supported => this.supportedConcurrencyModes; +} diff --git a/src/OpenTelemetry/ExportProcessorFactory.cs b/src/OpenTelemetry/ExportProcessorFactory.cs deleted file mode 100644 index 5e59845b07b..00000000000 --- a/src/OpenTelemetry/ExportProcessorFactory.cs +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -using System.Diagnostics; -using OpenTelemetry.Internal; -using OpenTelemetry.Logs; -using OpenTelemetry.Trace; - -namespace OpenTelemetry; - -public static class ExportProcessorFactory - where T : class -{ - public static BaseExportProcessor CreateBatchExportProcessor( - BatchExportProcessorOptions options, - BaseExporter exporter) - { - Guard.ThrowIfNull(options); - Guard.ThrowIfNull(exporter); - - if (typeof(T) == typeof(Activity)) - { - return (BaseExportProcessor)(object)new BatchActivityExportProcessor( - (BaseExporter)(object)exporter, - options.MaxQueueSize, - options.ScheduledDelayMilliseconds, - options.ExporterTimeoutMilliseconds, - options.MaxExportBatchSize); - } - else if (typeof(T) == typeof(LogRecord)) - { - return (BaseExportProcessor)(object)new BatchLogRecordExportProcessor( - (BaseExporter)(object)exporter, - options.MaxQueueSize, - options.ScheduledDelayMilliseconds, - options.ExporterTimeoutMilliseconds, - options.MaxExportBatchSize); - } - else - { - throw new NotSupportedException($"Building batch export processors for type '{typeof(T)}' is not supported"); - } - } - - public static BaseExportProcessor CreateSimpleExportProcessor( - BaseExporter exporter, - ConcurrencyModes concurrencyMode = ConcurrencyModes.Reentrant) - { - Guard.ThrowIfNull(exporter); - - if (!concurrencyMode.HasFlag(ConcurrencyModes.Reentrant)) - { - throw new NotSupportedException("Non-reentrant simple export processors are not currently supported."); - } - - if (typeof(T) == typeof(Activity)) - { - if (concurrencyMode.HasFlag(ConcurrencyModes.Multithreaded)) - { - return (BaseExportProcessor)(object)new SimpleMultithreadedActivityExportProcessor( - (BaseExporter)(object)exporter); - } - else - { - return (BaseExportProcessor)(object)new SimpleActivityExportProcessor( - (BaseExporter)(object)exporter); - } - } - else if (typeof(T) == typeof(LogRecord)) - { - if (concurrencyMode.HasFlag(ConcurrencyModes.Multithreaded)) - { - return (BaseExportProcessor)(object)new SimpleMultithreadedExportProcessor( - (BaseExporter)(object)exporter); - } - else - { - return (BaseExportProcessor)(object)new SimpleLogRecordExportProcessor( - (BaseExporter)(object)exporter); - } - } - else - { - throw new NotSupportedException($"Building simple export processors for type '{typeof(T)}' is not supported"); - } - } -} diff --git a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderExtensions.cs b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderExtensions.cs index 775e7ecb5a1..0f5fdbb4d03 100644 --- a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderExtensions.cs +++ b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderExtensions.cs @@ -6,6 +6,7 @@ #endif using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; using OpenTelemetry.Internal; using OpenTelemetry.Resources; @@ -138,6 +139,162 @@ public static LoggerProviderBuilder AddProcessor( return loggerProviderBuilder; } + /// + /// Adds a to the provider for the supplied exporter. + /// + /// . + /// . + /// The supplied for chaining. + public static LoggerProviderBuilder AddBatchExportProcessor( + this LoggerProviderBuilder loggerProviderBuilder, + BaseExporter exporter) + => AddBatchExportProcessor(loggerProviderBuilder, name: null, exporter); + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// . + /// Optional name which is used when retrieving options. + /// . + /// The supplied for chaining. + public static LoggerProviderBuilder AddBatchExportProcessor( + this LoggerProviderBuilder loggerProviderBuilder, + string? name, + BaseExporter exporter) + { + Guard.ThrowIfNull(exporter); + + return AddBatchExportProcessor( + loggerProviderBuilder, + name, + implementationFactory: (sp, name) => exporter); + } + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// . + /// Factory function used to create the exporter. + /// The supplied for chaining. + public static LoggerProviderBuilder AddBatchExportProcessor( + this LoggerProviderBuilder loggerProviderBuilder, + Func> implementationFactory) + { + Guard.ThrowIfNull(implementationFactory); + + return AddBatchExportProcessor( + loggerProviderBuilder, + name: null, + implementationFactory: (sp, name) => implementationFactory(sp)); + } + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// . + /// Optional name which is used when retrieving options. + /// Factory function used to create the exporter. + /// The supplied for chaining. + public static LoggerProviderBuilder AddBatchExportProcessor( + this LoggerProviderBuilder loggerProviderBuilder, + string? name, + Func> implementationFactory) + { + Guard.ThrowIfNull(implementationFactory); + + return loggerProviderBuilder.AddProcessor(sp => + { + var options = sp.GetRequiredService>().Get(name); + + var exporter = implementationFactory(sp, name) + ?? throw new InvalidOperationException("Implementation factory returned a null instance"); + + return LogRecordExportProcessorFactory.CreateBatchExportProcessor(options, exporter); + }); + } + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// + /// Note: The concurrency behavior of the constructed can be controlled by decorating + /// the exporter with the . + /// + /// . + /// . + /// The supplied for chaining. + public static LoggerProviderBuilder AddSimpleExportProcessor( + this LoggerProviderBuilder loggerProviderBuilder, + BaseExporter exporter) + => AddSimpleExportProcessor(loggerProviderBuilder, name: null, exporter); + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// + /// . + /// Optional name which is used when retrieving options. + /// . + /// The supplied for chaining. + public static LoggerProviderBuilder AddSimpleExportProcessor( + this LoggerProviderBuilder loggerProviderBuilder, + string? name, + BaseExporter exporter) + { + Guard.ThrowIfNull(exporter); + + return AddSimpleExportProcessor( + loggerProviderBuilder, + name, + implementationFactory: (sp, name) => exporter); + } + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// + /// . + /// Factory function used to create the exporter. + /// The supplied for chaining. + public static LoggerProviderBuilder AddSimpleExportProcessor( + this LoggerProviderBuilder loggerProviderBuilder, + Func> implementationFactory) + { + Guard.ThrowIfNull(implementationFactory); + + return AddSimpleExportProcessor( + loggerProviderBuilder, + name: null, + implementationFactory: (sp, name) => implementationFactory(sp)); + } + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// + /// . + /// Optional name which is used when retrieving options. + /// Factory function used to create the exporter. + /// The supplied for chaining. + public static LoggerProviderBuilder AddSimpleExportProcessor( + this LoggerProviderBuilder loggerProviderBuilder, + string? name, + Func> implementationFactory) + { + Guard.ThrowIfNull(implementationFactory); + + return loggerProviderBuilder.AddProcessor(sp => + { + var options = sp.GetRequiredService>().Get(name); + + var exporter = implementationFactory(sp, name) + ?? throw new InvalidOperationException("Implementation factory returned a null instance"); + + return LogRecordExportProcessorFactory.CreateSimpleExportProcessor(options, exporter); + }); + } + /// /// Run the given actions to initialize the . /// diff --git a/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs index 921fd948ce0..5f7a303f12c 100644 --- a/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs +++ b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 using System.Diagnostics; +using Microsoft.Extensions.DependencyInjection; using OpenTelemetry.Internal; using OpenTelemetry.Resources; @@ -10,10 +11,25 @@ namespace OpenTelemetry.Logs; /// /// Contains OpenTelemetry logging options. /// -public class OpenTelemetryLoggerOptions +public class OpenTelemetryLoggerOptions : IDeferredLoggerProviderBuilder { internal readonly List>> ProcessorFactories = new(); internal ResourceBuilder? ResourceBuilder; + private readonly IServiceProvider? serviceProvider; + + /// + /// Initializes a new instance of the class. + /// + public OpenTelemetryLoggerOptions() + { + } + + internal OpenTelemetryLoggerOptions(IServiceProvider serviceProvider) + { + Debug.Assert(serviceProvider != null, "serviceProvider was null"); + + this.serviceProvider = serviceProvider; + } /// /// Gets or sets a value indicating whether or not formatted log message @@ -124,6 +140,21 @@ public OpenTelemetryLoggerOptions SetResourceBuilder(ResourceBuilder resourceBui return this; } + LoggerProviderBuilder IDeferredLoggerProviderBuilder.Configure( + Action configure) + { + Guard.ThrowIfNull(configure); + + var sp = this.serviceProvider + ?? throw new NotSupportedException("Manually constructed OpenTelemetryLoggerOptions instances cannot be converted to LoggerProviderBuilder instances"); + + var builder = sp.GetRequiredService(); + + configure(sp, builder); + + return builder; + } + internal OpenTelemetryLoggerOptions Copy() { return new() diff --git a/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggingExtensions.cs b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggingExtensions.cs index 973096cf7bc..3eccbb50651 100644 --- a/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggingExtensions.cs +++ b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggingExtensions.cs @@ -157,6 +157,9 @@ private static ILoggingBuilder AddOpenTelemetryInternal( */ services.AddOpenTelemetrySharedProviderBuilderServices(); + services.RegisterOptionsFactory( + (sp, config, name) => new OpenTelemetryLoggerOptions(sp)); + if (configureOptions != null) { // Note: Order is important here so that user-supplied delegate diff --git a/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorFactory.cs b/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorFactory.cs new file mode 100644 index 00000000000..a34d055c772 --- /dev/null +++ b/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorFactory.cs @@ -0,0 +1,54 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using System.Reflection; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Logs; + +internal static class LogRecordExportProcessorFactory +{ + public static BaseExportProcessor CreateBatchExportProcessor( + LogRecordExportProcessorOptions options, + BaseExporter exporter) + { + Guard.ThrowIfNull(options); + Guard.ThrowIfNull(exporter); + + return new BatchLogRecordExportProcessor( + exporter, + options.BatchExportProcessorOptions.MaxQueueSize, + options.BatchExportProcessorOptions.ScheduledDelayMilliseconds, + options.BatchExportProcessorOptions.ExporterTimeoutMilliseconds, + options.BatchExportProcessorOptions.MaxExportBatchSize) + { + PipelineWeight = options.PipelineWeight, + }; + } + + public static BaseExportProcessor CreateSimpleExportProcessor( + LogRecordExportProcessorOptions options, + BaseExporter exporter) + { + Guard.ThrowIfNull(options); + Guard.ThrowIfNull(exporter); + + var concurrencyMode = exporter + .GetType() + .GetCustomAttribute(inherit: true)?.Supported + ?? ConcurrencyModes.Reentrant; + + if (!concurrencyMode.HasFlag(ConcurrencyModes.Reentrant)) + { + throw new NotSupportedException("Non-reentrant simple export processors are not currently supported."); + } + + BaseExportProcessor processor = concurrencyMode.HasFlag(ConcurrencyModes.Multithreaded) + ? new SimpleMultithreadedExportProcessor(exporter) + : new SimpleLogRecordExportProcessor(exporter); + + processor.PipelineWeight = options.PipelineWeight; + + return processor; + } +} diff --git a/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorOptions.cs b/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorOptions.cs index 95cdc830e35..ce4f5e46cfd 100644 --- a/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorOptions.cs +++ b/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorOptions.cs @@ -46,4 +46,7 @@ public BatchExportLogRecordProcessorOptions BatchExportProcessorOptions this.batchExportProcessorOptions = value; } } + + /// + internal int PipelineWeight { get; set; } } diff --git a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderExtensions.cs b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderExtensions.cs index c429dad7b01..85207f9f448 100644 --- a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderExtensions.cs +++ b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderExtensions.cs @@ -7,6 +7,7 @@ #endif using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; using OpenTelemetry.Internal; using OpenTelemetry.Resources; @@ -237,6 +238,162 @@ public static TracerProviderBuilder AddProcessor( return tracerProviderBuilder; } + /// + /// Adds a to the provider for the supplied exporter. + /// + /// . + /// . + /// The supplied for chaining. + public static TracerProviderBuilder AddBatchExportProcessor( + this TracerProviderBuilder tracerProviderBuilder, + BaseExporter exporter) + => AddBatchExportProcessor(tracerProviderBuilder, name: null, exporter); + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// . + /// Optional name which is used when retrieving options. + /// . + /// The supplied for chaining. + public static TracerProviderBuilder AddBatchExportProcessor( + this TracerProviderBuilder tracerProviderBuilder, + string? name, + BaseExporter exporter) + { + Guard.ThrowIfNull(exporter); + + return AddBatchExportProcessor( + tracerProviderBuilder, + name, + implementationFactory: (sp, name) => exporter); + } + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// . + /// Factory function used to create the exporter. + /// The supplied for chaining. + public static TracerProviderBuilder AddBatchExportProcessor( + this TracerProviderBuilder tracerProviderBuilder, + Func> implementationFactory) + { + Guard.ThrowIfNull(implementationFactory); + + return AddBatchExportProcessor( + tracerProviderBuilder, + name: null, + implementationFactory: (sp, name) => implementationFactory(sp)); + } + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// . + /// Optional name which is used when retrieving options. + /// Factory function used to create the exporter. + /// The supplied for chaining. + public static TracerProviderBuilder AddBatchExportProcessor( + this TracerProviderBuilder tracerProviderBuilder, + string? name, + Func> implementationFactory) + { + Guard.ThrowIfNull(implementationFactory); + + return tracerProviderBuilder.AddProcessor(sp => + { + var options = sp.GetRequiredService>().Get(name); + + var exporter = implementationFactory(sp, name) + ?? throw new InvalidOperationException("Implementation factory returned a null instance"); + + return ActivityExportProcessorFactory.CreateBatchExportProcessor(options, exporter); + }); + } + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// + /// Note: The concurrency behavior of the constructed can be controlled by decorating + /// the exporter with the . + /// + /// . + /// . + /// The supplied for chaining. + public static TracerProviderBuilder AddSimpleExportProcessor( + this TracerProviderBuilder tracerProviderBuilder, + BaseExporter exporter) + => AddSimpleExportProcessor(tracerProviderBuilder, name: null, exporter); + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// + /// . + /// Optional name which is used when retrieving options. + /// . + /// The supplied for chaining. + public static TracerProviderBuilder AddSimpleExportProcessor( + this TracerProviderBuilder tracerProviderBuilder, + string? name, + BaseExporter exporter) + { + Guard.ThrowIfNull(exporter); + + return AddSimpleExportProcessor( + tracerProviderBuilder, + name, + implementationFactory: (sp, name) => exporter); + } + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// + /// . + /// Factory function used to create the exporter. + /// The supplied for chaining. + public static TracerProviderBuilder AddSimpleExportProcessor( + this TracerProviderBuilder tracerProviderBuilder, + Func> implementationFactory) + { + Guard.ThrowIfNull(implementationFactory); + + return AddSimpleExportProcessor( + tracerProviderBuilder, + name: null, + implementationFactory: (sp, name) => implementationFactory(sp)); + } + + /// + /// Adds a to the provider for the supplied exporter. + /// + /// + /// . + /// Optional name which is used when retrieving options. + /// Factory function used to create the exporter. + /// The supplied for chaining. + public static TracerProviderBuilder AddSimpleExportProcessor( + this TracerProviderBuilder tracerProviderBuilder, + string? name, + Func> implementationFactory) + { + Guard.ThrowIfNull(implementationFactory); + + return tracerProviderBuilder.AddProcessor(sp => + { + var options = sp.GetRequiredService>().Get(name); + + var exporter = implementationFactory(sp, name) + ?? throw new InvalidOperationException("Implementation factory returned a null instance"); + + return ActivityExportProcessorFactory.CreateSimpleExportProcessor(options, exporter); + }); + } + /// /// Run the given actions to initialize the . /// diff --git a/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorFactory.cs b/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorFactory.cs new file mode 100644 index 00000000000..18c4526f7f6 --- /dev/null +++ b/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorFactory.cs @@ -0,0 +1,55 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using System.Diagnostics; +using System.Reflection; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Trace; + +internal static class ActivityExportProcessorFactory +{ + public static BaseExportProcessor CreateBatchExportProcessor( + ActivityExportProcessorOptions options, + BaseExporter exporter) + { + Guard.ThrowIfNull(options); + Guard.ThrowIfNull(exporter); + + return new BatchActivityExportProcessor( + exporter, + options.BatchExportProcessorOptions.MaxQueueSize, + options.BatchExportProcessorOptions.ScheduledDelayMilliseconds, + options.BatchExportProcessorOptions.ExporterTimeoutMilliseconds, + options.BatchExportProcessorOptions.MaxExportBatchSize) + { + PipelineWeight = options.PipelineWeight, + }; + } + + public static BaseExportProcessor CreateSimpleExportProcessor( + ActivityExportProcessorOptions options, + BaseExporter exporter) + { + Guard.ThrowIfNull(options); + Guard.ThrowIfNull(exporter); + + var concurrencyMode = exporter + .GetType() + .GetCustomAttribute(inherit: true)?.Supported + ?? ConcurrencyModes.Reentrant; + + if (!concurrencyMode.HasFlag(ConcurrencyModes.Reentrant)) + { + throw new NotSupportedException("Non-reentrant simple export processors are not currently supported."); + } + + BaseExportProcessor processor = concurrencyMode.HasFlag(ConcurrencyModes.Multithreaded) + ? new SimpleMultithreadedActivityExportProcessor(exporter) + : new SimpleActivityExportProcessor(exporter); + + processor.PipelineWeight = options.PipelineWeight; + + return processor; + } +} diff --git a/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorOptions.cs b/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorOptions.cs index 86acb043015..ce2d79f4801 100644 --- a/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorOptions.cs +++ b/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorOptions.cs @@ -46,4 +46,7 @@ public BatchExportActivityProcessorOptions BatchExportProcessorOptions this.batchExportProcessorOptions = value; } } + + /// + internal int PipelineWeight { get; set; } } diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/IntegrationTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/IntegrationTests.cs index 3e40b9c6d9f..59de4f9d46c 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/IntegrationTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/IntegrationTests.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Diagnostics.Metrics; using System.Diagnostics.Tracing; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; using OpenTelemetry.Logs; @@ -69,11 +70,13 @@ public void TraceExportResultIsSuccess(OtlpExportProtocol protocol, string endpo var builder = Sdk.CreateTracerProviderBuilder() .AddSource(activitySourceName); - builder.AddProcessor(sp => OtlpTraceExporterHelperExtensions.BuildOtlpExporterProcessor( + builder.ConfigureBuilder((sp, builder) => OtlpTraceExporterHelperExtensions.AddOtlpTraceExporter( serviceProvider: sp, + builder: builder, exporterOptions: exporterOptions, sdkLimitOptions: DefaultSdkLimitOptions, experimentalOptions: DefaultExperimentalOptions, + exportProcessorType: exporterOptions.ExportProcessorType, configureExporterInstance: otlpExporter => { delegatingExporter = new DelegatingExporter @@ -222,26 +225,26 @@ public void LogExportResultIsSuccess(OtlpExportProtocol protocol, string endpoin DelegatingExporter delegatingExporter; var exportResults = new List(); - var processorOptions = new LogRecordExportProcessorOptions - { - ExportProcessorType = exportProcessorType, - BatchExportProcessorOptions = new() - { - ScheduledDelayMilliseconds = ExportIntervalMilliseconds, - }, - }; using var loggerFactory = LoggerFactory.Create(builder => { builder .UseOpenTelemetry(logging => logging - .AddProcessor(sp => - OtlpLogExporterHelperExtensions.BuildOtlpLogExporter( + .ConfigureServices(services => + { + services.Configure(o => + { + o.BatchExportProcessorOptions.ScheduledDelayMilliseconds = ExportIntervalMilliseconds; + }); + }) + .ConfigureBuilder((sp, builder) => + OtlpLogExporterHelperExtensions.AddOtlpLogExporter( sp, + builder, exporterOptions, - processorOptions, DefaultSdkLimitOptions, DefaultExperimentalOptions, + exportProcessorType, configureExporterInstance: otlpExporter => { delegatingExporter = new DelegatingExporter @@ -261,7 +264,7 @@ public void LogExportResultIsSuccess(OtlpExportProtocol protocol, string endpoin var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); logger.LogInformation("Hello from {name} {price}.", "tomato", 2.99); - switch (processorOptions.ExportProcessorType) + switch (exportProcessorType) { case ExportProcessorType.Batch: Assert.True(handle.WaitOne(ExportIntervalMilliseconds * 2)); From f01a0138e7f7c22ec39a5789615ecb18fabb77c3 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Mon, 22 Jul 2024 15:22:00 -0700 Subject: [PATCH 3/9] Public API updates. --- .../.publicApi/Stable/PublicAPI.Unshipped.txt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt index e69de29bb2d..db2d7b1b7dd 100644 --- a/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt @@ -0,0 +1,23 @@ +OpenTelemetry.BatchExportProcessorOptions.ApplyTo(OpenTelemetry.BatchExportProcessorOptions! other) -> void +OpenTelemetry.ConcurrencyModes +OpenTelemetry.ConcurrencyModes.Multithreaded = 2 -> OpenTelemetry.ConcurrencyModes +OpenTelemetry.ConcurrencyModes.Reentrant = 1 -> OpenTelemetry.ConcurrencyModes +OpenTelemetry.ConcurrencyModesAttribute +OpenTelemetry.ConcurrencyModesAttribute.ConcurrencyModesAttribute(OpenTelemetry.ConcurrencyModes supported) -> void +OpenTelemetry.ConcurrencyModesAttribute.Supported.get -> OpenTelemetry.ConcurrencyModes +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddBatchExportProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddBatchExportProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, string? name, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddBatchExportProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, string? name, System.Func!>! implementationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddBatchExportProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Func!>! implementationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, string? name, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, string? name, System.Func!>! implementationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Func!>! implementationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder! +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddBatchExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder! +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddBatchExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, string? name, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder! +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddBatchExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, string? name, System.Func!>! implementationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddBatchExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Func!>! implementationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder! +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, string? name, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder! +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, string? name, System.Func!>! implementationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Func!>! implementationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! \ No newline at end of file From 73ae00038cf64a040e35792b1223c431e449bd1b Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Tue, 23 Jul 2024 11:25:39 -0700 Subject: [PATCH 4/9] Tweaks. --- .../Builder/OtlpExporterBuilder.cs | 6 +- .../OtlpLogExporterHelperExtensions.cs | 11 ++- .../OtlpTraceExporterHelperExtensions.cs | 11 ++- .../ConcurrencyModesAttribute.cs | 22 ++++++ .../LoggerProviderBuilderExtensions.cs | 75 ++++++++++++------- .../LogRecordExportProcessorFactory.cs | 43 +++++------ .../LogRecordExportProcessorOptions.cs | 3 - .../TracerProviderBuilderExtensions.cs | 75 ++++++++++++------- .../ActivityExportProcessorFactory.cs | 43 +++++------ .../ActivityExportProcessorOptions.cs | 3 - 10 files changed, 170 insertions(+), 122 deletions(-) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs index be8a6e4fdfe..4ec74ee456e 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs @@ -203,8 +203,6 @@ there but that may change in the future so it is handled var processorOptions = builderOptions.LogRecordExportProcessorOptions ?? throw new InvalidOperationException("LogRecordExportProcessorOptions were missing with logging enabled"); - processorOptions.PipelineWeight = DefaultProcessorPipelineWeight; - OtlpLogExporterHelperExtensions.AddOtlpLogExporter( sp, logging, @@ -212,6 +210,7 @@ there but that may change in the future so it is handled builderOptions.SdkLimitOptions, builderOptions.ExperimentalOptions, processorOptions.ExportProcessorType, + processorPipelineWeight: DefaultProcessorPipelineWeight, skipUseOtlpExporterRegistrationCheck: true); }); @@ -237,8 +236,6 @@ there but that may change in the future so it is handled var processorOptions = builderOptions.ActivityExportProcessorOptions ?? throw new InvalidOperationException("ActivityExportProcessorOptions were missing with tracing enabled"); - processorOptions.PipelineWeight = DefaultProcessorPipelineWeight; - OtlpTraceExporterHelperExtensions.AddOtlpTraceExporter( sp, tracing, @@ -246,6 +243,7 @@ there but that may change in the future so it is handled builderOptions.SdkLimitOptions, builderOptions.ExperimentalOptions, processorOptions.ExportProcessorType, + processorPipelineWeight: DefaultProcessorPipelineWeight, skipUseOtlpExporterRegistrationCheck: true); }); diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs index adf0c819c9c..a195635f346 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs @@ -284,6 +284,7 @@ internal static void AddOtlpLogExporter( SdkLimitOptions sdkLimitOptions, ExperimentalOptions experimentalOptions, ExportProcessorType exportProcessorType, + int processorPipelineWeight = 0, bool skipUseOtlpExporterRegistrationCheck = false, Func, BaseExporter>? configureExporterInstance = null) { @@ -326,11 +327,17 @@ internal static void AddOtlpLogExporter( if (exportProcessorType == ExportProcessorType.Simple) { - builder!.AddSimpleExportProcessor(otlpExporter); + builder!.AddSimpleExportProcessor( + name: null, + (sp, name) => otlpExporter, + processorPipelineWeight); } else { - builder!.AddBatchExportProcessor(otlpExporter); + builder!.AddBatchExportProcessor( + name: null, + (sp, name) => otlpExporter, + processorPipelineWeight); } } diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs index 59edb13fc49..7eecb5b44e9 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs @@ -128,6 +128,7 @@ internal static void AddOtlpTraceExporter( SdkLimitOptions sdkLimitOptions, ExperimentalOptions experimentalOptions, ExportProcessorType exportProcessorType, + int processorPipelineWeight = 0, bool skipUseOtlpExporterRegistrationCheck = false, Func, BaseExporter>? configureExporterInstance = null) { @@ -153,11 +154,17 @@ internal static void AddOtlpTraceExporter( if (exportProcessorType == ExportProcessorType.Simple) { - builder!.AddSimpleExportProcessor(otlpExporter); + builder!.AddSimpleExportProcessor( + name: null, + (sp, name) => otlpExporter, + processorPipelineWeight); } else { - builder!.AddBatchExportProcessor(otlpExporter); + builder!.AddBatchExportProcessor( + name: null, + (sp, name) => otlpExporter, + processorPipelineWeight); } } } diff --git a/src/OpenTelemetry/ConcurrencyModesAttribute.cs b/src/OpenTelemetry/ConcurrencyModesAttribute.cs index af1234789c7..c3abfb5d71a 100644 --- a/src/OpenTelemetry/ConcurrencyModesAttribute.cs +++ b/src/OpenTelemetry/ConcurrencyModesAttribute.cs @@ -1,6 +1,9 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +using System.Diagnostics; +using System.Reflection; + namespace OpenTelemetry; /// @@ -24,4 +27,23 @@ public ConcurrencyModesAttribute(ConcurrencyModes supported) /// Gets the supported . /// public ConcurrencyModes Supported => this.supportedConcurrencyModes; + + internal static ConcurrencyModes GetConcurrencyModeForExporter( + BaseExporter exporter) + where T : class + { + Debug.Assert(exporter != null, "exporter was null"); + + var concurrencyMode = exporter! + .GetType() + .GetCustomAttribute(inherit: true)?.Supported + ?? ConcurrencyModes.Reentrant; + + if (!concurrencyMode.HasFlag(ConcurrencyModes.Reentrant)) + { + throw new NotSupportedException("Non-reentrant simple export processors are not currently supported."); + } + + return concurrencyMode; + } } diff --git a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderExtensions.cs b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderExtensions.cs index 0f5fdbb4d03..29d03d0d9da 100644 --- a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderExtensions.cs +++ b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderExtensions.cs @@ -167,7 +167,8 @@ public static LoggerProviderBuilder AddBatchExportProcessor( return AddBatchExportProcessor( loggerProviderBuilder, name, - implementationFactory: (sp, name) => exporter); + implementationFactory: (sp, name) => exporter, + pipelineWeight: 0); } /// @@ -185,7 +186,8 @@ public static LoggerProviderBuilder AddBatchExportProcessor( return AddBatchExportProcessor( loggerProviderBuilder, name: null, - implementationFactory: (sp, name) => implementationFactory(sp)); + implementationFactory: (sp, name) => implementationFactory(sp), + pipelineWeight: 0); } /// @@ -199,19 +201,7 @@ public static LoggerProviderBuilder AddBatchExportProcessor( this LoggerProviderBuilder loggerProviderBuilder, string? name, Func> implementationFactory) - { - Guard.ThrowIfNull(implementationFactory); - - return loggerProviderBuilder.AddProcessor(sp => - { - var options = sp.GetRequiredService>().Get(name); - - var exporter = implementationFactory(sp, name) - ?? throw new InvalidOperationException("Implementation factory returned a null instance"); - - return LogRecordExportProcessorFactory.CreateBatchExportProcessor(options, exporter); - }); - } + => AddBatchExportProcessor(loggerProviderBuilder, name, implementationFactory, pipelineWeight: 0); /// /// Adds a to the provider for the supplied exporter. @@ -247,7 +237,8 @@ public static LoggerProviderBuilder AddSimpleExportProcessor( return AddSimpleExportProcessor( loggerProviderBuilder, name, - implementationFactory: (sp, name) => exporter); + implementationFactory: (sp, name) => exporter, + pipelineWeight: 0); } /// @@ -266,7 +257,8 @@ public static LoggerProviderBuilder AddSimpleExportProcessor( return AddSimpleExportProcessor( loggerProviderBuilder, name: null, - implementationFactory: (sp, name) => implementationFactory(sp)); + implementationFactory: (sp, name) => implementationFactory(sp), + pipelineWeight: 0); } /// @@ -281,6 +273,28 @@ public static LoggerProviderBuilder AddSimpleExportProcessor( this LoggerProviderBuilder loggerProviderBuilder, string? name, Func> implementationFactory) + => AddSimpleExportProcessor(loggerProviderBuilder, name, implementationFactory, pipelineWeight: 0); + + /// + /// Run the given actions to initialize the . + /// + /// . + /// . + public static LoggerProvider Build(this LoggerProviderBuilder loggerProviderBuilder) + { + if (loggerProviderBuilder is LoggerProviderBuilderBase loggerProviderBuilderBase) + { + return loggerProviderBuilderBase.Build(); + } + + throw new NotSupportedException($"Build is not supported on '{loggerProviderBuilder?.GetType().FullName ?? "null"}' instances."); + } + + internal static LoggerProviderBuilder AddBatchExportProcessor( + this LoggerProviderBuilder loggerProviderBuilder, + string? name, + Func> implementationFactory, + int pipelineWeight) { Guard.ThrowIfNull(implementationFactory); @@ -291,22 +305,27 @@ public static LoggerProviderBuilder AddSimpleExportProcessor( var exporter = implementationFactory(sp, name) ?? throw new InvalidOperationException("Implementation factory returned a null instance"); - return LogRecordExportProcessorFactory.CreateSimpleExportProcessor(options, exporter); + return LogRecordExportProcessorFactory.CreateBatchExportProcessor( + exporter, + options.BatchExportProcessorOptions, + pipelineWeight); }); } - /// - /// Run the given actions to initialize the . - /// - /// . - /// . - public static LoggerProvider Build(this LoggerProviderBuilder loggerProviderBuilder) + internal static LoggerProviderBuilder AddSimpleExportProcessor( + this LoggerProviderBuilder loggerProviderBuilder, + string? name, + Func> implementationFactory, + int pipelineWeight) { - if (loggerProviderBuilder is LoggerProviderBuilderBase loggerProviderBuilderBase) + Guard.ThrowIfNull(implementationFactory); + + return loggerProviderBuilder.AddProcessor(sp => { - return loggerProviderBuilderBase.Build(); - } + var exporter = implementationFactory(sp, name) + ?? throw new InvalidOperationException("Implementation factory returned a null instance"); - throw new NotSupportedException($"Build is not supported on '{loggerProviderBuilder?.GetType().FullName ?? "null"}' instances."); + return LogRecordExportProcessorFactory.CreateSimpleExportProcessor(exporter, pipelineWeight); + }); } } diff --git a/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorFactory.cs b/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorFactory.cs index a34d055c772..121b9aa7ca5 100644 --- a/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorFactory.cs +++ b/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorFactory.cs @@ -1,7 +1,6 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -using System.Reflection; using OpenTelemetry.Internal; namespace OpenTelemetry.Logs; @@ -9,45 +8,37 @@ namespace OpenTelemetry.Logs; internal static class LogRecordExportProcessorFactory { public static BaseExportProcessor CreateBatchExportProcessor( - LogRecordExportProcessorOptions options, - BaseExporter exporter) + BaseExporter exporter, + BatchExportProcessorOptions options, + int pipelineWeight) { - Guard.ThrowIfNull(options); Guard.ThrowIfNull(exporter); + Guard.ThrowIfNull(options); return new BatchLogRecordExportProcessor( exporter, - options.BatchExportProcessorOptions.MaxQueueSize, - options.BatchExportProcessorOptions.ScheduledDelayMilliseconds, - options.BatchExportProcessorOptions.ExporterTimeoutMilliseconds, - options.BatchExportProcessorOptions.MaxExportBatchSize) + options.MaxQueueSize, + options.ScheduledDelayMilliseconds, + options.ExporterTimeoutMilliseconds, + options.MaxExportBatchSize) { - PipelineWeight = options.PipelineWeight, + PipelineWeight = pipelineWeight, }; } public static BaseExportProcessor CreateSimpleExportProcessor( - LogRecordExportProcessorOptions options, - BaseExporter exporter) + BaseExporter exporter, + int pipelineWeight) { - Guard.ThrowIfNull(options); Guard.ThrowIfNull(exporter); - var concurrencyMode = exporter - .GetType() - .GetCustomAttribute(inherit: true)?.Supported - ?? ConcurrencyModes.Reentrant; - - if (!concurrencyMode.HasFlag(ConcurrencyModes.Reentrant)) - { - throw new NotSupportedException("Non-reentrant simple export processors are not currently supported."); - } - - BaseExportProcessor processor = concurrencyMode.HasFlag(ConcurrencyModes.Multithreaded) - ? new SimpleMultithreadedExportProcessor(exporter) - : new SimpleLogRecordExportProcessor(exporter); + BaseExportProcessor processor = ConcurrencyModesAttribute + .GetConcurrencyModeForExporter(exporter) + .HasFlag(ConcurrencyModes.Multithreaded) + ? new SimpleMultithreadedExportProcessor(exporter) + : new SimpleLogRecordExportProcessor(exporter); - processor.PipelineWeight = options.PipelineWeight; + processor.PipelineWeight = pipelineWeight; return processor; } diff --git a/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorOptions.cs b/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorOptions.cs index ce4f5e46cfd..95cdc830e35 100644 --- a/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorOptions.cs +++ b/src/OpenTelemetry/Logs/Processor/LogRecordExportProcessorOptions.cs @@ -46,7 +46,4 @@ public BatchExportLogRecordProcessorOptions BatchExportProcessorOptions this.batchExportProcessorOptions = value; } } - - /// - internal int PipelineWeight { get; set; } } diff --git a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderExtensions.cs b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderExtensions.cs index 85207f9f448..47eaecc3b66 100644 --- a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderExtensions.cs +++ b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderExtensions.cs @@ -266,7 +266,8 @@ public static TracerProviderBuilder AddBatchExportProcessor( return AddBatchExportProcessor( tracerProviderBuilder, name, - implementationFactory: (sp, name) => exporter); + implementationFactory: (sp, name) => exporter, + pipelineWeight: 0); } /// @@ -284,7 +285,8 @@ public static TracerProviderBuilder AddBatchExportProcessor( return AddBatchExportProcessor( tracerProviderBuilder, name: null, - implementationFactory: (sp, name) => implementationFactory(sp)); + implementationFactory: (sp, name) => implementationFactory(sp), + pipelineWeight: 0); } /// @@ -298,19 +300,7 @@ public static TracerProviderBuilder AddBatchExportProcessor( this TracerProviderBuilder tracerProviderBuilder, string? name, Func> implementationFactory) - { - Guard.ThrowIfNull(implementationFactory); - - return tracerProviderBuilder.AddProcessor(sp => - { - var options = sp.GetRequiredService>().Get(name); - - var exporter = implementationFactory(sp, name) - ?? throw new InvalidOperationException("Implementation factory returned a null instance"); - - return ActivityExportProcessorFactory.CreateBatchExportProcessor(options, exporter); - }); - } + => AddBatchExportProcessor(tracerProviderBuilder, name, implementationFactory, pipelineWeight: 0); /// /// Adds a to the provider for the supplied exporter. @@ -346,7 +336,8 @@ public static TracerProviderBuilder AddSimpleExportProcessor( return AddSimpleExportProcessor( tracerProviderBuilder, name, - implementationFactory: (sp, name) => exporter); + implementationFactory: (sp, name) => exporter, + pipelineWeight: 0); } /// @@ -365,7 +356,8 @@ public static TracerProviderBuilder AddSimpleExportProcessor( return AddSimpleExportProcessor( tracerProviderBuilder, name: null, - implementationFactory: (sp, name) => implementationFactory(sp)); + implementationFactory: (sp, name) => implementationFactory(sp), + pipelineWeight: 0); } /// @@ -380,6 +372,28 @@ public static TracerProviderBuilder AddSimpleExportProcessor( this TracerProviderBuilder tracerProviderBuilder, string? name, Func> implementationFactory) + => AddSimpleExportProcessor(tracerProviderBuilder, name, implementationFactory, pipelineWeight: 0); + + /// + /// Run the given actions to initialize the . + /// + /// . + /// . + public static TracerProvider Build(this TracerProviderBuilder tracerProviderBuilder) + { + if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase) + { + return tracerProviderBuilderBase.InvokeBuild(); + } + + throw new NotSupportedException($"Build is not supported on '{tracerProviderBuilder?.GetType().FullName ?? "null"}' instances."); + } + + internal static TracerProviderBuilder AddBatchExportProcessor( + this TracerProviderBuilder tracerProviderBuilder, + string? name, + Func> implementationFactory, + int pipelineWeight) { Guard.ThrowIfNull(implementationFactory); @@ -390,22 +404,27 @@ public static TracerProviderBuilder AddSimpleExportProcessor( var exporter = implementationFactory(sp, name) ?? throw new InvalidOperationException("Implementation factory returned a null instance"); - return ActivityExportProcessorFactory.CreateSimpleExportProcessor(options, exporter); + return ActivityExportProcessorFactory.CreateBatchExportProcessor( + exporter, + options.BatchExportProcessorOptions, + pipelineWeight); }); } - /// - /// Run the given actions to initialize the . - /// - /// . - /// . - public static TracerProvider Build(this TracerProviderBuilder tracerProviderBuilder) + internal static TracerProviderBuilder AddSimpleExportProcessor( + this TracerProviderBuilder tracerProviderBuilder, + string? name, + Func> implementationFactory, + int pipelineWeight) { - if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase) + Guard.ThrowIfNull(implementationFactory); + + return tracerProviderBuilder.AddProcessor(sp => { - return tracerProviderBuilderBase.InvokeBuild(); - } + var exporter = implementationFactory(sp, name) + ?? throw new InvalidOperationException("Implementation factory returned a null instance"); - throw new NotSupportedException($"Build is not supported on '{tracerProviderBuilder?.GetType().FullName ?? "null"}' instances."); + return ActivityExportProcessorFactory.CreateSimpleExportProcessor(exporter, pipelineWeight); + }); } } diff --git a/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorFactory.cs b/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorFactory.cs index 18c4526f7f6..195e770e88a 100644 --- a/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorFactory.cs +++ b/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorFactory.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 using System.Diagnostics; -using System.Reflection; using OpenTelemetry.Internal; namespace OpenTelemetry.Trace; @@ -10,45 +9,37 @@ namespace OpenTelemetry.Trace; internal static class ActivityExportProcessorFactory { public static BaseExportProcessor CreateBatchExportProcessor( - ActivityExportProcessorOptions options, - BaseExporter exporter) + BaseExporter exporter, + BatchExportProcessorOptions options, + int pipelineWeight) { - Guard.ThrowIfNull(options); Guard.ThrowIfNull(exporter); + Guard.ThrowIfNull(options); return new BatchActivityExportProcessor( exporter, - options.BatchExportProcessorOptions.MaxQueueSize, - options.BatchExportProcessorOptions.ScheduledDelayMilliseconds, - options.BatchExportProcessorOptions.ExporterTimeoutMilliseconds, - options.BatchExportProcessorOptions.MaxExportBatchSize) + options.MaxQueueSize, + options.ScheduledDelayMilliseconds, + options.ExporterTimeoutMilliseconds, + options.MaxExportBatchSize) { - PipelineWeight = options.PipelineWeight, + PipelineWeight = pipelineWeight, }; } public static BaseExportProcessor CreateSimpleExportProcessor( - ActivityExportProcessorOptions options, - BaseExporter exporter) + BaseExporter exporter, + int pipelineWeight) { - Guard.ThrowIfNull(options); Guard.ThrowIfNull(exporter); - var concurrencyMode = exporter - .GetType() - .GetCustomAttribute(inherit: true)?.Supported - ?? ConcurrencyModes.Reentrant; - - if (!concurrencyMode.HasFlag(ConcurrencyModes.Reentrant)) - { - throw new NotSupportedException("Non-reentrant simple export processors are not currently supported."); - } - - BaseExportProcessor processor = concurrencyMode.HasFlag(ConcurrencyModes.Multithreaded) - ? new SimpleMultithreadedActivityExportProcessor(exporter) - : new SimpleActivityExportProcessor(exporter); + BaseExportProcessor processor = ConcurrencyModesAttribute + .GetConcurrencyModeForExporter(exporter) + .HasFlag(ConcurrencyModes.Multithreaded) + ? new SimpleMultithreadedActivityExportProcessor(exporter) + : new SimpleActivityExportProcessor(exporter); - processor.PipelineWeight = options.PipelineWeight; + processor.PipelineWeight = pipelineWeight; return processor; } diff --git a/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorOptions.cs b/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorOptions.cs index ce2d79f4801..86acb043015 100644 --- a/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorOptions.cs +++ b/src/OpenTelemetry/Trace/Processor/ActivityExportProcessorOptions.cs @@ -46,7 +46,4 @@ public BatchExportActivityProcessorOptions BatchExportProcessorOptions this.batchExportProcessorOptions = value; } } - - /// - internal int PipelineWeight { get; set; } } From 8b065529c20664ec03dce660104f76bfc57a9dca Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Tue, 23 Jul 2024 15:43:29 -0700 Subject: [PATCH 5/9] Fixes. --- .../Builder/OtlpExporterBuilder.cs | 2 + .../Builder/OtlpExporterBuilderOptions.cs | 10 +-- .../OtlpExporterOptions.cs | 11 +-- .../OtlpLogExporterHelperExtensions.cs | 9 ++- .../OtlpTraceExporterHelperExtensions.cs | 59 +++++++++------- .../OpenTelemetry.Exporter.Zipkin.csproj | 8 +-- .../ZipkinExporterHelperExtensions.cs | 59 +++++++++------- .../ZipkinExporterOptions.cs | 7 +- src/OpenTelemetry/AssemblyInfo.cs | 2 + .../IntegrationTest/IntegrationTests.cs | 2 + .../OtlpTraceExporterTests.cs | 62 +++++++++++++++++ .../ZipkinExporterTests.cs | 69 ++++++++++++++++++- 12 files changed, 229 insertions(+), 71 deletions(-) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs index 4ec74ee456e..70ddfd6527f 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilder.cs @@ -204,6 +204,7 @@ there but that may change in the future so it is handled ?? throw new InvalidOperationException("LogRecordExportProcessorOptions were missing with logging enabled"); OtlpLogExporterHelperExtensions.AddOtlpLogExporter( + name, sp, logging, builderOptions.LoggingOptionsInstance.ApplyDefaults(builderOptions.DefaultOptionsInstance), @@ -237,6 +238,7 @@ there but that may change in the future so it is handled ?? throw new InvalidOperationException("ActivityExportProcessorOptions were missing with tracing enabled"); OtlpTraceExporterHelperExtensions.AddOtlpTraceExporter( + name, sp, tracing, builderOptions.TracingOptionsInstance.ApplyDefaults(builderOptions.DefaultOptionsInstance), diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilderOptions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilderOptions.cs index 7d9786bb040..27f0b27a3ac 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilderOptions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Builder/OtlpExporterBuilderOptions.cs @@ -41,15 +41,15 @@ internal OtlpExporterBuilderOptions( this.MetricReaderOptions = metricReaderOptions; this.ActivityExportProcessorOptions = activityExportProcessorOptions; - var defaultBatchOptions = this.ActivityExportProcessorOptions!.BatchExportProcessorOptions; + var defaultOptions = this.ActivityExportProcessorOptions!; - this.DefaultOptionsInstance = new OtlpExporterOptions(configuration!, OtlpExporterOptionsConfigurationType.Default, defaultBatchOptions); + this.DefaultOptionsInstance = new OtlpExporterOptions(configuration!, OtlpExporterOptionsConfigurationType.Default, defaultOptions); - this.LoggingOptionsInstance = new OtlpExporterOptions(configuration!, OtlpExporterOptionsConfigurationType.Logs, defaultBatchOptions); + this.LoggingOptionsInstance = new OtlpExporterOptions(configuration!, OtlpExporterOptionsConfigurationType.Logs, defaultOptions); - this.MetricsOptionsInstance = new OtlpExporterOptions(configuration!, OtlpExporterOptionsConfigurationType.Metrics, defaultBatchOptions); + this.MetricsOptionsInstance = new OtlpExporterOptions(configuration!, OtlpExporterOptionsConfigurationType.Metrics, defaultOptions); - this.TracingOptionsInstance = new OtlpExporterOptions(configuration!, OtlpExporterOptionsConfigurationType.Traces, defaultBatchOptions); + this.TracingOptionsInstance = new OtlpExporterOptions(configuration!, OtlpExporterOptionsConfigurationType.Traces, defaultOptions); } public IOtlpExporterOptions DefaultOptions => this.DefaultOptionsInstance; diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs index 355ab376743..c9076909a57 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs @@ -53,16 +53,16 @@ internal OtlpExporterOptions( : this( configuration: new ConfigurationBuilder().AddEnvironmentVariables().Build(), configurationType, - defaultBatchOptions: new()) + defaultOptions: new()) { } internal OtlpExporterOptions( IConfiguration configuration, OtlpExporterOptionsConfigurationType configurationType, - BatchExportActivityProcessorOptions defaultBatchOptions) + ActivityExportProcessorOptions defaultOptions) { - Debug.Assert(defaultBatchOptions != null, "defaultBatchOptions was null"); + Debug.Assert(defaultOptions != null, "defaultOptions was null"); this.ApplyConfiguration(configuration, configurationType); @@ -74,7 +74,8 @@ internal OtlpExporterOptions( }; }; - this.BatchExportProcessorOptions = defaultBatchOptions!; + this.ExportProcessorType = defaultOptions!.ExportProcessorType; + this.BatchExportProcessorOptions = defaultOptions.BatchExportProcessorOptions; } /// @@ -165,7 +166,7 @@ internal static OtlpExporterOptions CreateOtlpExporterOptions( => new( configuration, OtlpExporterOptionsConfigurationType.Default, - serviceProvider.GetRequiredService>().Get(name)); + serviceProvider.GetRequiredService>().Get(name)); internal void ApplyConfigurationUsingSpecificationEnvVars( IConfiguration configuration, diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs index a195635f346..1b220db803f 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporterHelperExtensions.cs @@ -65,6 +65,7 @@ public static OpenTelemetryLoggerOptions AddOtlpExporter( configure?.Invoke(exporterOptions); AddOtlpLogExporter( + finalOptionsName, sp, builder, exporterOptions, @@ -114,6 +115,7 @@ public static OpenTelemetryLoggerOptions AddOtlpExporter( configureExporterAndProcessor?.Invoke(exporterOptions, processorOptions); AddOtlpLogExporter( + finalOptionsName, sp, builder, exporterOptions, @@ -209,6 +211,7 @@ public static LoggerProviderBuilder AddOtlpExporter( var sdkLimitOptions = sp.GetRequiredService>().CurrentValue; AddOtlpLogExporter( + finalOptionsName, sp, builder, exporterOptions, @@ -268,6 +271,7 @@ public static LoggerProviderBuilder AddOtlpExporter( var sdkLimitOptions = sp.GetRequiredService>().CurrentValue; AddOtlpLogExporter( + finalOptionsName, sp, builder, exporterOptions, @@ -278,6 +282,7 @@ public static LoggerProviderBuilder AddOtlpExporter( } internal static void AddOtlpLogExporter( + string? name, IServiceProvider serviceProvider, LoggerProviderBuilder builder, OtlpExporterOptions exporterOptions, @@ -328,14 +333,14 @@ internal static void AddOtlpLogExporter( if (exportProcessorType == ExportProcessorType.Simple) { builder!.AddSimpleExportProcessor( - name: null, + name, (sp, name) => otlpExporter, processorPipelineWeight); } else { builder!.AddBatchExportProcessor( - name: null, + name, (sp, name) => otlpExporter, processorPipelineWeight); } diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs index 7eecb5b44e9..335b47269f9 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs @@ -58,28 +58,6 @@ public static TracerProviderBuilder AddOtlpExporter( } services.AddOtlpExporterTracingServices(); - - services - .AddOptions(name) - .Configure>( - (exporterOptions, batchOptionsMonitor) => - { - var defaultBatchOptions = batchOptionsMonitor.Get(name); - - var exporterBatchOptions = exporterOptions.BatchExportProcessorOptions; - if (exporterBatchOptions != null - && exporterBatchOptions != defaultBatchOptions) - { - // Note: By default - // OtlpExporterOptions.BatchExportProcessorOptions - // is set to BatchExportActivityProcessorOptions - // retrieved from DI. But users may change it via - // public setter so this code makes sure any changes - // are reflected on the DI instance so the call to - // AddBatchExportProcessor picks them up. - exporterBatchOptions.ApplyTo(defaultBatchOptions); - } - }); }); return builder.ConfigureBuilder((sp, builder) => @@ -111,7 +89,10 @@ public static TracerProviderBuilder AddOtlpExporter( // instance. var sdkLimitOptions = sp.GetRequiredService>().CurrentValue; + SyncExporterOptionsToDefaults(sp, finalOptionsName, exporterOptions); + AddOtlpTraceExporter( + finalOptionsName, sp, builder, exporterOptions, @@ -122,6 +103,7 @@ public static TracerProviderBuilder AddOtlpExporter( } internal static void AddOtlpTraceExporter( + string? name, IServiceProvider serviceProvider, TracerProviderBuilder builder, OtlpExporterOptions exporterOptions, @@ -155,16 +137,45 @@ internal static void AddOtlpTraceExporter( if (exportProcessorType == ExportProcessorType.Simple) { builder!.AddSimpleExportProcessor( - name: null, + name, (sp, name) => otlpExporter, processorPipelineWeight); } else { builder!.AddBatchExportProcessor( - name: null, + name, (sp, name) => otlpExporter, processorPipelineWeight); } } + + private static void SyncExporterOptionsToDefaults( + IServiceProvider serviceProvider, + string finalOptionsName, + OtlpExporterOptions exporterOptions) + { + var defaultOptions = serviceProvider.GetRequiredService>() + .Get(finalOptionsName); + + if (exporterOptions.ExportProcessorType != defaultOptions.ExportProcessorType) + { + defaultOptions.ExportProcessorType = exporterOptions.ExportProcessorType; + } + + var defaultBatchOptions = defaultOptions.BatchExportProcessorOptions; + var exporterBatchOptions = exporterOptions.BatchExportProcessorOptions; + if (exporterBatchOptions != null + && exporterBatchOptions != defaultBatchOptions) + { + // Note: By default + // OtlpExporterOptions.BatchExportProcessorOptions + // is set to BatchExportActivityProcessorOptions + // retrieved from DI. But users may change it via + // public setter so this code makes sure any changes + // are reflected on the DI instance so the call to + // AddBatchExportProcessor picks them up. + exporterBatchOptions.ApplyTo(defaultBatchOptions); + } + } } diff --git a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj index 22b6537a7dd..06afbabfe74 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj +++ b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj @@ -10,15 +10,11 @@ - - - - - - + + diff --git a/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs index a81fb8b9fec..6036a2d0792 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs @@ -60,29 +60,7 @@ public static TracerProviderBuilder AddZipkinExporter( services.RegisterOptionsFactory( (sp, configuration, name) => new ZipkinExporterOptions( configuration, - sp.GetRequiredService>().Get(name))); - - services - .AddOptions(name) - .Configure>( - (exporterOptions, batchOptionsMonitor) => - { - var defaultBatchOptions = batchOptionsMonitor.Get(name); - - var exporterBatchOptions = exporterOptions.BatchExportProcessorOptions; - if (exporterBatchOptions != null - && exporterBatchOptions != defaultBatchOptions) - { - // Note: By default - // ZipkinExporterOptions.BatchExportProcessorOptions is - // set to BatchExportActivityProcessorOptions retrieved - // from DI. But users may change it via public setter so - // this code makes sure any changes are reflected on the - // DI instance so the call to AddBatchExportProcessor - // picks them up. - exporterBatchOptions.ApplyTo(defaultBatchOptions); - } - }); + sp.GetRequiredService>().Get(name))); services.ConfigureOpenTelemetryTracerProvider( (sp, builder) => AddZipkinExporter(sp, builder, name)); @@ -96,6 +74,8 @@ private static void AddZipkinExporter( { var exporterOptions = serviceProvider.GetRequiredService>().Get(name); + SyncExporterOptionsToDefaults(serviceProvider, name, exporterOptions); + if (exporterOptions.HttpClientFactory == ZipkinExporterOptions.DefaultHttpClientFactory) { exporterOptions.HttpClientFactory = () => @@ -127,11 +107,40 @@ private static void AddZipkinExporter( if (exporterOptions.ExportProcessorType == ExportProcessorType.Simple) { - builder.AddSimpleExportProcessor(zipkinExporter); + builder.AddSimpleExportProcessor(name, zipkinExporter); } else { - builder.AddBatchExportProcessor(zipkinExporter); + builder.AddBatchExportProcessor(name, zipkinExporter); + } + } + + private static void SyncExporterOptionsToDefaults( + IServiceProvider serviceProvider, + string name, + ZipkinExporterOptions exporterOptions) + { + var defaultOptions = serviceProvider.GetRequiredService>() + .Get(name); + + if (exporterOptions.ExportProcessorType != defaultOptions.ExportProcessorType) + { + defaultOptions.ExportProcessorType = exporterOptions.ExportProcessorType; + } + + var defaultBatchOptions = defaultOptions.BatchExportProcessorOptions; + var exporterBatchOptions = exporterOptions.BatchExportProcessorOptions; + if (exporterBatchOptions != null + && exporterBatchOptions != defaultBatchOptions) + { + // Note: By default + // ZipkinExporterOptions.BatchExportProcessorOptions is + // set to BatchExportActivityProcessorOptions retrieved + // from DI. But users may change it via public setter so + // this code makes sure any changes are reflected on the + // DI instance so the call to AddBatchExportProcessor + // picks them up. + exporterBatchOptions.ApplyTo(defaultBatchOptions); } } } diff --git a/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterOptions.cs b/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterOptions.cs index bc94307351d..2ccd9a61fef 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterOptions.cs @@ -35,17 +35,18 @@ public ZipkinExporterOptions() internal ZipkinExporterOptions( IConfiguration configuration, - BatchExportActivityProcessorOptions defaultBatchOptions) + ActivityExportProcessorOptions defaultOptions) { Debug.Assert(configuration != null, "configuration was null"); - Debug.Assert(defaultBatchOptions != null, "defaultBatchOptions was null"); + Debug.Assert(defaultOptions != null, "defaultOptions was null"); if (configuration.TryGetUriValue(ZipkinExporterEventSource.Log, ZipkinEndpointEnvVar, out var endpoint)) { this.Endpoint = endpoint; } - this.BatchExportProcessorOptions = defaultBatchOptions; + this.ExportProcessorType = defaultOptions.ExportProcessorType; + this.BatchExportProcessorOptions = defaultOptions.BatchExportProcessorOptions; } /// diff --git a/src/OpenTelemetry/AssemblyInfo.cs b/src/OpenTelemetry/AssemblyInfo.cs index 46c323088a6..df9434b687d 100644 --- a/src/OpenTelemetry/AssemblyInfo.cs +++ b/src/OpenTelemetry/AssemblyInfo.cs @@ -10,6 +10,8 @@ [assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.HttpListener.Tests" + AssemblyInfo.PublicKey)] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Zipkin" + AssemblyInfo.PublicKey)] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Zipkin.Tests" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Hosting" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Hosting.Tests" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Tests" + AssemblyInfo.PublicKey)] diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/IntegrationTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/IntegrationTests.cs index 59de4f9d46c..51d1b6f4532 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/IntegrationTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/IntegrationTests.cs @@ -71,6 +71,7 @@ public void TraceExportResultIsSuccess(OtlpExportProtocol protocol, string endpo .AddSource(activitySourceName); builder.ConfigureBuilder((sp, builder) => OtlpTraceExporterHelperExtensions.AddOtlpTraceExporter( + name: null, serviceProvider: sp, builder: builder, exporterOptions: exporterOptions, @@ -239,6 +240,7 @@ public void LogExportResultIsSuccess(OtlpExportProtocol protocol, string endpoin }) .ConfigureBuilder((sp, builder) => OtlpLogExporterHelperExtensions.AddOtlpLogExporter( + name: null, sp, builder, exporterOptions, diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs index 84d3076500a..c2192dd03c9 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using Google.Protobuf.Collections; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.Transmission; using OpenTelemetry.Metrics; @@ -60,6 +61,67 @@ public void AddOtlpTraceExporterNamedOptionsSupported() Assert.Equal(1, namedExporterOptionsConfigureOptionsInvocations); } + [Theory] + [InlineData(true, null)] + [InlineData(false, null)] + [InlineData(true, "otlp")] + [InlineData(false, "otlp")] + public void AddOtlpTraceExporterBatchOptionsChangedTest(bool overrideDefaults, string? name) + { + using var sdk = OpenTelemetrySdk.Create(builder => builder + .WithTracing(tracing => tracing + .ConfigureServices(services => + { + services.Configure( + name, + o => + { + o.ExportProcessorType = ExportProcessorType.Simple; + o.BatchExportProcessorOptions.ScheduledDelayMilliseconds = 18; + }); + }) + .AddOtlpExporter( + name, + o => + { + if (overrideDefaults) + { + o.ExportProcessorType = ExportProcessorType.Batch; + o.BatchExportProcessorOptions = new() + { + ScheduledDelayMilliseconds = 10, + }; + } + }))); + + var tracerProvider = sdk.TracerProvider as TracerProviderSdk; + + Assert.NotNull(tracerProvider); + + if (overrideDefaults) + { + var batchProcessor = tracerProvider.Processor as BatchExportProcessor; + + Assert.NotNull(batchProcessor); + + Assert.Equal(10, batchProcessor.ScheduledDelayMilliseconds); + + var defaultOptions = sdk.Services.GetRequiredService>() + .Get(name); + + Assert.Equal( + ExportProcessorType.Batch, + defaultOptions.ExportProcessorType); + Assert.Equal( + 10, + defaultOptions.BatchExportProcessorOptions.ScheduledDelayMilliseconds); + } + else + { + Assert.NotNull(tracerProvider.Processor as SimpleExportProcessor); + } + } + [Fact] public void OtlpExporter_BadArgs() { diff --git a/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs b/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs index 01e40b66b16..233a82bfa76 100644 --- a/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs +++ b/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs @@ -11,6 +11,7 @@ using System.Text; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using OpenTelemetry.Exporter.Zipkin.Implementation; using OpenTelemetry.Resources; using OpenTelemetry.Tests; @@ -72,7 +73,7 @@ public void Dispose() } [Fact] - public void AddAddZipkinExporterNamedOptionsSupported() + public void AddZipkinExporterNamedOptionsSupported() { int defaultExporterOptionsConfigureOptionsInvocations = 0; int namedExporterOptionsConfigureOptionsInvocations = 0; @@ -92,6 +93,72 @@ public void AddAddZipkinExporterNamedOptionsSupported() Assert.Equal(1, namedExporterOptionsConfigureOptionsInvocations); } + [Theory] + [InlineData(true, null)] + [InlineData(false, null)] + [InlineData(true, "zipkin")] + [InlineData(false, "zipkin")] + public void AddZipkinExporterBatchOptionsChangedTest(bool overrideDefaults, string name) + { + using var sdk = OpenTelemetrySdk.Create(builder => builder + .WithTracing(tracing => tracing + .ConfigureServices(services => + { + services.Configure( + name, + o => + { + o.ExportProcessorType = ExportProcessorType.Simple; + o.BatchExportProcessorOptions.ScheduledDelayMilliseconds = 18; + }); + }) + .AddZipkinExporter( + name, + o => + { + if (overrideDefaults) + { + o.ExportProcessorType = ExportProcessorType.Batch; + o.BatchExportProcessorOptions = new() + { + ScheduledDelayMilliseconds = 10, + }; + } + }))); + + var tracerProvider = sdk.TracerProvider as TracerProviderSdk; + + Assert.NotNull(tracerProvider); + + if (overrideDefaults) + { + var batchProcessor = tracerProvider.Processor as BatchExportProcessor; + + Assert.NotNull(batchProcessor); + + Assert.Equal(10, batchProcessor.ScheduledDelayMilliseconds); + + var defaultOptions = sdk.Services.GetRequiredService>() + .Get(name); + + var zipkinOptions = sdk.Services.GetRequiredService>() + .Get(name); + + Assert.False( + ReferenceEquals(defaultOptions.BatchExportProcessorOptions, zipkinOptions.BatchExportProcessorOptions)); + Assert.Equal( + defaultOptions.ExportProcessorType, + zipkinOptions.ExportProcessorType); + Assert.Equal( + defaultOptions.BatchExportProcessorOptions.ScheduledDelayMilliseconds, + zipkinOptions.BatchExportProcessorOptions.ScheduledDelayMilliseconds); + } + else + { + Assert.NotNull(tracerProvider.Processor as SimpleExportProcessor); + } + } + [Fact] public void BadArgs() { From c43be00eeafd0d4233822f47a1f6cae9219a333f Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Wed, 24 Jul 2024 09:57:43 -0700 Subject: [PATCH 6/9] Tweak. --- src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt | 3 +-- src/OpenTelemetry/BatchExportProcessorOptions.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt index 6c0893bd722..3593da9d519 100644 --- a/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt @@ -1,4 +1,3 @@ -OpenTelemetry.BatchExportProcessorOptions.ApplyTo(OpenTelemetry.BatchExportProcessorOptions! other) -> void OpenTelemetry.ConcurrencyModes OpenTelemetry.ConcurrencyModes.Multithreaded = 2 -> OpenTelemetry.ConcurrencyModes OpenTelemetry.ConcurrencyModes.Reentrant = 1 -> OpenTelemetry.ConcurrencyModes @@ -28,4 +27,4 @@ static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddBatchExportProcess static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, string? name, OpenTelemetry.BaseExporter! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, string? name, System.Func!>! implementationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! -static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Func!>! implementationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! \ No newline at end of file +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddSimpleExportProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Func!>! implementationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! diff --git a/src/OpenTelemetry/BatchExportProcessorOptions.cs b/src/OpenTelemetry/BatchExportProcessorOptions.cs index a3611b24247..90ac9abb71e 100644 --- a/src/OpenTelemetry/BatchExportProcessorOptions.cs +++ b/src/OpenTelemetry/BatchExportProcessorOptions.cs @@ -37,7 +37,7 @@ public class BatchExportProcessorOptions /// cref="BatchExportProcessorOptions{T}"/> instance. /// /// . - public void ApplyTo(BatchExportProcessorOptions other) + internal void ApplyTo(BatchExportProcessorOptions other) { Guard.ThrowIfNull(other); From 932fd86667da409f7eb1b7ae7cfffa714ca9ca69 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Wed, 24 Jul 2024 11:48:11 -0700 Subject: [PATCH 7/9] Lint. --- docs/trace/customizing-the-sdk/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/trace/customizing-the-sdk/README.md b/docs/trace/customizing-the-sdk/README.md index 64d7411d858..e6de7f4e6d1 100644 --- a/docs/trace/customizing-the-sdk/README.md +++ b/docs/trace/customizing-the-sdk/README.md @@ -261,7 +261,7 @@ is built. ```csharp using OpenTelemetry; using OpenTelemetry.Trace; - + var tracerProvider = Sdk.CreateTracerProviderBuilder() .AddBatchExportProcessor(new MyExporter1()) .AddSimpleExportProcessor(new MyExporter2()) @@ -273,7 +273,7 @@ is built. ```csharp using OpenTelemetry; using OpenTelemetry.Trace; - + var tracerProvider = Sdk.CreateTracerProviderBuilder() .AddProcessor(new BatchActivityExportProcessor(new MyExporter1())) .AddProcessor(new SimpleActivityExportProcessor(new MyExporter2())) From 1e05a41ef4a0276ed73cb63f666086b120c3a710 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Wed, 24 Jul 2024 12:12:43 -0700 Subject: [PATCH 8/9] Fixes. --- .../ILogger/OpenTelemetryLoggerOptions.cs | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs index 5f7a303f12c..bc232a6df27 100644 --- a/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs +++ b/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs @@ -15,7 +15,7 @@ public class OpenTelemetryLoggerOptions : IDeferredLoggerProviderBuilder { internal readonly List>> ProcessorFactories = new(); internal ResourceBuilder? ResourceBuilder; - private readonly IServiceProvider? serviceProvider; + private readonly LoggerProviderBuilderSdk? innerBuilder; /// /// Initializes a new instance of the class. @@ -28,7 +28,7 @@ internal OpenTelemetryLoggerOptions(IServiceProvider serviceProvider) { Debug.Assert(serviceProvider != null, "serviceProvider was null"); - this.serviceProvider = serviceProvider; + this.innerBuilder = serviceProvider!.GetRequiredService(); } /// @@ -103,7 +103,14 @@ public OpenTelemetryLoggerOptions AddProcessor(BaseProcessor processo { Guard.ThrowIfNull(processor); - this.ProcessorFactories.Add(_ => processor); + if (this.innerBuilder != null) + { + this.innerBuilder.AddProcessor(processor); + } + else + { + this.ProcessorFactories.Add(_ => processor); + } return this; } @@ -119,7 +126,14 @@ public OpenTelemetryLoggerOptions AddProcessor( { Guard.ThrowIfNull(implementationFactory); - this.ProcessorFactories.Add(implementationFactory); + if (this.innerBuilder != null) + { + this.innerBuilder.AddProcessor(implementationFactory); + } + else + { + this.ProcessorFactories.Add(implementationFactory); + } return this; } @@ -135,7 +149,14 @@ public OpenTelemetryLoggerOptions SetResourceBuilder(ResourceBuilder resourceBui { Guard.ThrowIfNull(resourceBuilder); - this.ResourceBuilder = resourceBuilder; + if (this.innerBuilder != null) + { + this.innerBuilder.SetResourceBuilder(resourceBuilder); + } + else + { + this.ResourceBuilder = resourceBuilder; + } return this; } @@ -145,14 +166,10 @@ LoggerProviderBuilder IDeferredLoggerProviderBuilder.Configure( { Guard.ThrowIfNull(configure); - var sp = this.serviceProvider + var innerBuilder = this.innerBuilder ?? throw new NotSupportedException("Manually constructed OpenTelemetryLoggerOptions instances cannot be converted to LoggerProviderBuilder instances"); - var builder = sp.GetRequiredService(); - - configure(sp, builder); - - return builder; + return innerBuilder.ConfigureBuilder(configure); } internal OpenTelemetryLoggerOptions Copy() From 898c1a83625d1e0778543cfee18f7320bae6c4e6 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Wed, 24 Jul 2024 12:28:17 -0700 Subject: [PATCH 9/9] Fix file encoding. --- src/OpenTelemetry/SimpleMultithreadedExportProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenTelemetry/SimpleMultithreadedExportProcessor.cs b/src/OpenTelemetry/SimpleMultithreadedExportProcessor.cs index c33299cbba5..acc1832165f 100644 --- a/src/OpenTelemetry/SimpleMultithreadedExportProcessor.cs +++ b/src/OpenTelemetry/SimpleMultithreadedExportProcessor.cs @@ -1,4 +1,4 @@ -// Copyright The OpenTelemetry Authors +// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 using OpenTelemetry.Internal;