From 68c16da46fd13c06cd04ded12012291067766393 Mon Sep 17 00:00:00 2001 From: Alan West <3676547+alanwest@users.noreply.github.com> Date: Wed, 19 Aug 2020 21:05:29 -0700 Subject: [PATCH] SuppressInstrumentation from ActivityListener and DiagnosticSourceListener (#1079) * Add SuppressInstrumentation check in the ActivityListener * Add SuppressInstrumentation check in the DiagnosticSourceListner * Fix things post merge * Put AlwaysOn/AlwaysOff sampler check back in the constructor --- .../DiagnosticSourceListener.cs | 5 ++ src/OpenTelemetry/Trace/TracerProviderSdk.cs | 9 ++- .../DiagnosticSourceListenerTest.cs | 60 +++++++++++++++++++ .../Instrumentation/TestListenerHandler.cs | 53 ++++++++++++++++ .../Trace/TracerProvideSdkTest.cs | 18 ++++++ 5 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 test/OpenTelemetry.Tests/Instrumentation/DiagnosticSourceListenerTest.cs create mode 100644 test/OpenTelemetry.Tests/Instrumentation/TestListenerHandler.cs diff --git a/src/OpenTelemetry/Instrumentation/DiagnosticSourceListener.cs b/src/OpenTelemetry/Instrumentation/DiagnosticSourceListener.cs index 2ebb330b3ac..d7112b9365f 100644 --- a/src/OpenTelemetry/Instrumentation/DiagnosticSourceListener.cs +++ b/src/OpenTelemetry/Instrumentation/DiagnosticSourceListener.cs @@ -39,6 +39,11 @@ public void OnError(Exception error) public void OnNext(KeyValuePair value) { + if (Sdk.SuppressInstrumentation) + { + return; + } + if (!this.handler.SupportsNullActivity && Activity.Current == null) { InstrumentationEventSource.Log.NullActivity(value.Key); diff --git a/src/OpenTelemetry/Trace/TracerProviderSdk.cs b/src/OpenTelemetry/Trace/TracerProviderSdk.cs index 84f5b2fd8e0..7eb0aa53a68 100644 --- a/src/OpenTelemetry/Trace/TracerProviderSdk.cs +++ b/src/OpenTelemetry/Trace/TracerProviderSdk.cs @@ -92,18 +92,21 @@ internal TracerProviderSdk( if (sampler is AlwaysOnSampler) { - listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions options) => ActivityDataRequest.AllDataAndRecorded; + listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions options) => + !Sdk.SuppressInstrumentation ? ActivityDataRequest.AllDataAndRecorded : ActivityDataRequest.None; } else if (sampler is AlwaysOffSampler) { /*TODO: Change options.Parent.SpanId to options.Parent.TraceId once AutoGenerateRootContextTraceId is removed.*/ - listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions options) => PropagateOrIgnoreData(options.Parent.SpanId); + listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions options) => + !Sdk.SuppressInstrumentation ? PropagateOrIgnoreData(options.Parent.SpanId) : ActivityDataRequest.None; } else { // This delegate informs ActivitySource about sampling decision when the parent context is an ActivityContext. - listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions options) => ComputeActivityDataRequest(options, sampler); + listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions options) => + !Sdk.SuppressInstrumentation ? ComputeActivityDataRequest(options, sampler) : ActivityDataRequest.None; } if (sources.Any()) diff --git a/test/OpenTelemetry.Tests/Instrumentation/DiagnosticSourceListenerTest.cs b/test/OpenTelemetry.Tests/Instrumentation/DiagnosticSourceListenerTest.cs new file mode 100644 index 00000000000..424c0f50dbb --- /dev/null +++ b/test/OpenTelemetry.Tests/Instrumentation/DiagnosticSourceListenerTest.cs @@ -0,0 +1,60 @@ +// +// 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.Diagnostics; +using Xunit; + +namespace OpenTelemetry.Instrumentation.Tests +{ + public class DiagnosticSourceListenerTest + { + private const string TestSourceName = "TestSourceName"; + private DiagnosticSource diagnosticSource; + private TestListenerHandler testListenerHandler; + private DiagnosticSourceSubscriber testDiagnosticSourceSubscriber; + + public DiagnosticSourceListenerTest() + { + this.diagnosticSource = new DiagnosticListener(TestSourceName); + this.testListenerHandler = new TestListenerHandler(TestSourceName); + this.testDiagnosticSourceSubscriber = new DiagnosticSourceSubscriber(this.testListenerHandler, null); + this.testDiagnosticSourceSubscriber.Subscribe(); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ListenerHandlerIsNotInvokedWhenSuppressInstrumentationTrue(bool suppressInstrumentation) + { + using var scope = SuppressInstrumentationScope.Begin(suppressInstrumentation); + + var activity = new Activity("Main"); + this.diagnosticSource.StartActivity(activity, null); + this.diagnosticSource.StopActivity(activity, null); + + if (suppressInstrumentation) + { + Assert.Equal(0, this.testListenerHandler.OnStartInvokedCount); + Assert.Equal(0, this.testListenerHandler.OnStopInvokedCount); + } + else + { + Assert.Equal(1, this.testListenerHandler.OnStartInvokedCount); + Assert.Equal(1, this.testListenerHandler.OnStopInvokedCount); + } + } + } +} diff --git a/test/OpenTelemetry.Tests/Instrumentation/TestListenerHandler.cs b/test/OpenTelemetry.Tests/Instrumentation/TestListenerHandler.cs new file mode 100644 index 00000000000..aee4188ef3f --- /dev/null +++ b/test/OpenTelemetry.Tests/Instrumentation/TestListenerHandler.cs @@ -0,0 +1,53 @@ +// +// 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.Diagnostics; + +namespace OpenTelemetry.Instrumentation.Tests +{ + public class TestListenerHandler : ListenerHandler + { + public int OnStartInvokedCount = 0; + public int OnStopInvokedCount = 0; + public int OnExceptionInvokedCount = 0; + public int OnCustomInvokedCount = 0; + + public TestListenerHandler(string sourceName) + : base(sourceName) + { + } + + public override void OnStartActivity(Activity activity, object payload) + { + this.OnStartInvokedCount++; + } + + public override void OnStopActivity(Activity activity, object payload) + { + this.OnStopInvokedCount++; + } + + public override void OnException(Activity activity, object payload) + { + this.OnExceptionInvokedCount++; + } + + public override void OnCustom(string name, Activity activity, object payload) + { + this.OnCustomInvokedCount++; + } + } +} diff --git a/test/OpenTelemetry.Tests/Trace/TracerProvideSdkTest.cs b/test/OpenTelemetry.Tests/Trace/TracerProvideSdkTest.cs index 442000cea65..00276e9581a 100644 --- a/test/OpenTelemetry.Tests/Trace/TracerProvideSdkTest.cs +++ b/test/OpenTelemetry.Tests/Trace/TracerProvideSdkTest.cs @@ -147,6 +147,24 @@ public void TracerSdkSetsActivityDataRequestBasedOnSamplingDecision() } } + [Fact] + public void TracerSdkSetsActivityDataRequestToNoneWhenSuppressInstrumentationIsTrue() + { + using var scope = SuppressInstrumentationScope.Begin(); + + var testSampler = new TestSampler(); + using var activitySource = new ActivitySource(ActivitySourceName); + using var sdk = Sdk.CreateTracerProviderBuilder() + .AddSource(ActivitySourceName) + .SetSampler(testSampler) + .Build(); + + using (var activity = activitySource.StartActivity("root")) + { + Assert.Null(activity); + } + } + [Fact] public void ProcessorDoesNotReceiveNotRecordDecisionSpan() {