diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleExporter.cs b/src/OpenTelemetry.Exporter.Console/ConsoleExporter.cs index 0c973d131b4..dcdb573f2a9 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleExporter.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleExporter.cs @@ -27,10 +27,10 @@ namespace OpenTelemetry.Exporter.Console { - public class ConsoleExporter : ActivityExporter + public class ConsoleExporter : ActivityExporterSync { private readonly JsonSerializerOptions serializerOptions; - private bool displayAsJson; + private readonly bool displayAsJson; public ConsoleExporter(ConsoleExporterOptions options) { @@ -46,9 +46,9 @@ public ConsoleExporter(ConsoleExporterOptions options) this.serializerOptions.Converters.Add(new ActivityTraceIdConverter()); } - public override Task ExportAsync(IEnumerable activityBatch, CancellationToken cancellationToken) + public override ExportResultSync Export(IEnumerable batch) { - foreach (var activity in activityBatch) + foreach (var activity in batch) { if (this.displayAsJson) { @@ -127,12 +127,7 @@ public override Task ExportAsync(IEnumerable activityBat } } - return Task.FromResult(ExportResult.Success); - } - - public override Task ShutdownAsync(CancellationToken cancellationToken) - { - return Task.CompletedTask; + return ExportResultSync.Success; } } } diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs index 897e073d9a9..0f2e38693aa 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleExporterHelperExtensions.cs @@ -36,7 +36,7 @@ public static TracerProviderBuilder AddConsoleExporter(this TracerProviderBuilde var options = new ConsoleExporterOptions(); configure?.Invoke(options); - return builder.AddProcessor(new SimpleActivityProcessor(new ConsoleExporter(options))); + return builder.AddProcessor(new SimpleExportActivityProcessor(new ConsoleExporter(options))); } } } diff --git a/src/OpenTelemetry/Trace/ActivityExporterSync.cs b/src/OpenTelemetry/Trace/ActivityExporterSync.cs index f2bcb97c910..7d6954b6dfa 100644 --- a/src/OpenTelemetry/Trace/ActivityExporterSync.cs +++ b/src/OpenTelemetry/Trace/ActivityExporterSync.cs @@ -46,7 +46,7 @@ public abstract class ActivityExporterSync : IDisposable /// /// Batch of activities to export. /// Result of export. - public abstract ExportResult Export(IEnumerable batch); + public abstract ExportResultSync Export(IEnumerable batch); /// /// Shuts down the exporter. diff --git a/src/OpenTelemetry/Trace/ReentrantExportActivityProcessor.cs b/src/OpenTelemetry/Trace/ReentrantExportActivityProcessor.cs new file mode 100644 index 00000000000..f549ae070c8 --- /dev/null +++ b/src/OpenTelemetry/Trace/ReentrantExportActivityProcessor.cs @@ -0,0 +1,93 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Trace +{ + /// + /// Implements activity processor that exports at each OnEnd call without synchronization. + /// + public class ReentrantExportActivityProcessor : ActivityProcessor + { + private readonly ActivityExporterSync exporter; + private bool stopped; + + /// + /// Initializes a new instance of the class. + /// + /// Activity exporter instance. + public ReentrantExportActivityProcessor(ActivityExporterSync exporter) + { + this.exporter = exporter ?? throw new ArgumentNullException(nameof(exporter)); + } + + /// + public override void OnEnd(Activity activity) + { + try + { + // TODO: avoid heap allocation + _ = this.exporter.Export(new[] { activity }); + } + catch (Exception ex) + { + OpenTelemetrySdkEventSource.Log.SpanProcessorException(nameof(this.OnEnd), ex); + } + } + + /// + public override Task ShutdownAsync(CancellationToken cancellationToken) + { + if (!this.stopped) + { + this.exporter.Shutdown(); + this.stopped = true; + } + +#if NET452 + return Task.FromResult(0); +#else + return Task.CompletedTask; +#endif + } + + /// + /// Releases the unmanaged resources used by this class and optionally releases the managed resources. + /// + /// to release both managed and unmanaged resources; to release only unmanaged resources. + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + try + { + this.exporter.Dispose(); + } + catch (Exception ex) + { + OpenTelemetrySdkEventSource.Log.SpanProcessorException(nameof(this.Dispose), ex); + } + } + } + } +} diff --git a/src/OpenTelemetry/Trace/SimpleExportActivityProcessor.cs b/src/OpenTelemetry/Trace/SimpleExportActivityProcessor.cs index ae103d41cf1..2eb536ed654 100644 --- a/src/OpenTelemetry/Trace/SimpleExportActivityProcessor.cs +++ b/src/OpenTelemetry/Trace/SimpleExportActivityProcessor.cs @@ -23,70 +23,27 @@ namespace OpenTelemetry.Trace { /// - /// Implements simple activity processor that exports activities in OnEnd call without batching. + /// Implements activity processor that exports at each OnEnd call. /// - public class SimpleExportActivityProcessor : ActivityProcessor + public class SimpleExportActivityProcessor : ReentrantExportActivityProcessor { - private readonly ActivityExporterSync exporter; - private bool stopped; + private readonly object lck = new object(); /// /// Initializes a new instance of the class. /// /// Activity exporter instance. public SimpleExportActivityProcessor(ActivityExporterSync exporter) + : base(exporter) { - this.exporter = exporter ?? throw new ArgumentNullException(nameof(exporter)); } /// public override void OnEnd(Activity activity) { - try + lock (this.lck) { - // TODO: avoid heap allocation - _ = this.exporter.Export(new[] { activity }); - } - catch (Exception ex) - { - OpenTelemetrySdkEventSource.Log.SpanProcessorException(nameof(this.OnEnd), ex); - } - } - - /// - public override Task ShutdownAsync(CancellationToken cancellationToken) - { - if (!this.stopped) - { - this.exporter.Shutdown(); - this.stopped = true; - } - -#if NET452 - return Task.FromResult(0); -#else - return Task.CompletedTask; -#endif - } - - /// - /// Releases the unmanaged resources used by this class and optionally releases the managed resources. - /// - /// to release both managed and unmanaged resources; to release only unmanaged resources. - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - - if (disposing) - { - try - { - this.exporter.Dispose(); - } - catch (Exception ex) - { - OpenTelemetrySdkEventSource.Log.SpanProcessorException(nameof(this.Dispose), ex); - } + base.OnEnd(activity); } } }