Skip to content

Commit

Permalink
Implement TracerProvider Shutdown (#1489)
Browse files Browse the repository at this point in the history
* Add Shutdown method to TracerProvider

* Updated CHANGELOG.md

* Updated the PublicAPI.Unshipped txt files to include the TracerProvider Shutdown andOnShutdown methods

* Updated the OnShutdown method to move listener dispose after processor dispose

* Fixed build issues

* Address PR changes

* Added Instrumentations Dispoe to TracerProviderSdk OnShutdown method

Co-authored-by: Cijo Thomas <[email protected]>
  • Loading branch information
utpilla and cijothomas authored Nov 13, 2020
1 parent 6cc8e44 commit 941a0b9
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ static OpenTelemetry.SuppressInstrumentationScope.Enter() -> int
static OpenTelemetry.Trace.SamplingResult.operator !=(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool
static OpenTelemetry.Trace.SamplingResult.operator ==(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool
static OpenTelemetry.Trace.TracerProviderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProvider provider, OpenTelemetry.BaseProcessor<System.Diagnostics.Activity> processor) -> OpenTelemetry.Trace.TracerProvider
static OpenTelemetry.Trace.TracerProviderExtensions.Shutdown(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool
virtual OpenTelemetry.BaseExporter<T>.Dispose(bool disposing) -> void
virtual OpenTelemetry.BaseExporter<T>.OnShutdown(int timeoutMilliseconds) -> bool
virtual OpenTelemetry.BaseProcessor<T>.Dispose(bool disposing) -> void
Expand Down
1 change: 1 addition & 0 deletions src/OpenTelemetry/.publicApi/net46/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ static OpenTelemetry.SuppressInstrumentationScope.Enter() -> int
static OpenTelemetry.Trace.SamplingResult.operator !=(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool
static OpenTelemetry.Trace.SamplingResult.operator ==(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool
static OpenTelemetry.Trace.TracerProviderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProvider provider, OpenTelemetry.BaseProcessor<System.Diagnostics.Activity> processor) -> OpenTelemetry.Trace.TracerProvider
static OpenTelemetry.Trace.TracerProviderExtensions.Shutdown(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool
virtual OpenTelemetry.BaseExporter<T>.Dispose(bool disposing) -> void
virtual OpenTelemetry.BaseExporter<T>.OnShutdown(int timeoutMilliseconds) -> bool
virtual OpenTelemetry.BaseProcessor<T>.Dispose(bool disposing) -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ static OpenTelemetry.SuppressInstrumentationScope.Enter() -> int
static OpenTelemetry.Trace.SamplingResult.operator !=(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool
static OpenTelemetry.Trace.SamplingResult.operator ==(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool
static OpenTelemetry.Trace.TracerProviderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProvider provider, OpenTelemetry.BaseProcessor<System.Diagnostics.Activity> processor) -> OpenTelemetry.Trace.TracerProvider
static OpenTelemetry.Trace.TracerProviderExtensions.Shutdown(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool
virtual OpenTelemetry.BaseExporter<T>.Dispose(bool disposing) -> void
virtual OpenTelemetry.BaseExporter<T>.OnShutdown(int timeoutMilliseconds) -> bool
virtual OpenTelemetry.BaseProcessor<T>.Dispose(bool disposing) -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ static OpenTelemetry.SuppressInstrumentationScope.Enter() -> int
static OpenTelemetry.Trace.SamplingResult.operator !=(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool
static OpenTelemetry.Trace.SamplingResult.operator ==(OpenTelemetry.Trace.SamplingResult decision1, OpenTelemetry.Trace.SamplingResult decision2) -> bool
static OpenTelemetry.Trace.TracerProviderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProvider provider, OpenTelemetry.BaseProcessor<System.Diagnostics.Activity> processor) -> OpenTelemetry.Trace.TracerProvider
static OpenTelemetry.Trace.TracerProviderExtensions.Shutdown(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool
virtual OpenTelemetry.BaseExporter<T>.Dispose(bool disposing) -> void
virtual OpenTelemetry.BaseExporter<T>.OnShutdown(int timeoutMilliseconds) -> bool
virtual OpenTelemetry.BaseProcessor<T>.Dispose(bool disposing) -> void
Expand Down
2 changes: 2 additions & 0 deletions src/OpenTelemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* `ActivitySourceAdapter` supports setting `ActivitySource` for Activities
created without `ActivitySource`.
([#1515](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1515/))
* Implemented Shutdown for TracerProvider
([#1489](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1489))

## 0.8.0-beta.1

Expand Down
15 changes: 15 additions & 0 deletions src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ public void SelfDiagnosticsFileCreateException(string logDirectory, Exception ex
}
}

[NonEvent]
public void TracerProviderException(string evnt, Exception ex)
{
if (this.IsEnabled(EventLevel.Warning, (EventKeywords)(-1)))
{
this.TracerProviderException(evnt, ex.ToInvariantString());
}
}

[Event(1, Message = "Span processor queue size reached maximum. Throttling spans.", Level = EventLevel.Warning)]
public void SpanProcessorQueueIsExhausted()
{
Expand Down Expand Up @@ -272,6 +281,12 @@ public void ResourceDetectorFailed(string resourceDetector, string issue)
this.WriteEvent(27, resourceDetector, issue);
}

[Event(28, Message = "Unknown error in TracerProvider '{0}': '{1}'.", Level = EventLevel.Warning)]
public void TracerProviderException(string evnt, string ex)
{
this.WriteEvent(28, evnt, ex);
}

#if DEBUG
public class OpenTelemetryEventListener : EventListener
{
Expand Down
54 changes: 54 additions & 0 deletions src/OpenTelemetry/Trace/TracerProviderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

using System;
using System.Diagnostics;
using System.Threading;
using OpenTelemetry.Internal;

namespace OpenTelemetry.Trace
{
Expand All @@ -40,5 +42,57 @@ public static TracerProvider AddProcessor(this TracerProvider provider, BaseProc

return provider;
}

/// <summary>
/// Attempts to shutdown the TracerProviderSdk, blocks the current thread until
/// shutdown completed or timed out.
/// </summary>
/// <param name="provider">TracerProviderSdk instance on which Shutdown will be called.</param>
/// <param name="timeoutMilliseconds">
/// The number of milliseconds to wait, or <c>Timeout.Infinite</c> to
/// wait indefinitely.
/// </param>
/// <returns>
/// Returns <c>true</c> when shutdown succeeded; otherwise, <c>false</c>.
/// </returns>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown when the <c>timeoutMilliseconds</c> is smaller than -1.
/// </exception>
/// <remarks>
/// This function guarantees thread-safety. Only the first call will
/// win, subsequent calls will be no-op.
/// </remarks>
public static bool Shutdown(this TracerProvider provider, int timeoutMilliseconds = Timeout.Infinite)
{
if (provider == null)
{
throw new ArgumentNullException(nameof(provider));
}

if (provider is TracerProviderSdk tracerProviderSdk)
{
if (timeoutMilliseconds < 0 && timeoutMilliseconds != Timeout.Infinite)
{
throw new ArgumentOutOfRangeException(nameof(timeoutMilliseconds), timeoutMilliseconds, "timeoutMilliseconds should be non-negative.");
}

if (Interlocked.Increment(ref tracerProviderSdk.ShutdownCount) > 1)
{
return false; // shutdown already called
}

try
{
return tracerProviderSdk.OnShutdown(timeoutMilliseconds);
}
catch (Exception ex)
{
OpenTelemetrySdkEventSource.Log.TracerProviderException(nameof(tracerProviderSdk.OnShutdown), ex);
return false;
}
}

return true;
}
}
}
38 changes: 38 additions & 0 deletions src/OpenTelemetry/Trace/TracerProviderSdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Threading;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;

namespace OpenTelemetry.Trace
{
internal class TracerProviderSdk : TracerProvider
{
internal int ShutdownCount;

private readonly List<object> instrumentations = new List<object>();
private readonly ActivityListener listener;
private readonly Sampler sampler;
Expand Down Expand Up @@ -196,6 +199,41 @@ internal TracerProviderSdk AddProcessor(BaseProcessor<Activity> processor)
return this;
}

/// <summary>
/// Called by <c>Shutdown</c>. This function should block the current
/// thread until shutdown completed or timed out.
/// </summary>
/// <param name="timeoutMilliseconds">
/// The number of milliseconds to wait, or <c>Timeout.Infinite</c> to
/// wait indefinitely.
/// </param>
/// <returns>
/// Returns <c>true</c> when shutdown succeeded; otherwise, <c>false</c>.
/// </returns>
/// <remarks>
/// This function is called synchronously on the thread which made the
/// first call to <c>Shutdown</c>. This function should not throw
/// exceptions.
/// </remarks>
internal bool OnShutdown(int timeoutMilliseconds)
{
// TO DO Put OnShutdown logic in a task to run within the user provider timeOutMilliseconds
bool? result;
if (this.instrumentations != null)
{
foreach (var item in this.instrumentations)
{
(item as IDisposable)?.Dispose();
}

this.instrumentations.Clear();
}

result = this.processor?.Shutdown(timeoutMilliseconds);
this.listener?.Dispose();
return result ?? true;
}

protected override void Dispose(bool disposing)
{
if (this.instrumentations != null)
Expand Down

0 comments on commit 941a0b9

Please sign in to comment.