// // 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 System.Collections.Concurrent; using System.Runtime.CompilerServices; namespace OpenTelemetry.Context { /// /// Generic runtime context management API. /// public sealed class RuntimeContext { private static readonly ConcurrentDictionary Slots = new ConcurrentDictionary(); /// /// Gets or sets the actual context carrier implementation. /// #if !NET452 public static Type ContextSlotType { get; set; } = typeof(AsyncLocalRuntimeContextSlot<>); #else public static Type ContextSlotType { get; set; } = typeof(RemotingRuntimeContextSlot<>); #endif /// /// Register a named context slot. /// /// The name of the context slot. /// The type of the underlying value. /// The slot registered. public static RuntimeContextSlot RegisterSlot(string name) { lock (Slots) { if (Slots.ContainsKey(name)) { throw new InvalidOperationException($"The context slot {name} is already registered."); } var type = ContextSlotType.MakeGenericType(typeof(T)); var ctor = type.GetConstructor(new Type[] { typeof(string) }); 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) { foreach (var entry in snapshot) { // TODO: revisit this part if we want Snapshot() to be used on critical paths dynamic value = entry.Value; SetValue(entry.Key, value); } } public static IDictionary Snapshot() { var retval = new Dictionary(); foreach (var entry in Slots) { // TODO: revisit this part if we want Snapshot() to be used on critical paths dynamic slot = entry.Value; retval[entry.Key] = slot.Get(); } return retval; } */ /// /// Sets the value to a registered slot. /// /// 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]; slot.Set(value); } /// /// Gets the value from a registered slot. /// /// 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]; return slot.Get(); } // For testing purpose // private static Clear } }