From 099c3c76a0a31b506cf03959886a9f8049860b38 Mon Sep 17 00:00:00 2001 From: Alan West <3676547+alanwest@users.noreply.github.com> Date: Tue, 4 Aug 2020 22:04:03 -0700 Subject: [PATCH] Make SuppressInstrumentation an IDisposable (#988) * Make SuppressInstrumentation an IDisposable * Simplify SuppressInstrumentation * Rename to SuppressInstrumentationScope * Clean up comment * Implicit operator instead of IsSuppressed property * Make SuppressInstrumentationScope constructor internal * Clean up some names * Update changelog Co-authored-by: Cijo Thomas Co-authored-by: Reiley Yang --- src/OpenTelemetry/CHANGELOG.md | 1 + src/OpenTelemetry/Sdk.cs | 48 +----------- .../SuppressInstrumentationScope.cs | 74 +++++++++++++++++++ .../SuppressInstrumentationTest.cs | 45 +++++++++++ 4 files changed, 122 insertions(+), 46 deletions(-) create mode 100644 src/OpenTelemetry/SuppressInstrumentationScope.cs create mode 100644 test/OpenTelemetry.Tests/SuppressInstrumentationTest.cs diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index ad1b665688..0bb78d5730 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +* Introduce `SuppressInstrumentationScope` API (#988). * `ActivityProcessor` implements `IDisposable`. * When `Dispose` occurs, it calls `ShutdownAsync`. * If you want a custom behavior for dispose, you will have to override the diff --git a/src/OpenTelemetry/Sdk.cs b/src/OpenTelemetry/Sdk.cs index 38f0889fea..3f68ff21b6 100644 --- a/src/OpenTelemetry/Sdk.cs +++ b/src/OpenTelemetry/Sdk.cs @@ -34,53 +34,9 @@ namespace OpenTelemetry /// public static class Sdk { - private static readonly TimeSpan DefaultPushInterval = TimeSpan.FromSeconds(60); - - private static readonly RuntimeContextSlot SuppressInstrumentationRuntimeContextSlot = RuntimeContext.RegisterSlot("otel.suppress_instrumentation"); - - /// - /// Gets or sets a value indicating whether automatic telemetry - /// collection in the current context should be suppressed (disabled). - /// Default value: False. - /// - /// - /// Set to - /// when you want to turn off automatic telemetry collection. - /// This is typically used to prevent infinite loops created by - /// collection of internal operations, such as exporting traces over HTTP. - /// - /// public override async Task<ExportResult> ExportAsync( - /// IEnumerable<Activity> batch, - /// CancellationToken cancellationToken) - /// { - /// var currentSuppressionPolicy = Sdk.SuppressInstrumentation; - /// Sdk.SuppressInstrumentation = true; - /// try - /// { - /// await this.SendBatchActivityAsync(batch, cancellationToken).ConfigureAwait(false); - /// return ExportResult.Success; - /// } - /// finally - /// { - /// Sdk.SuppressInstrumentation = currentSuppressionPolicy; - /// } - /// } - /// - /// - public static bool SuppressInstrumentation - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return SuppressInstrumentationRuntimeContextSlot.Get(); - } + public static readonly SuppressInstrumentationScope SuppressInstrumentation = new SuppressInstrumentationScope(false); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set - { - SuppressInstrumentationRuntimeContextSlot.Set(value); - } - } + private static readonly TimeSpan DefaultPushInterval = TimeSpan.FromSeconds(60); /// /// Creates MeterProvider with the configuration provided. diff --git a/src/OpenTelemetry/SuppressInstrumentationScope.cs b/src/OpenTelemetry/SuppressInstrumentationScope.cs new file mode 100644 index 0000000000..1eae39b429 --- /dev/null +++ b/src/OpenTelemetry/SuppressInstrumentationScope.cs @@ -0,0 +1,74 @@ +// +// 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 OpenTelemetry.Context; + +namespace OpenTelemetry +{ + public sealed class SuppressInstrumentationScope : IDisposable + { + private static readonly RuntimeContextSlot Slot = RuntimeContext.RegisterSlot("otel.suppress_instrumentation"); + + private readonly bool previousValue; + private bool disposed; + + internal SuppressInstrumentationScope(bool value = true) + { + this.previousValue = Slot.Get(); + Slot.Set(value); + } + + public static implicit operator bool(SuppressInstrumentationScope unused) => Slot.Get(); + + /// + /// Begins a new scope in which instrumentation is suppressed (disabled). + /// + /// Value indicating whether to suppress instrumentation. + /// Object to dispose to end the scope. + /// + /// This is typically used to prevent infinite loops created by + /// collection of internal operations, such as exporting traces over HTTP. + /// + /// public override async Task<ExportResult> ExportAsync( + /// IEnumerable<Activity> batch, + /// CancellationToken cancellationToken) + /// { + /// using (Sdk.SuppressInstrumentation.Begin()) + /// { + /// // Instrumentation is suppressed (i.e., Sdk.SuppressInstrumentation == true) + /// } + /// + /// // Instrumentation is not suppressed (i.e., Sdk.SuppressInstrumentation == false) + /// } + /// + /// + public IDisposable Begin(bool value = true) + { + return new SuppressInstrumentationScope(value); + } + + /// + public void Dispose() + { + if (!this.disposed) + { + Slot.Set(this.previousValue); + this.disposed = true; + } + } + } +} diff --git a/test/OpenTelemetry.Tests/SuppressInstrumentationTest.cs b/test/OpenTelemetry.Tests/SuppressInstrumentationTest.cs new file mode 100644 index 0000000000..6cf6c2849f --- /dev/null +++ b/test/OpenTelemetry.Tests/SuppressInstrumentationTest.cs @@ -0,0 +1,45 @@ +// +// 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 Xunit; + +namespace OpenTelemetry.Tests +{ + public class SuppressInstrumentationTest + { + [Fact] + public static void UsingSuppressInstrumentation() + { + using (var scope = Sdk.SuppressInstrumentation.Begin()) + { + Assert.True(Sdk.SuppressInstrumentation); + + using (var innerScope = Sdk.SuppressInstrumentation.Begin()) + { + innerScope.Dispose(); + + Assert.True(Sdk.SuppressInstrumentation); + + scope.Dispose(); + } + + Assert.False(Sdk.SuppressInstrumentation); + } + + Assert.False(Sdk.SuppressInstrumentation); + } + } +}