Step 1 - Use new Activity to Replace OT Span (#660)

This commit is contained in:
Cijo Thomas 2020-05-13 12:21:28 -07:00 committed by GitHub
parent 92963a384d
commit 44b3a438d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 801 additions and 6 deletions

View File

@ -37,7 +37,7 @@ namespace Samples
/// <param name="args">Arguments from command line.</param>
public static void Main(string[] args)
{
Parser.Default.ParseArguments<JaegerOptions, ZipkinOptions, PrometheusOptions, HttpClientOptions, ZPagesOptions, ConsoleOptions, OtlpOptions>(args)
Parser.Default.ParseArguments<JaegerOptions, ZipkinOptions, PrometheusOptions, HttpClientOptions, ZPagesOptions, ConsoleOptions, ConsoleActivityOptions, OtlpOptions>(args)
.MapResult(
(JaegerOptions options) => TestJaeger.Run(options.Host, options.Port),
(ZipkinOptions options) => TestZipkin.Run(options.Uri),
@ -46,6 +46,7 @@ namespace Samples
(RedisOptions options) => TestRedis.Run(options.Uri),
(ZPagesOptions options) => TestZPages.Run(),
(ConsoleOptions options) => TestConsole.Run(options),
(ConsoleActivityOptions options) => TestConsoleActivity.Run(options),
(OtlpOptions options) => TestOtlp.Run(options.Endpoint),
errs => 1);
@ -105,10 +106,17 @@ namespace Samples
[Verb("console", HelpText = "Specify the options required to test console exporter")]
internal class ConsoleOptions
{
[Option('p', "pretty", HelpText = "Specify if the output should be pretty printed (default: false)", Default = false)]
[Option('p', "pretty", HelpText = "Specify if the output should be pretty printed (default: true)", Default = true)]
public bool Pretty { get; set; }
}
[Verb("consoleactivity", HelpText = "Specify the options required to test console activity exporter")]
internal class ConsoleActivityOptions
{
[Option('p', "displayasjson", HelpText = "Specify if the output should be displayed as json or not (default: false)", Default = false)]
public bool DisplayAsJson { get; set; }
}
[Verb("otlp", HelpText = "Specify the options required to test OpenTelemetry Protocol (OTLP)")]
internal class OtlpOptions
{

View File

@ -1,8 +1,22 @@
// <auto-generated/>
// <copyright file="TestConsole.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using OpenTelemetry.Trace.Configuration;
using OpenTelemetry.Exporter.Console;
using OpenTelemetry.Trace;
using OpenTelemetry.Trace.Configuration;
namespace Samples
{
@ -13,14 +27,15 @@ namespace Samples
// map test project settings to ConsoleExporterSetting
var exporterOptions = new ConsoleExporterOptions
{
Pretty = options.Pretty
Pretty = options.Pretty,
};
// create exporter
var exporter = new ConsoleExporter(exporterOptions);
// Create tracer
using var tracerFactory = TracerFactory.Create(builder => {
using var tracerFactory = TracerFactory.Create(builder =>
{
builder.AddProcessorPipeline(p => p.SetExporter(exporter));
});
var tracer = tracerFactory.GetTracer("console-test");

View File

@ -0,0 +1,89 @@
// <copyright file="TestConsoleActivity.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Diagnostics;
using OpenTelemetry.Exporter.Console;
using OpenTelemetry.Trace.Configuration;
namespace Samples
{
internal class TestConsoleActivity
{
internal static object Run(ConsoleActivityOptions options)
{
// Enable OpenTelemetry for the source "MyCompany.MyProduct.MyWebServer"
// and use Console exporter
OpenTelemetrySdk.EnableOpenTelemetry(
(builder) => builder.AddActivitySource("MyCompany.MyProduct.MyWebServer")
.UseConsoleActivityExporter(opt => opt.DisplayAsJson = options.DisplayAsJson));
// The above line is required only in Applications
// which decide to use OT.
// Libraries would simply write the following lines of code to
// emit activities, which are the .NET representation of OT Spans.
var source = new ActivitySource("MyCompany.MyProduct.MyWebServer");
// The below commented out line shows more likely code in a real world webserver.
// using (var parent = source.StartActivity("HttpIn", ActivityKind.Server, HttpContext.Request.Headers["traceparent"] ))
using (var parent = source.StartActivity("HttpIn", ActivityKind.Server))
{
// TagNames can follow the OT guidelines
// from https://github.com/open-telemetry/opentelemetry-specification/tree/master/specification/trace/semantic_conventions
parent?.AddTag("http.method", "GET");
parent?.AddTag("http.host", "MyHostName");
if (parent != null)
{
parent.DisplayName = "HttpIn DisplayName";
}
try
{
// Actual code to achieve the purpose of the library.
// For websebserver example, this would be calling
// user middlware pipeline.
// There can be child activities.
// In this example HttpOut is a child of HttpIn.
using (var child = source.StartActivity("HttpOut", ActivityKind.Client))
{
child?.AddTag("http.url", "www.mydependencyapi.com");
try
{
// do actual work.
child?.AddEvent(new ActivityEvent("sample activity event."));
child?.AddTag("http.status_code", "200");
}
catch (Exception)
{
child?.AddTag("http.status_code", "500");
}
}
parent?.AddTag("http.status_code", "200");
}
catch (Exception)
{
parent?.AddTag("http.status_code", "500");
}
}
return null;
}
}
}

View File

@ -0,0 +1,97 @@
// <copyright file="ConsoleActivityExporter.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using OpenTelemetry.Trace.Export;
namespace OpenTelemetry.Exporter.Console
{
public class ConsoleActivityExporter : ActivityExporter
{
private readonly JsonSerializerOptions serializerOptions;
private bool displayAsJson;
public ConsoleActivityExporter(ConsoleActivityExporterOptions options)
{
this.serializerOptions = new JsonSerializerOptions()
{
WriteIndented = true,
};
this.displayAsJson = options.DisplayAsJson;
this.serializerOptions.Converters.Add(new JsonStringEnumConverter());
this.serializerOptions.Converters.Add(new ActivitySpanIdConverter());
this.serializerOptions.Converters.Add(new ActivityTraceIdConverter());
}
public override Task<ExportResult> ExportAsync(IEnumerable<Activity> activityBatch, CancellationToken cancellationToken)
{
foreach (var activity in activityBatch)
{
if (this.displayAsJson)
{
System.Console.WriteLine(JsonSerializer.Serialize(activity, this.serializerOptions));
}
else
{
System.Console.WriteLine("Activity ID - " + activity.Id);
if (!string.IsNullOrEmpty(activity.ParentId))
{
System.Console.WriteLine("Activity ParentId - " + activity.ParentId);
}
System.Console.WriteLine("Activity OperationName - " + activity.OperationName);
System.Console.WriteLine("Activity DisplayName - " + activity.DisplayName);
System.Console.WriteLine("Activity StartTime - " + activity.StartTimeUtc);
System.Console.WriteLine("Activity Duration - " + activity.Duration);
if (activity.Tags.Count() > 0)
{
System.Console.WriteLine("Activity Tags");
foreach (var tag in activity.Tags)
{
System.Console.WriteLine($"\t {tag.Key} : {tag.Value}");
}
}
if (activity.Events.Any())
{
System.Console.WriteLine("Activity Events");
foreach (var activityEvent in activity.Events)
{
System.Console.WriteLine($"Event Name: {activityEvent.Name} TimeStamp: {activityEvent.Timestamp}");
}
}
System.Console.WriteLine("\n");
}
}
return Task.FromResult(ExportResult.Success);
}
public override Task ShutdownAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}

View File

@ -0,0 +1,23 @@
// <copyright file="ConsoleActivityExporterOptions.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
namespace OpenTelemetry.Exporter.Console
{
public class ConsoleActivityExporterOptions
{
public bool DisplayAsJson { get; set; }
}
}

View File

@ -0,0 +1,48 @@
// <copyright file="OpenTelemetryBuilderExtensions.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using OpenTelemetry.Trace.Configuration;
namespace OpenTelemetry.Exporter.Console
{
public static class OpenTelemetryBuilderExtensions
{
/// <summary>
/// Registers a ConsoleActivity exporter.
/// </summary>
/// <param name="builder">Open Telemetry builder to use.</param>
/// <param name="configure">Exporter configuration options.</param>
/// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns>
public static OpenTelemetryBuilder UseConsoleActivityExporter(this OpenTelemetryBuilder builder, Action<ConsoleActivityExporterOptions> configure)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}
var exporterOptions = new ConsoleActivityExporterOptions();
configure(exporterOptions);
var consoleExporter = new ConsoleActivityExporter(exporterOptions);
return builder.SetProcessorPipeline(pipeline => pipeline.SetExporter(consoleExporter));
}
}
}

View File

@ -0,0 +1,126 @@
// <copyright file="ActivityProcessorPipelineBuilder.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Collections.Generic;
using OpenTelemetry.Trace.Export;
namespace OpenTelemetry.Trace.Configuration
{
/// <summary>
/// Configures exporting pipeline with chains of processors and exporter.
/// </summary>
public class ActivityProcessorPipelineBuilder
{
private Func<ActivityExporter, ActivityProcessor> lastProcessorFactory;
private List<Func<ActivityProcessor, ActivityProcessor>> processorChain;
internal ActivityProcessorPipelineBuilder()
{
}
internal ActivityExporter Exporter { get; private set; }
internal List<ActivityProcessor> Processors { get; private set; }
/// <summary>
/// Adds chained processor to the pipeline. Processors are executed in the order they were added.
/// </summary>
/// <param name="processorFactory">Function that creates processor from the next one.</param>
/// <returns>Returns <see cref="ActivityProcessorPipelineBuilder"/>.</returns>
public ActivityProcessorPipelineBuilder AddProcessor(Func<ActivityProcessor, ActivityProcessor> processorFactory)
{
if (processorFactory == null)
{
throw new ArgumentNullException(nameof(processorFactory));
}
if (this.processorChain == null)
{
this.processorChain = new List<Func<ActivityProcessor, ActivityProcessor>>();
}
this.processorChain.Add(processorFactory);
return this;
}
/// <summary>
/// Configures last processor that invokes exporter. When not set, <see cref="SimpleActivityProcessor"/> is used.
/// </summary>
/// <param name="processorFactory">Factory that creates exporting processor from the exporter.</param>
/// <returns>Returns <see cref="ActivityProcessorPipelineBuilder"/>.</returns>
public ActivityProcessorPipelineBuilder SetExportingProcessor(Func<ActivityExporter, ActivityProcessor> processorFactory)
{
this.lastProcessorFactory = processorFactory ?? throw new ArgumentNullException(nameof(processorFactory));
return this;
}
/// <summary>
/// Configures exporter.
/// </summary>
/// <param name="exporter">Exporter instance.</param>
/// <returns>Returns <see cref="ActivityProcessorPipelineBuilder"/>.</returns>
public ActivityProcessorPipelineBuilder SetExporter(ActivityExporter exporter)
{
this.Exporter = exporter ?? throw new ArgumentNullException(nameof(exporter));
return this;
}
internal ActivityProcessor Build()
{
this.Processors = new List<ActivityProcessor>();
ActivityProcessor exportingProcessor = null;
// build or create default exporting processor
if (this.lastProcessorFactory != null)
{
exportingProcessor = this.lastProcessorFactory.Invoke(this.Exporter);
this.Processors.Add(exportingProcessor);
}
else if (this.Exporter != null)
{
exportingProcessor = new SimpleActivityProcessor(this.Exporter);
this.Processors.Add(exportingProcessor);
}
if (this.processorChain == null)
{
// if there is no chain, return exporting processor.
if (exportingProcessor == null)
{
exportingProcessor = new NoopActivityProcessor();
this.Processors.Add(exportingProcessor);
}
return exportingProcessor;
}
var next = exportingProcessor;
// build chain from the end to the beginning
for (int i = this.processorChain.Count - 1; i >= 0; i--)
{
next = this.processorChain[i].Invoke(next);
this.Processors.Add(next);
}
// return the last processor in the chain - it will be called first
return this.Processors[this.Processors.Count - 1];
}
}
}

View File

@ -0,0 +1,71 @@
// <copyright file="OpenTelemetryBuilder.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Collections.Generic;
using OpenTelemetry.Resources;
namespace OpenTelemetry.Trace.Configuration
{
/// <summary>
/// Build OpenTelemetry pipeline.
/// Currently supports a single processing pipeline, and any number of activity source names
/// to subscribe to.
/// </summary>
public class OpenTelemetryBuilder
{
internal OpenTelemetryBuilder()
{
}
internal ActivityProcessorPipelineBuilder ProcessingPipeline { get; private set; }
internal HashSet<string> ActivitySourceNames { get; private set; }
/// <summary>
/// Sets processing and exporting pipeline.
/// </summary>
/// <param name="configure">Function that configures pipeline.</param>
/// <returns>Returns <see cref="OpenTelemetryBuilder"/> for chaining.</returns>
public OpenTelemetryBuilder SetProcessorPipeline(Action<ActivityProcessorPipelineBuilder> configure)
{
if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}
var pipelineBuilder = new ActivityProcessorPipelineBuilder();
configure(pipelineBuilder);
this.ProcessingPipeline = pipelineBuilder;
return this;
}
/// <summary>
/// Adds given activitysource name to the list of subscribed sources.
/// </summary>
/// <param name="activitySourceName">Activity source name.</param>
/// <returns>Returns <see cref="OpenTelemetryBuilder"/> for chaining.</returns>
public OpenTelemetryBuilder AddActivitySource(string activitySourceName)
{
if (this.ActivitySourceNames == null)
{
this.ActivitySourceNames = new HashSet<string>();
}
this.ActivitySourceNames.Add(activitySourceName.ToUpperInvariant());
return this;
}
}
}

View File

@ -0,0 +1,76 @@
// <copyright file="OpenTelemetrySdk.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Diagnostics;
using OpenTelemetry.Trace.Export;
namespace OpenTelemetry.Trace.Configuration
{
public class OpenTelemetrySdk
{
static OpenTelemetrySdk()
{
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
Activity.ForceDefaultIdFormat = true;
}
/// <summary>
/// Enables OpenTelemetry.
/// </summary>
/// <param name="configureOpenTelemetryBuilder">Function that configures OpenTelemetryBuilder.</param>
/// <remarks>
/// Basic implementation only. Most logic from TracerBuilder will be ported here.
/// </remarks>
public static void EnableOpenTelemetry(Action<OpenTelemetryBuilder> configureOpenTelemetryBuilder)
{
var openTelemetryBuilder = new OpenTelemetryBuilder();
configureOpenTelemetryBuilder(openTelemetryBuilder);
ActivityProcessor activityProcessor;
if (openTelemetryBuilder.ProcessingPipeline == null)
{
// if there are no pipelines are configured, use noop processor
activityProcessor = new NoopActivityProcessor();
}
else
{
activityProcessor = openTelemetryBuilder.ProcessingPipeline.Build();
}
// This is what subscribes to Activities.
// Think of this as the replacement for DiagnosticListener.AllListeners.Subscribe(onNext => diagnosticListener.Subscribe(..));
ActivityListener listener = new ActivityListener
{
// Callback when Activity is started.
ActivityStarted = activityProcessor.OnStart,
// Callback when Activity is started.
ActivityStopped = activityProcessor.OnEnd,
// Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to
// or not
ShouldListenTo = (activitySource) => openTelemetryBuilder.ActivitySourceNames.Contains(activitySource.Name.ToUpperInvariant()),
// The following parameters are not used now.
GetRequestedDataUsingParentId = (ref ActivityCreationOptions<string> options) => ActivityDataRequest.AllData,
GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> options) => ActivityDataRequest.AllData,
};
ActivitySource.AddActivityListener(listener);
}
}
}

View File

@ -0,0 +1,61 @@
// <copyright file="ActivityExporter.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace OpenTelemetry.Trace.Export
{
/// <summary>
/// ActivityExporter base class.
/// </summary>
public abstract class ActivityExporter
{
public enum ExportResult
{
/// <summary>
/// Batch is successfully exported.
/// </summary>
Success = 0,
/// <summary>
/// Batch export failed. Caller must not retry.
/// </summary>
FailedNotRetryable = 1,
/// <summary>
/// Batch export failed transiently. Caller should record error and may retry.
/// </summary>
FailedRetryable = 2,
}
/// <summary>
/// Exports batch of activities asynchronously.
/// </summary>
/// <param name="batch">Batch of activities to export.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Result of export.</returns>
public abstract Task<ExportResult> ExportAsync(IEnumerable<Activity> batch, CancellationToken cancellationToken);
/// <summary>
/// Shuts down exporter asynchronously.
/// </summary>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Returns <see cref="Task"/>.</returns>
public abstract Task ShutdownAsync(CancellationToken cancellationToken);
}
}

View File

@ -0,0 +1,46 @@
// <copyright file="ActivityProcessor.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace OpenTelemetry.Trace.Export
{
/// <summary>
/// Activity processor base class.
/// </summary>
public abstract class ActivityProcessor
{
/// <summary>
/// Activity start hook.
/// </summary>
/// <param name="activity">Instance of activity to process.</param>
public abstract void OnStart(Activity activity);
/// <summary>
/// Activity end hook.
/// </summary>
/// <param name="activity">Instance of activity to process.</param>
public abstract void OnEnd(Activity activity);
/// <summary>
/// Shuts down Activity processor asynchronously.
/// </summary>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Returns <see cref="Task"/>.</returns>
public abstract Task ShutdownAsync(CancellationToken cancellationToken);
}
}

View File

@ -0,0 +1,38 @@
// <copyright file="NoopActivityProcessor.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace OpenTelemetry.Trace.Export
{
internal sealed class NoopActivityProcessor : ActivityProcessor
{
public override void OnStart(Activity activity)
{
}
public override void OnEnd(Activity activity)
{
}
public override Task ShutdownAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}

View File

@ -0,0 +1,97 @@
// <copyright file="SimpleActivityProcessor.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Trace.Export
{
/// <summary>
/// Implements simple activity processor that exports activities in OnEnd call without batching.
/// </summary>
public class SimpleActivityProcessor : ActivityProcessor, IDisposable
{
private readonly ActivityExporter exporter;
private bool disposed = false;
/// <summary>
/// Initializes a new instance of the <see cref="SimpleActivityProcessor"/> class.
/// </summary>
/// <param name="exporter">Activity exporter instance.</param>
public SimpleActivityProcessor(ActivityExporter exporter)
{
this.exporter = exporter ?? throw new ArgumentNullException(nameof(exporter));
}
/// <inheritdoc />
public override void OnStart(Activity activity)
{
}
/// <inheritdoc />
public override void OnEnd(Activity activity)
{
try
{
// do not await, just start export
// it can still throw in synchronous part
_ = this.exporter.ExportAsync(new[] { activity }, CancellationToken.None);
}
catch (Exception ex)
{
OpenTelemetrySdkEventSource.Log.SpanProcessorException("OnEnd", ex);
}
}
/// <inheritdoc />
public override Task ShutdownAsync(CancellationToken cancellationToken)
{
if (!this.disposed)
{
this.disposed = true;
return this.exporter.ShutdownAsync(cancellationToken);
}
return Task.CompletedTask;
}
public void Dispose()
{
this.Dispose(true);
}
protected virtual void Dispose(bool isDisposing)
{
if (isDisposing)
{
if (this.exporter is IDisposable disposableExporter)
{
try
{
disposableExporter.Dispose();
}
catch (Exception e)
{
OpenTelemetrySdkEventSource.Log.SpanProcessorException("Dispose", e);
}
}
}
}
}
}