From 3083c624672f0a72236a3b8dbafd4962892cd679 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 24 Apr 2018 23:49:08 -0500 Subject: [PATCH] added ThreadLocalScopeManager --- src/OpenTracing/Util/ThreadLocalScope.cs | 42 +++++++++++++++++++ .../Util/ThreadLocalScopeManager.cs | 30 +++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/OpenTracing/Util/ThreadLocalScope.cs create mode 100644 src/OpenTracing/Util/ThreadLocalScopeManager.cs diff --git a/src/OpenTracing/Util/ThreadLocalScope.cs b/src/OpenTracing/Util/ThreadLocalScope.cs new file mode 100644 index 0000000..680c5f7 --- /dev/null +++ b/src/OpenTracing/Util/ThreadLocalScope.cs @@ -0,0 +1,42 @@ +namespace OpenTracing.Util +{ + /// + /// + /// A primitive that relies on thread local storage for + /// managing active scopes. Intended to be used in systems where multiple logical, + /// related operations are all executed in the same thread albeit at different times. + /// + public class ThreadLocalScope : IScope + { + private readonly ThreadLocalScopeManager _scopeManager; + private readonly bool _finishOnDispose; + private readonly IScope _scopeToRestore; + + public ThreadLocalScope(ThreadLocalScopeManager scopeManager, ISpan wrappedSpan, bool finishOnDispose) + { + _scopeManager = scopeManager; + Span = wrappedSpan; + _finishOnDispose = finishOnDispose; + _scopeToRestore = scopeManager.Active; + scopeManager.Active = this; + } + + public void Dispose() + { + if (_scopeManager.Active != this) + { + // This shouldn't happen if users call methods in the expected order. Bail out. + return; + } + + if (_finishOnDispose) + { + Span.Finish(); + } + + _scopeManager.Active = _scopeToRestore; + } + + public ISpan Span { get; } + } +} diff --git a/src/OpenTracing/Util/ThreadLocalScopeManager.cs b/src/OpenTracing/Util/ThreadLocalScopeManager.cs new file mode 100644 index 0000000..4124098 --- /dev/null +++ b/src/OpenTracing/Util/ThreadLocalScopeManager.cs @@ -0,0 +1,30 @@ +using System; + +namespace OpenTracing.Util +{ + /// + /// An implementation that relies on thread local storage for + /// managing active scopes. Intended to be used in systems where multiple logical, + /// related operations are all executed in the same thread albeit at different times. + /// + public class ThreadLocalScopeManager : IScopeManager + { + /* + * Went with ThreadStatic over ThreadLocal because we don't + * want scopes to be initialized upon thread initialization by default + * and we want ThreadStatic's mutability for restoring / replacing scopes. + */ + [ThreadStatic] + private static IScope _active; + + public IScope Active + { + get => _active; + set => _active = value; + } + public IScope Activate(ISpan span, bool finishSpanOnDispose) + { + return new ThreadLocalScope(this, span, finishSpanOnDispose); + } + } +}