diff --git a/src/OpenTelemetry.Api/Context/AsyncLocalRuntimeContextSlot.cs b/src/OpenTelemetry.Api/Context/AsyncLocalRuntimeContextSlot.cs index 14e68b05588..fc99c1b9c81 100644 --- a/src/OpenTelemetry.Api/Context/AsyncLocalRuntimeContextSlot.cs +++ b/src/OpenTelemetry.Api/Context/AsyncLocalRuntimeContextSlot.cs @@ -15,6 +15,7 @@ // #if !NET452 +using System.Runtime.CompilerServices; using System.Threading; namespace OpenTelemetry.Context @@ -38,12 +39,14 @@ public AsyncLocalRuntimeContextSlot(string name) } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public override T Get() { return this.slot.Value; } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public override void Set(T value) { this.slot.Value = value; diff --git a/src/OpenTelemetry.Api/Context/RemotingRuntimeContextSlot.cs b/src/OpenTelemetry.Api/Context/RemotingRuntimeContextSlot.cs index 315674e4681..c96caa57b2c 100644 --- a/src/OpenTelemetry.Api/Context/RemotingRuntimeContextSlot.cs +++ b/src/OpenTelemetry.Api/Context/RemotingRuntimeContextSlot.cs @@ -17,6 +17,7 @@ #if NET452 using System.Collections; using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.Remoting.Messaging; namespace OpenTelemetry.Context @@ -50,6 +51,7 @@ public RemotingRuntimeContextSlot(string name) } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public override T Get() { var wrapper = CallContext.LogicalGetData(this.Name) as BitArray; @@ -63,6 +65,7 @@ public override T Get() } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public override void Set(T value) { var wrapper = new BitArray(0); diff --git a/src/OpenTelemetry.Api/Context/RuntimeContext.cs b/src/OpenTelemetry.Api/Context/RuntimeContext.cs index c4db55c679e..625556c751c 100644 --- a/src/OpenTelemetry.Api/Context/RuntimeContext.cs +++ b/src/OpenTelemetry.Api/Context/RuntimeContext.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace OpenTelemetry.Context { @@ -41,7 +42,8 @@ public sealed class RuntimeContext /// /// The name of the context slot. /// The type of the underlying value. - public static void RegisterSlot(string name) + /// The slot registered. + public static RuntimeContextSlot RegisterSlot(string name) { lock (Slots) { @@ -52,10 +54,23 @@ public static void RegisterSlot(string name) var type = ContextSlotType.MakeGenericType(typeof(T)); var ctor = type.GetConstructor(new Type[] { typeof(string) }); - Slots[name] = ctor.Invoke(new object[] { name }); + var slot = (RuntimeContextSlot)ctor.Invoke(new object[] { name }); + Slots[name] = slot; + return slot; } } + /// + /// Get a registered slot from a given name. + /// + /// The name of the context slot. + /// The type of the underlying value. + /// The slot previously registered. + public static RuntimeContextSlot GetSlot(string name) + { + return (RuntimeContextSlot)Slots[name]; + } + /* public static void Apply(IDictionary snapshot) { @@ -86,6 +101,7 @@ public static IDictionary Snapshot() /// The name of the context slot. /// The value to be set. /// The type of the value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SetValue(string name, T value) { var slot = (RuntimeContextSlot)Slots[name]; @@ -98,6 +114,7 @@ public static void SetValue(string name, T value) /// The name of the context slot. /// The type of the value. /// The value retrieved from the context slot. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T GetValue(string name) { var slot = (RuntimeContextSlot)Slots[name]; diff --git a/src/OpenTelemetry.Api/Context/ThreadLocalRuntimeContextSlot.cs b/src/OpenTelemetry.Api/Context/ThreadLocalRuntimeContextSlot.cs index a18cc69c193..b1314f9b4b3 100644 --- a/src/OpenTelemetry.Api/Context/ThreadLocalRuntimeContextSlot.cs +++ b/src/OpenTelemetry.Api/Context/ThreadLocalRuntimeContextSlot.cs @@ -14,6 +14,7 @@ // limitations under the License. // +using System.Runtime.CompilerServices; using System.Threading; namespace OpenTelemetry.Context @@ -37,12 +38,14 @@ public ThreadLocalRuntimeContextSlot(string name) } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public override T Get() { return this.slot.Value; } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public override void Set(T value) { this.slot.Value = value; diff --git a/src/OpenTelemetry/Sdk.cs b/src/OpenTelemetry/Sdk.cs index eb85d063102..38f0889feaf 100644 --- a/src/OpenTelemetry/Sdk.cs +++ b/src/OpenTelemetry/Sdk.cs @@ -17,7 +17,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading; +using OpenTelemetry.Context; using OpenTelemetry.Metrics; using OpenTelemetry.Metrics.Export; using OpenTelemetry.Trace; @@ -32,7 +34,53 @@ namespace OpenTelemetry /// public static class Sdk { - private static TimeSpan defaultPushInterval = TimeSpan.FromSeconds(60); + 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(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + SuppressInstrumentationRuntimeContextSlot.Set(value); + } + } /// /// Creates MeterProvider with the configuration provided. @@ -60,7 +108,7 @@ public static MeterProvider CreateMeterProvider(Action configure) meterRegistry, metricProcessor, metricExporter, - meterBuilder.MetricPushInterval == default(TimeSpan) ? defaultPushInterval : meterBuilder.MetricPushInterval, + meterBuilder.MetricPushInterval == default(TimeSpan) ? DefaultPushInterval : meterBuilder.MetricPushInterval, cancellationTokenSource); var meterProviderSdk = new MeterProviderSdk(metricProcessor, meterRegistry, controller, cancellationTokenSource);