using System; using System.Buffers; using System.Buffers.Binary; using System.Buffers.Text; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.Globalization; using System.Linq; using System.Net; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using FxResources.System.Diagnostics.DiagnosticSource; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: AssemblyMetadata("PreferInbox", "True")] [assembly: AssemblyDefaultAlias("System.Diagnostics.DiagnosticSource")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: CLSCompliant(true)] [assembly: AssemblyMetadata("IsTrimmable", "True")] [assembly: AssemblyMetadata("IsAotCompatible", "True")] [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)] [assembly: AssemblyCompany("Microsoft Corporation")] [assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] [assembly: AssemblyDescription("Provides Classes that allow you to decouple code logging rich (unserializable) diagnostics/telemetry (e.g. framework) from code that consumes it (e.g. tools)\r\n\r\nCommonly Used Types:\r\nSystem.Diagnostics.DiagnosticListener\r\nSystem.Diagnostics.DiagnosticSource")] [assembly: AssemblyFileVersion("10.0.1126.37416")] [assembly: AssemblyInformationalVersion("10.0.11+e2f47b0110ed922f21a1522da67279133ce28f32")] [assembly: AssemblyProduct("Microsoft® .NET")] [assembly: AssemblyTitle("System.Diagnostics.DiagnosticSource")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/dotnet")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("10.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NullablePublicOnly(false)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Embedded] internal sealed class ParamCollectionAttribute : Attribute { } [CompilerGenerated] [Embedded] internal sealed class IsByRefLikeAttribute : Attribute { } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class NullablePublicOnlyAttribute : Attribute { public readonly bool IncludesInternals; public NullablePublicOnlyAttribute(bool P_0) { IncludesInternals = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] internal sealed class ScopedRefAttribute : Attribute { } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class ExtensionMarkerAttribute : Attribute { public ExtensionMarkerAttribute(string name) { } } } namespace FxResources.System.Diagnostics.DiagnosticSource { internal static class SR { } } namespace Internal { internal static class PaddingHelpers { internal const int CACHE_LINE_SIZE = 128; } [StructLayout(LayoutKind.Explicit, Size = 124)] internal struct PaddingFor32 { } } namespace System { internal static class HexConverter { public enum Casing : uint { Upper = 0u, Lower = 8224u } private ref struct SpanCasingPair { public ReadOnlySpan Bytes { get; set; } public Casing Casing { get; set; } } public static ReadOnlySpan CharToHexLookup => new byte[256] { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ToBytesBuffer(byte value, Span buffer, int startingIndex = 0, Casing casing = Casing.Upper) { uint num = (uint)(((value & 0xF0) << 4) + (value & 0xF) - 35209); uint num2 = ((((0 - num) & 0x7070) >> 4) + num + 47545) | (uint)casing; buffer[startingIndex + 1] = (byte)num2; buffer[startingIndex] = (byte)(num2 >> 8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ToCharsBuffer(byte value, Span buffer, int startingIndex = 0, Casing casing = Casing.Upper) { uint num = (uint)(((value & 0xF0) << 4) + (value & 0xF) - 35209); uint num2 = ((((0 - num) & 0x7070) >> 4) + num + 47545) | (uint)casing; buffer[startingIndex + 1] = (char)(num2 & 0xFF); buffer[startingIndex] = (char)(num2 >> 8); } public static void EncodeToUtf8(ReadOnlySpan source, Span utf8Destination, Casing casing = Casing.Upper) { for (int i = 0; i < source.Length; i++) { ToBytesBuffer(source[i], utf8Destination, i * 2, casing); } } public static void EncodeToUtf16(ReadOnlySpan source, Span destination, Casing casing = Casing.Upper) { for (int i = 0; i < source.Length; i++) { ToCharsBuffer(source[i], destination, i * 2, casing); } } public static string ToString(ReadOnlySpan bytes, Casing casing = Casing.Upper) { Span span = ((bytes.Length <= 16) ? stackalloc char[bytes.Length * 2] : new char[bytes.Length * 2].AsSpan()); Span buffer = span; int num = 0; ReadOnlySpan readOnlySpan = bytes; for (int i = 0; i < readOnlySpan.Length; i++) { ToCharsBuffer(readOnlySpan[i], buffer, num, casing); num += 2; } return buffer.ToString(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static char ToCharUpper(int value) { value &= 0xF; value += 48; if (value > 57) { value += 7; } return (char)value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static char ToCharLower(int value) { value &= 0xF; value += 48; if (value > 57) { value += 39; } return (char)value; } public static bool TryDecodeFromUtf8(ReadOnlySpan utf8Source, Span destination, out int bytesProcessed) { return TryDecodeFromUtf8_Scalar(utf8Source, destination, out bytesProcessed); } public static bool TryDecodeFromUtf16(ReadOnlySpan source, Span destination, out int charsProcessed) { return TryDecodeFromUtf16_Scalar(source, destination, out charsProcessed); } private static bool TryDecodeFromUtf8_Scalar(ReadOnlySpan utf8Source, Span destination, out int bytesProcessed) { int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; while (num2 < destination.Length) { num3 = FromChar(utf8Source[num + 1]); num4 = FromChar(utf8Source[num]); if ((num3 | num4) == 255) { break; } destination[num2++] = (byte)((num4 << 4) | num3); num += 2; } if (num3 == 255) { num++; } bytesProcessed = num; return (num3 | num4) != 255; } private static bool TryDecodeFromUtf16_Scalar(ReadOnlySpan source, Span destination, out int charsProcessed) { int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; while (num2 < destination.Length) { num3 = FromChar(source[num + 1]); num4 = FromChar(source[num]); if ((num3 | num4) == 255) { break; } destination[num2++] = (byte)((num4 << 4) | num3); num += 2; } if (num3 == 255) { num++; } charsProcessed = num; return (num3 | num4) != 255; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int FromChar(int c) { if (c < CharToHexLookup.Length) { return CharToHexLookup[c]; } return 255; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int FromUpperChar(int c) { if (c <= 71) { return CharToHexLookup[c]; } return 255; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int FromLowerChar(int c) { switch (c) { case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: return c - 48; case 97: case 98: case 99: case 100: case 101: case 102: return c - 97 + 10; default: return 255; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsHexChar(int c) { if (IntPtr.Size == 8) { ulong num = (uint)(c - 48); long num2 = -17875860044349952L << (int)num; ulong num3 = num - 64; return (long)((ulong)num2 & num3) < 0L; } return FromChar(c) != 255; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsHexUpperChar(int c) { if ((uint)(c - 48) > 9u) { return (uint)(c - 65) <= 5u; } return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsHexLowerChar(int c) { if ((uint)(c - 48) > 9u) { return (uint)(c - 97) <= 5u; } return true; } } internal static class SR { private static readonly bool s_usingResourceKeys = GetUsingResourceKeysSwitchValue(); private static ResourceManager s_resourceManager; internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR))); internal static string ActivityIdFormatInvalid => GetResourceString("ActivityIdFormatInvalid"); internal static string ActivityNotRunning => GetResourceString("ActivityNotRunning"); internal static string ActivityNotStarted => GetResourceString("ActivityNotStarted"); internal static string ActivityStartAlreadyStarted => GetResourceString("ActivityStartAlreadyStarted"); internal static string ActivitySetParentAlreadyStarted => GetResourceString("ActivitySetParentAlreadyStarted"); internal static string EndTimeNotUtc => GetResourceString("EndTimeNotUtc"); internal static string OperationNameInvalid => GetResourceString("OperationNameInvalid"); internal static string ParentIdAlreadySet => GetResourceString("ParentIdAlreadySet"); internal static string ParentIdInvalid => GetResourceString("ParentIdInvalid"); internal static string SetFormatOnStartedActivity => GetResourceString("SetFormatOnStartedActivity"); internal static string SetParentIdOnActivityWithParent => GetResourceString("SetParentIdOnActivityWithParent"); internal static string StartTimeNotUtc => GetResourceString("StartTimeNotUtc"); internal static string KeyAlreadyExist => GetResourceString("KeyAlreadyExist"); internal static string InvalidTraceParent => GetResourceString("InvalidTraceParent"); internal static string UnableAccessServicePointTable => GetResourceString("UnableAccessServicePointTable"); internal static string UnableToInitialize => GetResourceString("UnableToInitialize"); internal static string UnsupportedType => GetResourceString("UnsupportedType"); internal static string Arg_BufferTooSmall => GetResourceString("Arg_BufferTooSmall"); internal static string InvalidInstrumentType => GetResourceString("InvalidInstrumentType"); internal static string InvalidHistogramExplicitBucketBoundaries => GetResourceString("InvalidHistogramExplicitBucketBoundaries"); internal static string InvalidHistogramScale => GetResourceString("InvalidHistogramScale"); internal static string InvalidHistogramMaxBuckets => GetResourceString("InvalidHistogramMaxBuckets"); private static bool GetUsingResourceKeysSwitchValue() { if (!AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled)) { return false; } return isEnabled; } internal static bool UsingResourceKeys() { return s_usingResourceKeys; } private static string GetResourceString(string resourceKey) { if (UsingResourceKeys()) { return resourceKey; } string result = null; try { result = ResourceManager.GetString(resourceKey); } catch (MissingManifestResourceException) { } return result; } private static string GetResourceString(string resourceKey, string defaultString) { string resourceString = GetResourceString(resourceKey); if (!(resourceKey == resourceString) && resourceString != null) { return resourceString; } return defaultString; } internal static string Format(string resourceFormat, object p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(resourceFormat, p1); } internal static string Format(string resourceFormat, object p1, object p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(resourceFormat, p1, p2); } internal static string Format(string resourceFormat, object p1, object p2, object p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(resourceFormat, p1, p2, p3); } internal static string Format(string resourceFormat, params object[] args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(resourceFormat, args); } return resourceFormat; } internal static string Format(IFormatProvider provider, string resourceFormat, object p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(provider, resourceFormat, p1); } internal static string Format(IFormatProvider provider, string resourceFormat, object p1, object p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(provider, resourceFormat, p1, p2); } internal static string Format(IFormatProvider provider, string resourceFormat, object p1, object p2, object p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(provider, resourceFormat, p1, p2, p3); } internal static string Format(IFormatProvider provider, string resourceFormat, params object[] args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(provider, resourceFormat, args); } return resourceFormat; } } internal static class ExceptionPolyfills { [SpecialName] public sealed class $E6188BA5B951F1F7AA9135E0EBB76F2B { [SpecialName] public static class $96F0261AC622664B8B003966835C0332 { } [ExtensionMarker("$96F0261AC622664B8B003966835C0332")] public static void ThrowIfNull([NotNull] object argument, [CallerArgumentExpression("argument")] string paramName = null) { throw null; } } [SpecialName] public sealed class $3F30F31B33543D5FB8E174FB4FD780B9 { [SpecialName] public static class $1F10CFA08738E6D8AF61CBECC6763DBC { } [ExtensionMarker("$1F10CFA08738E6D8AF61CBECC6763DBC")] public static void ThrowIf([DoesNotReturnIf(true)] bool condition, object instance) { throw null; } [ExtensionMarker("$1F10CFA08738E6D8AF61CBECC6763DBC")] public static void ThrowIf([DoesNotReturnIf(true)] bool condition, Type type) { throw null; } } public static void ThrowIfNull([NotNull] object argument, [CallerArgumentExpression("argument")] string paramName = null) { if (argument == null) { ThrowArgumentNullException(paramName); } } [DoesNotReturn] private static void ThrowArgumentNullException(string paramName) { throw new ArgumentNullException(paramName); } public static void ThrowIf([DoesNotReturnIf(true)] bool condition, object instance) { if (condition) { ThrowObjectDisposedException(instance); } } public static void ThrowIf([DoesNotReturnIf(true)] bool condition, Type type) { if (condition) { ThrowObjectDisposedException(type); } } [DoesNotReturn] private static void ThrowObjectDisposedException(object instance) { throw new ObjectDisposedException(instance?.GetType().FullName); } [DoesNotReturn] private static void ThrowObjectDisposedException(Type type) { throw new ObjectDisposedException(type?.FullName); } } } namespace System.Runtime.Versioning { internal abstract class OSPlatformAttribute : Attribute { public string PlatformName { get; } private protected OSPlatformAttribute(string platformName) { PlatformName = platformName; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] internal sealed class TargetPlatformAttribute : OSPlatformAttribute { public TargetPlatformAttribute(string platformName) : base(platformName) { } } [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)] internal sealed class SupportedOSPlatformAttribute : OSPlatformAttribute { public SupportedOSPlatformAttribute(string platformName) : base(platformName) { } } [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)] internal sealed class UnsupportedOSPlatformAttribute : OSPlatformAttribute { public string Message { get; } public UnsupportedOSPlatformAttribute(string platformName) : base(platformName) { } public UnsupportedOSPlatformAttribute(string platformName, string message) : base(platformName) { Message = message; } } [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)] internal sealed class ObsoletedOSPlatformAttribute : OSPlatformAttribute { public string Message { get; } public string Url { get; set; } public ObsoletedOSPlatformAttribute(string platformName) : base(platformName) { } public ObsoletedOSPlatformAttribute(string platformName, string message) : base(platformName) { Message = message; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true, Inherited = false)] internal sealed class SupportedOSPlatformGuardAttribute : OSPlatformAttribute { public SupportedOSPlatformGuardAttribute(string platformName) : base(platformName) { } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true, Inherited = false)] internal sealed class UnsupportedOSPlatformGuardAttribute : OSPlatformAttribute { public UnsupportedOSPlatformGuardAttribute(string platformName) : base(platformName) { } } } namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] internal sealed class LibraryImportAttribute : Attribute { public string LibraryName { get; } public string EntryPoint { get; set; } public StringMarshalling StringMarshalling { get; set; } public Type StringMarshallingCustomType { get; set; } public bool SetLastError { get; set; } public LibraryImportAttribute(string libraryName) { LibraryName = libraryName; } } internal enum StringMarshalling { Custom, Utf8, Utf16 } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class, Inherited = false)] internal sealed class CompilerLoweringPreserveAttribute : Attribute { } [EditorBrowsable(EditorBrowsableState.Never)] internal static class IsExternalInit { } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] internal sealed class CallerArgumentExpressionAttribute : Attribute { public string ParameterName { get; } public CallerArgumentExpressionAttribute(string parameterName) { ParameterName = parameterName; } } } namespace System.Text { internal ref struct ValueStringBuilder { private char[] _arrayToReturnToPool; private Span _chars; private int _pos; public int Length { get { return _pos; } set { _pos = value; } } public int Capacity => _chars.Length; public ref char this[int index] => ref _chars[index]; public Span RawChars => _chars; public ValueStringBuilder(Span initialBuffer) { _arrayToReturnToPool = null; _chars = initialBuffer; _pos = 0; } public ValueStringBuilder(int initialCapacity) { _arrayToReturnToPool = ArrayPool.Shared.Rent(initialCapacity); _chars = _arrayToReturnToPool; _pos = 0; } public void EnsureCapacity(int capacity) { if ((uint)capacity > (uint)_chars.Length) { Grow(capacity - _pos); } } public ref char GetPinnableReference() { return ref MemoryMarshal.GetReference(_chars); } public ref char GetPinnableReference(bool terminate) { if (terminate) { EnsureCapacity(Length + 1); _chars[Length] = '\0'; } return ref MemoryMarshal.GetReference(_chars); } public override string ToString() { string result = _chars.Slice(0, _pos).ToString(); Dispose(); return result; } public ReadOnlySpan AsSpan(bool terminate) { if (terminate) { EnsureCapacity(Length + 1); _chars[Length] = '\0'; } return _chars.Slice(0, _pos); } public ReadOnlySpan AsSpan() { return _chars.Slice(0, _pos); } public ReadOnlySpan AsSpan(int start) { return _chars.Slice(start, _pos - start); } public ReadOnlySpan AsSpan(int start, int length) { return _chars.Slice(start, length); } public bool TryCopyTo(Span destination, out int charsWritten) { if (_chars.Slice(0, _pos).TryCopyTo(destination)) { charsWritten = _pos; Dispose(); return true; } charsWritten = 0; Dispose(); return false; } public void Insert(int index, char value, int count) { if (_pos > _chars.Length - count) { Grow(count); } int length = _pos - index; _chars.Slice(index, length).CopyTo(_chars.Slice(index + count)); _chars.Slice(index, count).Fill(value); _pos += count; } public void Insert(int index, string s) { if (s != null) { int length = s.Length; if (_pos > _chars.Length - length) { Grow(length); } int length2 = _pos - index; _chars.Slice(index, length2).CopyTo(_chars.Slice(index + length)); s.AsSpan().CopyTo(_chars.Slice(index)); _pos += length; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Append(char c) { int pos = _pos; Span chars = _chars; if ((uint)pos < (uint)chars.Length) { chars[pos] = c; _pos = pos + 1; } else { GrowAndAppend(c); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Append(string s) { if (s != null) { int pos = _pos; if (s.Length == 1 && (uint)pos < (uint)_chars.Length) { _chars[pos] = s[0]; _pos = pos + 1; } else { AppendSlow(s); } } } private void AppendSlow(string s) { int pos = _pos; if (pos > _chars.Length - s.Length) { Grow(s.Length); } s.AsSpan().CopyTo(_chars.Slice(pos)); _pos += s.Length; } public void Append(char c, int count) { if (_pos > _chars.Length - count) { Grow(count); } Span span = _chars.Slice(_pos, count); for (int i = 0; i < span.Length; i++) { span[i] = c; } _pos += count; } public void Append(scoped ReadOnlySpan value) { if (_pos > _chars.Length - value.Length) { Grow(value.Length); } value.CopyTo(_chars.Slice(_pos)); _pos += value.Length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span AppendSpan(int length) { int pos = _pos; if (pos > _chars.Length - length) { Grow(length); } _pos = pos + length; return _chars.Slice(pos, length); } [MethodImpl(MethodImplOptions.NoInlining)] private void GrowAndAppend(char c) { Grow(1); Append(c); } [MethodImpl(MethodImplOptions.NoInlining)] private void Grow(int additionalCapacityBeyondPos) { int minimumLength = (int)Math.Max((uint)(_pos + additionalCapacityBeyondPos), Math.Min((uint)(_chars.Length * 2), 2147483591u)); char[] array = ArrayPool.Shared.Rent(minimumLength); _chars.Slice(0, _pos).CopyTo(array); char[] arrayToReturnToPool = _arrayToReturnToPool; _chars = (_arrayToReturnToPool = array); if (arrayToReturnToPool != null) { ArrayPool.Shared.Return(arrayToReturnToPool); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { char[] arrayToReturnToPool = _arrayToReturnToPool; this = default(System.Text.ValueStringBuilder); if (arrayToReturnToPool != null) { ArrayPool.Shared.Return(arrayToReturnToPool); } } } } namespace System.Diagnostics { public readonly struct ActivityChangedEventArgs { public Activity? Previous { get; init; } public Activity? Current { get; init; } internal ActivityChangedEventArgs(Activity previous, Activity current) { Previous = previous; Current = current; } } public class Activity : IDisposable { public struct Enumerator { private static readonly DiagNode s_Empty = new DiagNode(default(T)); private DiagNode _nextNode; private DiagNode _currentNode; public readonly ref T Current => ref _currentNode.Value; internal Enumerator(DiagNode head) { _nextNode = head; _currentNode = s_Empty; } [EditorBrowsable(EditorBrowsableState.Never)] public readonly Enumerator GetEnumerator() { return this; } public bool MoveNext() { if (_nextNode == null) { _currentNode = s_Empty; return false; } _currentNode = _nextNode; _nextNode = _nextNode.Next; return true; } } private sealed class BaggageLinkedList : IEnumerable>, IEnumerable { private DiagNode> _first; public DiagNode> First => _first; public BaggageLinkedList(KeyValuePair firstValue, bool set = false) { _first = ((set && firstValue.Value == null) ? null : new DiagNode>(firstValue)); } public void Add(KeyValuePair value) { DiagNode> diagNode = new DiagNode>(value); lock (this) { diagNode.Next = _first; _first = diagNode; } } public void Set(KeyValuePair value) { if (value.Value == null) { Remove(value.Key); return; } lock (this) { for (DiagNode> diagNode = _first; diagNode != null; diagNode = diagNode.Next) { if (diagNode.Value.Key == value.Key) { diagNode.Value = value; return; } } DiagNode> diagNode2 = new DiagNode>(value); diagNode2.Next = _first; _first = diagNode2; } } public void Remove(string key) { lock (this) { if (_first == null) { return; } if (_first.Value.Key == key) { _first = _first.Next; return; } DiagNode> diagNode = _first; while (diagNode.Next != null) { if (diagNode.Next.Value.Key == key) { diagNode.Next = diagNode.Next.Next; break; } diagNode = diagNode.Next; } } } public DiagEnumerator> GetEnumerator() { return new DiagEnumerator>(_first); } IEnumerator> IEnumerable>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal sealed class TagsLinkedList : IEnumerable>, IEnumerable { private DiagNode> _first; private DiagNode> _last; private StringBuilder _stringBuilder; public DiagNode> First => _first; public TagsLinkedList(KeyValuePair firstValue, bool set = false) { _last = (_first = ((set && firstValue.Value == null) ? null : new DiagNode>(firstValue))); } public TagsLinkedList(IEnumerator> e) { _last = (_first = new DiagNode>(e.Current)); while (e.MoveNext()) { _last.Next = new DiagNode>(e.Current); _last = _last.Next; } } public TagsLinkedList(IEnumerable> list) { Add(list); } public void Add(IEnumerable> list) { IEnumerator> enumerator = list.GetEnumerator(); if (enumerator.MoveNext()) { if (_first == null) { _last = (_first = new DiagNode>(enumerator.Current)); } else { _last.Next = new DiagNode>(enumerator.Current); _last = _last.Next; } while (enumerator.MoveNext()) { _last.Next = new DiagNode>(enumerator.Current); _last = _last.Next; } } } public void Add(KeyValuePair value) { DiagNode> diagNode = new DiagNode>(value); lock (this) { if (_first == null) { _first = (_last = diagNode); return; } _last.Next = diagNode; _last = diagNode; } } public object Get(string key) { for (DiagNode> diagNode = _first; diagNode != null; diagNode = diagNode.Next) { if (diagNode.Value.Key == key) { return diagNode.Value.Value; } } return null; } public void Remove(string key) { lock (this) { if (_first == null) { return; } if (_first.Value.Key == key) { _first = _first.Next; if (_first == null) { _last = null; } return; } DiagNode> diagNode = _first; while (diagNode.Next != null) { if (diagNode.Next.Value.Key == key) { if (_last == diagNode.Next) { _last = diagNode; } diagNode.Next = diagNode.Next.Next; break; } diagNode = diagNode.Next; } } } public void Set(KeyValuePair value) { if (value.Value == null) { Remove(value.Key); return; } lock (this) { for (DiagNode> diagNode = _first; diagNode != null; diagNode = diagNode.Next) { if (diagNode.Value.Key == value.Key) { diagNode.Value = value; return; } } DiagNode> diagNode2 = new DiagNode>(value); if (_first == null) { _first = (_last = diagNode2); return; } _last.Next = diagNode2; _last = diagNode2; } } public DiagEnumerator> GetEnumerator() { return new DiagEnumerator>(_first); } IEnumerator> IEnumerable>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IEnumerable> EnumerateStringValues() { for (DiagNode> current = _first; current != null; current = current.Next) { if (current.Value.Value is string || current.Value.Value == null) { yield return new KeyValuePair(current.Value.Key, (string)current.Value.Value); } } } public override string ToString() { lock (this) { if (_first == null) { return string.Empty; } if (_stringBuilder == null) { _stringBuilder = new StringBuilder(); } _stringBuilder.Append(_first.Value.Key); _stringBuilder.Append(':'); _stringBuilder.Append(_first.Value.Value); for (DiagNode> next = _first.Next; next != null; next = next.Next) { _stringBuilder.Append(", "); _stringBuilder.Append(next.Value.Key); _stringBuilder.Append(':'); _stringBuilder.Append(next.Value.Value); } string result = _stringBuilder.ToString(); _stringBuilder.Clear(); return result; } } } [Flags] private enum State : byte { None = 0, FormatUnknown = 0, FormatHierarchical = 1, FormatW3C = 2, FormatFlags = 3, IsStopped = 0x80 } private static readonly IEnumerable> s_emptyBaggageTags = new KeyValuePair[0]; private static readonly IEnumerable> s_emptyTagObjects = new KeyValuePair[0]; private static readonly IEnumerable s_emptyLinks = new DiagLinkedList(); private static readonly IEnumerable s_emptyEvents = new DiagLinkedList(); private static readonly ActivitySource s_defaultSource = new ActivitySource(string.Empty); private static readonly AsyncLocal s_current = new AsyncLocal(); private const byte ActivityTraceFlagsIsSet = 128; private const int RequestIdMaxLength = 1024; private static readonly string s_uniqSuffix = $"-{GetRandomNumber():x}."; private static long s_currentRootId = (uint)GetRandomNumber(); private static ActivityIdFormat s_defaultIdFormat; [CompilerGenerated] private static EventHandler CurrentChanged; private string _traceState; private State _state; private int _currentChildId; private string _id; private string _rootId; private string _parentId; private string _parentSpanId; private string _traceId; private string _spanId; private byte _w3CIdFlags; private byte _parentTraceFlags; private TagsLinkedList _tags; private BaggageLinkedList _baggage; private DiagLinkedList _links; private DiagLinkedList _events; private Dictionary _customProperties; private string _displayName; private ActivityStatusCode _statusCode; private string _statusDescription; private Activity _previousActiveActivity; public static bool ForceDefaultIdFormat { get; set; } public ActivityStatusCode Status => _statusCode; public string? StatusDescription => _statusDescription; public bool HasRemoteParent { get; private set; } public static Activity? Current { get { return s_current.Value; } set { if (ValidateSetCurrent(value)) { SetCurrent(value); } } } public ActivityKind Kind { get; private set; } public string OperationName { get; } public string DisplayName { get { return _displayName ?? OperationName; } set { _displayName = value ?? throw new ArgumentNullException("value"); } } public ActivitySource Source { get; private set; } public Activity? Parent { get; private set; } public TimeSpan Duration { get; private set; } public DateTime StartTimeUtc { get; private set; } public string? Id { get { if (_id == null && _spanId != null) { Span buffer = stackalloc char[2]; System.HexConverter.ToCharsBuffer((byte)(-129 & _w3CIdFlags), buffer, 0, System.HexConverter.Casing.Lower); string value = "00-" + _traceId + "-" + _spanId + "-" + buffer; Interlocked.CompareExchange(ref _id, value, null); } return _id; } } public string? ParentId { get { if (_parentId == null) { if (_parentSpanId != null) { Span buffer = stackalloc char[2]; System.HexConverter.ToCharsBuffer((byte)(-129 & _parentTraceFlags), buffer, 0, System.HexConverter.Casing.Lower); string value = "00-" + _traceId + "-" + _parentSpanId + "-" + buffer; Interlocked.CompareExchange(ref _parentId, value, null); } else if (Parent != null) { Interlocked.CompareExchange(ref _parentId, Parent.Id, null); } } return _parentId; } } public string? RootId { get { if (_rootId == null) { string text = null; if (Id != null) { text = GetRootId(Id); } else if (ParentId != null) { text = GetRootId(ParentId); } if (text != null) { Interlocked.CompareExchange(ref _rootId, text, null); } } return _rootId; } } public IEnumerable> Tags => _tags?.EnumerateStringValues() ?? s_emptyBaggageTags; public IEnumerable> TagObjects { get { IEnumerable> tags = _tags; return tags ?? s_emptyTagObjects; } } public IEnumerable Events { get { IEnumerable events = _events; return events ?? s_emptyEvents; } } public IEnumerable Links { get { IEnumerable links = _links; return links ?? s_emptyLinks; } } public IEnumerable> Baggage { get { for (Activity activity = this; activity != null; activity = activity.Parent) { if (activity._baggage != null) { return Iterate(activity); } } return s_emptyBaggageTags; static IEnumerable> Iterate(Activity parent) { do { if (parent._baggage != null) { for (DiagNode> current = parent._baggage.First; current != null; current = current.Next) { yield return current.Value; } } parent = parent.Parent; } while (parent != null); } } } public ActivityContext Context => new ActivityContext(TraceId, SpanId, ActivityTraceFlags, TraceStateString); public string? TraceStateString { get { for (Activity activity = this; activity != null; activity = activity.Parent) { string traceState = activity._traceState; if (traceState != null) { return traceState; } } return null; } set { _traceState = value; } } public ActivitySpanId SpanId { get { if (_spanId == null && _id != null && IdFormat == ActivityIdFormat.W3C) { string value = ActivitySpanId.CreateFromString(_id.AsSpan(36, 16)).ToHexString(); Interlocked.CompareExchange(ref _spanId, value, null); } return new ActivitySpanId(_spanId); } } public ActivityTraceId TraceId { get { if (_traceId == null) { TrySetTraceIdFromParent(); } return new ActivityTraceId(_traceId); } } public bool Recorded => (ActivityTraceFlags & ActivityTraceFlags.Recorded) != 0; public bool IsAllDataRequested { get; set; } public ActivityTraceFlags ActivityTraceFlags { get { if (!W3CIdFlagsSet) { TrySetTraceFlagsFromParent(); } return (ActivityTraceFlags)(-129 & _w3CIdFlags); } set { _w3CIdFlags = (byte)(0x80 | (byte)value); } } public ActivitySpanId ParentSpanId { get { if (_parentSpanId == null) { string text = null; if (_parentId != null && IsW3CId(_parentId)) { try { text = ActivitySpanId.CreateFromString(_parentId.AsSpan(36, 16)).ToHexString(); } catch { } } else if (Parent != null && Parent.IdFormat == ActivityIdFormat.W3C) { text = Parent.SpanId.ToHexString(); } if (text != null) { Interlocked.CompareExchange(ref _parentSpanId, text, null); } } return new ActivitySpanId(_parentSpanId); } } public static Func? TraceIdGenerator { get; set; } public static ActivityIdFormat DefaultIdFormat { get { if (s_defaultIdFormat == ActivityIdFormat.Unknown) { s_defaultIdFormat = ActivityIdFormat.Hierarchical; } return s_defaultIdFormat; } set { if (ActivityIdFormat.Hierarchical > value || value > ActivityIdFormat.W3C) { throw new ArgumentException(System.SR.ActivityIdFormatInvalid); } s_defaultIdFormat = value; } } private bool W3CIdFlagsSet => (_w3CIdFlags & 0x80) != 0; public bool IsStopped { get { return (_state & State.IsStopped) != 0; } private set { if (value) { _state |= State.IsStopped; } else { _state &= ~State.IsStopped; } } } public ActivityIdFormat IdFormat { get { return (ActivityIdFormat)(_state & State.FormatFlags); } private set { _state = (State)((uint)(_state & ~State.FormatFlags) | (uint)(byte)((byte)value & 3)); } } public static event EventHandler? CurrentChanged; public Activity SetStatus(ActivityStatusCode code, string? description = null) { _statusCode = code; _statusDescription = ((code == ActivityStatusCode.Error) ? description : null); return this; } public Enumerator> EnumerateTagObjects() { return new Enumerator>(_tags?.First); } public Enumerator EnumerateEvents() { return new Enumerator(_events?.First); } public Enumerator EnumerateLinks() { return new Enumerator(_links?.First); } public string? GetBaggageItem(string key) { foreach (KeyValuePair item in Baggage) { if (key == item.Key) { return item.Value; } } return null; } public object? GetTagItem(string key) { return _tags?.Get(key) ?? null; } public Activity(string operationName) { Source = s_defaultSource; IsAllDataRequested = true; if (string.IsNullOrEmpty(operationName)) { NotifyError(new ArgumentException(System.SR.OperationNameInvalid)); } OperationName = operationName ?? string.Empty; } public Activity AddTag(string key, string? value) { return AddTag(key, (object?)value); } public Activity AddTag(string key, object? value) { KeyValuePair keyValuePair = new KeyValuePair(key, value); if (_tags != null || Interlocked.CompareExchange(ref _tags, new TagsLinkedList(keyValuePair), null) != null) { _tags.Add(keyValuePair); } return this; } public Activity SetTag(string key, object? value) { KeyValuePair keyValuePair = new KeyValuePair(key, value); if (_tags != null || Interlocked.CompareExchange(ref _tags, new TagsLinkedList(keyValuePair, set: true), null) != null) { _tags.Set(keyValuePair); } return this; } public Activity AddEvent(ActivityEvent e) { if (_events != null || Interlocked.CompareExchange(ref _events, new DiagLinkedList(e), null) != null) { _events.Add(e); } return this; } public Activity AddException(Exception exception, in TagList tags = default(TagList), DateTimeOffset timestamp = default(DateTimeOffset)) { ExceptionPolyfills.ThrowIfNull(exception, "exception"); TagList tags2 = tags; Source.NotifyActivityAddException(this, exception, ref tags2); bool flag = false; bool flag2 = false; bool flag3 = false; for (int i = 0; i < tags2.Count; i++) { if (tags2[i].Key == "exception.message") { flag = true; } else if (tags2[i].Key == "exception.stacktrace") { flag2 = true; } else if (tags2[i].Key == "exception.type") { flag3 = true; } } if (!flag) { tags2.Add(new KeyValuePair("exception.message", exception.Message)); } if (!flag2) { tags2.Add(new KeyValuePair("exception.stacktrace", exception.ToString())); } if (!flag3) { tags2.Add(new KeyValuePair("exception.type", exception.GetType().ToString())); } return AddEvent(new ActivityEvent("exception", timestamp, ref tags2)); } public Activity AddLink(ActivityLink link) { if (_links != null || Interlocked.CompareExchange(ref _links, new DiagLinkedList(link), null) != null) { _links.Add(link); } return this; } public Activity AddBaggage(string key, string? value) { KeyValuePair keyValuePair = new KeyValuePair(key, value); if (_baggage != null || Interlocked.CompareExchange(ref _baggage, new BaggageLinkedList(keyValuePair), null) != null) { _baggage.Add(keyValuePair); } return this; } public Activity SetBaggage(string key, string? value) { KeyValuePair keyValuePair = new KeyValuePair(key, value); if (_baggage != null || Interlocked.CompareExchange(ref _baggage, new BaggageLinkedList(keyValuePair, set: true), null) != null) { _baggage.Set(keyValuePair); } return this; } public Activity SetParentId(string parentId) { if (_id != null || _spanId != null) { NotifyError(new InvalidOperationException(System.SR.ActivitySetParentAlreadyStarted)); } else if (Parent != null) { NotifyError(new InvalidOperationException(System.SR.SetParentIdOnActivityWithParent)); } else if (ParentId != null || _parentSpanId != null) { NotifyError(new InvalidOperationException(System.SR.ParentIdAlreadySet)); } else if (string.IsNullOrEmpty(parentId)) { NotifyError(new ArgumentException(System.SR.ParentIdInvalid)); } else { _parentId = parentId; } return this; } public Activity SetParentId(ActivityTraceId traceId, ActivitySpanId spanId, ActivityTraceFlags activityTraceFlags = ActivityTraceFlags.None) { if (_id != null || _spanId != null) { NotifyError(new InvalidOperationException(System.SR.ActivitySetParentAlreadyStarted)); } else if (Parent != null) { NotifyError(new InvalidOperationException(System.SR.SetParentIdOnActivityWithParent)); } else if (ParentId != null || _parentSpanId != null) { NotifyError(new InvalidOperationException(System.SR.ParentIdAlreadySet)); } else { _traceId = traceId.ToHexString(); _parentSpanId = spanId.ToHexString(); ActivityTraceFlags = activityTraceFlags; _parentTraceFlags = (byte)activityTraceFlags; } return this; } public Activity SetStartTime(DateTime startTimeUtc) { if (startTimeUtc.Kind != DateTimeKind.Utc) { NotifyError(new InvalidOperationException(System.SR.StartTimeNotUtc)); } else { StartTimeUtc = startTimeUtc; } return this; } public Activity SetEndTime(DateTime endTimeUtc) { if (endTimeUtc.Kind != DateTimeKind.Utc) { NotifyError(new InvalidOperationException(System.SR.EndTimeNotUtc)); } else { Duration = endTimeUtc - StartTimeUtc; if (Duration.Ticks <= 0) { Duration = new TimeSpan(1L); } } return this; } public Activity Start() { if (_id != null || _spanId != null) { NotifyError(new InvalidOperationException(System.SR.ActivityStartAlreadyStarted)); } else { _previousActiveActivity = Current; if (_parentId == null && _parentSpanId == null && _previousActiveActivity != null) { Parent = _previousActiveActivity; } if (StartTimeUtc == default(DateTime)) { StartTimeUtc = GetUtcNow(); } if (IdFormat == ActivityIdFormat.Unknown) { IdFormat = (ForceDefaultIdFormat ? DefaultIdFormat : ((Parent != null) ? Parent.IdFormat : ((_parentSpanId != null) ? ActivityIdFormat.W3C : ((_parentId == null) ? DefaultIdFormat : ((!IsW3CId(_parentId)) ? ActivityIdFormat.Hierarchical : ActivityIdFormat.W3C))))); } if (IdFormat == ActivityIdFormat.W3C) { GenerateW3CId(); } else { _id = GenerateHierarchicalId(); } SetCurrent(this); Source.NotifyActivityStart(this); } return this; } public void Stop() { if (_id == null && _spanId == null) { NotifyError(new InvalidOperationException(System.SR.ActivityNotStarted)); } else if (!IsStopped) { IsStopped = true; if (Duration == TimeSpan.Zero) { SetEndTime(GetUtcNow()); } Source.NotifyActivityStop(this); SetCurrent(_previousActiveActivity); } } public Activity SetIdFormat(ActivityIdFormat format) { if (_id != null || _spanId != null) { NotifyError(new InvalidOperationException(System.SR.SetFormatOnStartedActivity)); } else { IdFormat = format; } return this; } private static bool IsW3CId(string id) { if (id.Length == 55 && (('0' <= id[0] && id[0] <= '9') || ('a' <= id[0] && id[0] <= 'f')) && (('0' <= id[1] && id[1] <= '9') || ('a' <= id[1] && id[1] <= 'f'))) { if (id[0] == 'f') { return id[1] != 'f'; } return true; } return false; } internal static bool TryConvertIdToContext(string traceParent, string traceState, bool isRemote, out ActivityContext context) { context = default(ActivityContext); if (!IsW3CId(traceParent)) { return false; } ReadOnlySpan idData = traceParent.AsSpan(3, 32); ReadOnlySpan idData2 = traceParent.AsSpan(36, 16); if (!ActivityTraceId.IsLowerCaseHexAndNotAllZeros(idData) || !ActivityTraceId.IsLowerCaseHexAndNotAllZeros(idData2) || !System.HexConverter.IsHexLowerChar(traceParent[53]) || !System.HexConverter.IsHexLowerChar(traceParent[54])) { return false; } context = new ActivityContext(new ActivityTraceId(idData.ToString()), new ActivitySpanId(idData2.ToString()), (ActivityTraceFlags)ActivityTraceId.HexByteFromChars(traceParent[53], traceParent[54]), traceState, isRemote); return true; } public void Dispose() { if (!IsStopped) { Stop(); } Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { } public void SetCustomProperty(string propertyName, object? propertyValue) { if (_customProperties == null) { Interlocked.CompareExchange(ref _customProperties, new Dictionary(), null); } lock (_customProperties) { if (propertyValue == null) { _customProperties.Remove(propertyName); } else { _customProperties[propertyName] = propertyValue; } } } public object? GetCustomProperty(string propertyName) { if (_customProperties == null) { return null; } lock (_customProperties) { object value; return _customProperties.TryGetValue(propertyName, out value) ? value : null; } } internal static Activity Create(ActivitySource source, string name, ActivityKind kind, string parentId, ActivityContext parentContext, IEnumerable> tags, IEnumerable links, DateTimeOffset startTime, ActivityTagsCollection samplerTags, ActivitySamplingResult request, bool startIt, ActivityIdFormat idFormat, string traceState) { Activity activity = new Activity(name); activity.Source = source; activity.Kind = kind; activity.IdFormat = idFormat; activity._traceState = traceState; if (links != null) { using IEnumerator enumerator = links.GetEnumerator(); if (enumerator.MoveNext()) { activity._links = new DiagLinkedList(enumerator); } } if (tags != null) { using IEnumerator> enumerator2 = tags.GetEnumerator(); if (enumerator2.MoveNext()) { activity._tags = new TagsLinkedList(enumerator2); } } if (samplerTags != null) { if (activity._tags == null) { activity._tags = new TagsLinkedList(samplerTags); } else { activity._tags.Add(samplerTags); } } if (parentId != null) { activity._parentId = parentId; } else if (parentContext != default(ActivityContext)) { activity._traceId = parentContext.TraceId.ToString(); if (parentContext.SpanId != default(ActivitySpanId)) { activity._parentSpanId = parentContext.SpanId.ToString(); } activity.ActivityTraceFlags = parentContext.TraceFlags & ~ActivityTraceFlags.Recorded; activity._parentTraceFlags = (byte)parentContext.TraceFlags; activity.HasRemoteParent = parentContext.IsRemote; } activity.IsAllDataRequested = request == ActivitySamplingResult.AllData || request == ActivitySamplingResult.AllDataAndRecorded; if (request == ActivitySamplingResult.AllDataAndRecorded) { activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; } if (startTime != default(DateTimeOffset)) { activity.StartTimeUtc = startTime.UtcDateTime; } if (startIt) { activity.Start(); } return activity; } private static void SetCurrent(Activity activity) { EventHandler currentChanged = Activity.CurrentChanged; if (currentChanged == null) { s_current.Value = activity; return; } Activity value = s_current.Value; s_current.Value = activity; currentChanged(null, new ActivityChangedEventArgs(value, activity)); } private void GenerateW3CId() { if (_traceId == null && !TrySetTraceIdFromParent()) { _traceId = (TraceIdGenerator?.Invoke() ?? ActivityTraceId.CreateRandom()).ToHexString(); } if (!W3CIdFlagsSet) { TrySetTraceFlagsFromParent(); } _spanId = ActivitySpanId.CreateRandom().ToHexString(); } private static void NotifyError(Exception exception) { try { throw exception; } catch { } } private string GenerateHierarchicalId() { if (Parent != null) { return AppendSuffix(Parent.Id, Interlocked.Increment(ref Parent._currentChildId).ToString(), '.'); } if (ParentId != null) { string text = ((ParentId[0] == '|') ? ParentId : ("|" + ParentId)); char c = text[text.Length - 1]; if (c != '.' && c != '_') { text += "."; } return AppendSuffix(text, Interlocked.Increment(ref s_currentRootId).ToString("x"), '_'); } return GenerateRootId(); } private string GetRootId(string id) { if (IdFormat == ActivityIdFormat.W3C) { return id.Substring(3, 32); } int num = id.IndexOf('.'); if (num < 0) { num = id.Length; } int num2 = ((id[0] == '|') ? 1 : 0); return id.Substring(num2, num - num2); } private string AppendSuffix(string parentId, string suffix, char delimiter) { if (parentId.Length + suffix.Length < 1024) { return parentId + suffix + delimiter; } int num = 1015; while (num > 1 && parentId[num - 1] != '.' && parentId[num - 1] != '_') { num--; } if (num == 1) { return GenerateRootId(); } string text = ((int)GetRandomNumber()).ToString("x8"); return parentId.Substring(0, num) + text + "#"; } private unsafe static long GetRandomNumber() { Guid guid = Guid.NewGuid(); return *(long*)(&guid); } private static bool ValidateSetCurrent(Activity activity) { int num; if (activity != null) { if (activity.Id != null) { num = ((!activity.IsStopped) ? 1 : 0); if (num != 0) { goto IL_002c; } } else { num = 0; } NotifyError(new InvalidOperationException(System.SR.ActivityNotRunning)); } else { num = 1; } goto IL_002c; IL_002c: return (byte)num != 0; } private bool TrySetTraceIdFromParent() { if (Parent != null && Parent.IdFormat == ActivityIdFormat.W3C) { _traceId = Parent.TraceId.ToHexString(); } else if (_parentId != null && IsW3CId(_parentId)) { try { _traceId = ActivityTraceId.CreateFromString(_parentId.AsSpan(3, 32)).ToHexString(); } catch { } } return _traceId != null; } private void TrySetTraceFlagsFromParent() { if (W3CIdFlagsSet) { return; } if (Parent != null) { ActivityTraceFlags = Parent.ActivityTraceFlags; } else if (_parentId != null && IsW3CId(_parentId)) { if (System.HexConverter.IsHexLowerChar(_parentId[53]) && System.HexConverter.IsHexLowerChar(_parentId[54])) { _w3CIdFlags = (byte)(ActivityTraceId.HexByteFromChars(_parentId[53], _parentId[54]) | 0x80); } else { _w3CIdFlags = 128; } } } private static string GenerateRootId() { return $"|{Interlocked.Increment(ref s_currentRootId):x}{s_uniqSuffix}"; } internal static DateTime GetUtcNow() { return DateTime.UtcNow; } } [Flags] public enum ActivityTraceFlags { None = 0, Recorded = 1 } public enum ActivityIdFormat { Unknown, Hierarchical, W3C } public readonly struct ActivityTraceId : IEquatable { private readonly string _hexString; internal ActivityTraceId(string hexString) { _hexString = hexString; } public static ActivityTraceId CreateRandom() { Span obj = stackalloc byte[16]; SetToRandomBytes(obj); return CreateFromBytes(obj); } public static ActivityTraceId CreateFromBytes(ReadOnlySpan idData) { if (idData.Length != 16) { throw new ArgumentOutOfRangeException("idData"); } return new ActivityTraceId(System.HexConverter.ToString(idData, System.HexConverter.Casing.Lower)); } public static ActivityTraceId CreateFromUtf8String(ReadOnlySpan idData) { return new ActivityTraceId(idData); } public static ActivityTraceId CreateFromString(ReadOnlySpan idData) { if (idData.Length != 32 || !IsLowerCaseHexAndNotAllZeros(idData)) { throw new ArgumentOutOfRangeException("idData"); } return new ActivityTraceId(idData.ToString()); } public string ToHexString() { return _hexString ?? "00000000000000000000000000000000"; } public override string ToString() { return ToHexString(); } public static bool operator ==(ActivityTraceId traceId1, ActivityTraceId traceId2) { return traceId1._hexString == traceId2._hexString; } public static bool operator !=(ActivityTraceId traceId1, ActivityTraceId traceId2) { return traceId1._hexString != traceId2._hexString; } public bool Equals(ActivityTraceId traceId) { return _hexString == traceId._hexString; } public override bool Equals([NotNullWhen(true)] object? obj) { if (obj is ActivityTraceId activityTraceId) { return _hexString == activityTraceId._hexString; } return false; } public override int GetHashCode() { return ToHexString().GetHashCode(); } private ActivityTraceId(ReadOnlySpan idData) { if (idData.Length != 32) { throw new ArgumentOutOfRangeException("idData"); } Span span = stackalloc ulong[2]; if (!Utf8Parser.TryParse(idData.Slice(0, 16), out span[0], out int bytesConsumed, 'x')) { _hexString = CreateRandom()._hexString; return; } if (!Utf8Parser.TryParse(idData.Slice(16, 16), out span[1], out bytesConsumed, 'x')) { _hexString = CreateRandom()._hexString; return; } if (BitConverter.IsLittleEndian) { span[0] = BinaryPrimitives.ReverseEndianness(span[0]); span[1] = BinaryPrimitives.ReverseEndianness(span[1]); } _hexString = System.HexConverter.ToString(MemoryMarshal.AsBytes(span), System.HexConverter.Casing.Lower); } public void CopyTo(Span destination) { SetSpanFromHexChars(ToHexString().AsSpan(), destination); } internal static void SetToRandomBytes(Span outBytes) { RandomNumberGenerator current = RandomNumberGenerator.Current; Unsafe.WriteUnaligned(ref outBytes[0], current.Next()); if (outBytes.Length == 16) { Unsafe.WriteUnaligned(ref outBytes[8], current.Next()); } } internal static void SetSpanFromHexChars(ReadOnlySpan charData, Span outBytes) { for (int i = 0; i < outBytes.Length; i++) { outBytes[i] = HexByteFromChars(charData[i * 2], charData[i * 2 + 1]); } } internal static byte HexByteFromChars(char char1, char char2) { int num = System.HexConverter.FromLowerChar(char1); int num2 = System.HexConverter.FromLowerChar(char2); if ((num | num2) == 255) { throw new ArgumentOutOfRangeException("idData"); } return (byte)((num << 4) | num2); } internal static bool IsLowerCaseHexAndNotAllZeros(ReadOnlySpan idData) { bool result = false; for (int i = 0; i < idData.Length; i++) { char c = idData[i]; if (!System.HexConverter.IsHexLowerChar(c)) { return false; } if (c != '0') { result = true; } } return result; } } public readonly struct ActivitySpanId : IEquatable { private readonly string _hexString; internal ActivitySpanId(string hexString) { _hexString = hexString; } public unsafe static ActivitySpanId CreateRandom() { ulong num = default(ulong); ActivityTraceId.SetToRandomBytes(new Span(&num, 8)); return new ActivitySpanId(System.HexConverter.ToString(new ReadOnlySpan(&num, 8), System.HexConverter.Casing.Lower)); } public static ActivitySpanId CreateFromBytes(ReadOnlySpan idData) { if (idData.Length != 8) { throw new ArgumentOutOfRangeException("idData"); } return new ActivitySpanId(System.HexConverter.ToString(idData, System.HexConverter.Casing.Lower)); } public static ActivitySpanId CreateFromUtf8String(ReadOnlySpan idData) { return new ActivitySpanId(idData); } public static ActivitySpanId CreateFromString(ReadOnlySpan idData) { if (idData.Length != 16 || !ActivityTraceId.IsLowerCaseHexAndNotAllZeros(idData)) { throw new ArgumentOutOfRangeException("idData"); } return new ActivitySpanId(idData.ToString()); } public string ToHexString() { return _hexString ?? "0000000000000000"; } public override string ToString() { return ToHexString(); } public static bool operator ==(ActivitySpanId spanId1, ActivitySpanId spandId2) { return spanId1._hexString == spandId2._hexString; } public static bool operator !=(ActivitySpanId spanId1, ActivitySpanId spandId2) { return spanId1._hexString != spandId2._hexString; } public bool Equals(ActivitySpanId spanId) { return _hexString == spanId._hexString; } public override bool Equals([NotNullWhen(true)] object? obj) { if (obj is ActivitySpanId activitySpanId) { return _hexString == activitySpanId._hexString; } return false; } public override int GetHashCode() { return ToHexString().GetHashCode(); } private unsafe ActivitySpanId(ReadOnlySpan idData) { if (idData.Length != 16) { throw new ArgumentOutOfRangeException("idData"); } if (!Utf8Parser.TryParse(idData, out ulong value, out int _, 'x')) { _hexString = CreateRandom()._hexString; return; } if (BitConverter.IsLittleEndian) { value = BinaryPrimitives.ReverseEndianness(value); } _hexString = System.HexConverter.ToString(new ReadOnlySpan(&value, 8), System.HexConverter.Casing.Lower); } public void CopyTo(Span destination) { ActivityTraceId.SetSpanFromHexChars(ToHexString().AsSpan(), destination); } } public enum ActivityStatusCode { Unset, Ok, Error } public class ActivityTagsCollection : IDictionary, ICollection>, IEnumerable>, IEnumerable { public struct Enumerator : IEnumerator>, IEnumerator, IDisposable { private List>.Enumerator _enumerator; public KeyValuePair Current => _enumerator.Current; object IEnumerator.Current => ((IEnumerator)_enumerator).Current; internal Enumerator(List> list) { _enumerator = list.GetEnumerator(); } public void Dispose() { _enumerator.Dispose(); } public bool MoveNext() { return _enumerator.MoveNext(); } void IEnumerator.Reset() { ((IEnumerator)_enumerator).Reset(); } } private readonly List> _list = new List>(); public object? this[string key] { get { int num = FindIndex(key); if (num >= 0) { return _list[num].Value; } return null; } set { ExceptionPolyfills.ThrowIfNull(key, "key"); int num = FindIndex(key); if (value == null) { if (num >= 0) { _list.RemoveAt(num); } } else if (num >= 0) { _list[num] = new KeyValuePair(key, value); } else { _list.Add(new KeyValuePair(key, value)); } } } public ICollection Keys { get { List list = new List(_list.Count); foreach (KeyValuePair item in _list) { list.Add(item.Key); } return list; } } public ICollection Values { get { List list = new List(_list.Count); foreach (KeyValuePair item in _list) { list.Add(item.Value); } return list; } } public bool IsReadOnly => false; public int Count => _list.Count; public ActivityTagsCollection() { } public ActivityTagsCollection(IEnumerable> list) { ExceptionPolyfills.ThrowIfNull(list, "list"); foreach (KeyValuePair item in list) { if (item.Key != null) { this[item.Key] = item.Value; } } } public void Add(string key, object? value) { ExceptionPolyfills.ThrowIfNull(key, "key"); if (FindIndex(key) >= 0) { throw new InvalidOperationException(System.SR.Format(System.SR.KeyAlreadyExist, key)); } _list.Add(new KeyValuePair(key, value)); } public void Add(KeyValuePair item) { if (item.Key == null) { throw new ArgumentNullException("item"); } if (FindIndex(item.Key) >= 0) { throw new InvalidOperationException(System.SR.Format(System.SR.KeyAlreadyExist, item.Key)); } _list.Add(item); } public void Clear() { _list.Clear(); } public bool Contains(KeyValuePair item) { return _list.Contains(item); } public bool ContainsKey(string key) { return FindIndex(key) >= 0; } public void CopyTo(KeyValuePair[] array, int arrayIndex) { _list.CopyTo(array, arrayIndex); } IEnumerator> IEnumerable>.GetEnumerator() { return new Enumerator(_list); } public Enumerator GetEnumerator() { return new Enumerator(_list); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_list); } public bool Remove(string key) { ExceptionPolyfills.ThrowIfNull(key, "key"); int num = FindIndex(key); if (num >= 0) { _list.RemoveAt(num); return true; } return false; } public bool Remove(KeyValuePair item) { return _list.Remove(item); } public bool TryGetValue(string key, out object? value) { int num = FindIndex(key); if (num >= 0) { value = _list[num].Value; return true; } value = null; return false; } private int FindIndex(string key) { for (int i = 0; i < _list.Count; i++) { if (_list[i].Key == key) { return i; } } return -1; } } public readonly struct ActivityContext : IEquatable { public ActivityTraceId TraceId { get; } public ActivitySpanId SpanId { get; } public ActivityTraceFlags TraceFlags { get; } public string? TraceState { get; } public bool IsRemote { get; } public ActivityContext(ActivityTraceId traceId, ActivitySpanId spanId, ActivityTraceFlags traceFlags, string? traceState = null, bool isRemote = false) { TraceId = traceId; SpanId = spanId; TraceFlags = traceFlags; TraceState = traceState; IsRemote = isRemote; } public static bool TryParse(string? traceParent, string? traceState, bool isRemote, out ActivityContext context) { if (traceParent == null) { context = default(ActivityContext); return false; } return Activity.TryConvertIdToContext(traceParent, traceState, isRemote, out context); } public static bool TryParse(string? traceParent, string? traceState, out ActivityContext context) { return TryParse(traceParent, traceState, isRemote: false, out context); } public static ActivityContext Parse(string traceParent, string? traceState) { ExceptionPolyfills.ThrowIfNull(traceParent, "traceParent"); if (!Activity.TryConvertIdToContext(traceParent, traceState, isRemote: false, out var context)) { throw new ArgumentException(System.SR.InvalidTraceParent); } return context; } public bool Equals(ActivityContext value) { if (SpanId.Equals(value.SpanId) && TraceId.Equals(value.TraceId) && TraceFlags == value.TraceFlags && TraceState == value.TraceState) { return IsRemote == value.IsRemote; } return false; } public override bool Equals([NotNullWhen(true)] object? obj) { if (!(obj is ActivityContext value)) { return false; } return Equals(value); } public static bool operator ==(ActivityContext left, ActivityContext right) { return left.Equals(right); } public static bool operator !=(ActivityContext left, ActivityContext right) { return !(left == right); } public override int GetHashCode() { if (this == default(ActivityContext)) { return 0; } int num = 5381; num = (num << 5) + num + TraceId.GetHashCode(); num = (num << 5) + num + SpanId.GetHashCode(); num = (int)((num << 5) + num + TraceFlags); return (num << 5) + num + ((TraceState != null) ? TraceState.GetHashCode() : 0); } } public readonly struct ActivityCreationOptions { private readonly ActivityTagsCollection _samplerTags; private readonly ActivityContext _context; private readonly string _traceState; public ActivitySource Source { get; } public string Name { get; } public ActivityKind Kind { get; } public T Parent { get; } public IEnumerable>? Tags { get; } public IEnumerable? Links { get; } public ActivityTagsCollection SamplingTags { get { if (_samplerTags == null) { Unsafe.AsRef(in _samplerTags) = new ActivityTagsCollection(); } return _samplerTags; } } public ActivityTraceId TraceId { get { if (Parent is ActivityContext && IdFormat == ActivityIdFormat.W3C && _context == default(ActivityContext)) { ActivityTraceId traceId = Activity.TraceIdGenerator?.Invoke() ?? ActivityTraceId.CreateRandom(); Unsafe.AsRef(in _context) = new ActivityContext(traceId, default(ActivitySpanId), ActivityTraceFlags.None); } return _context.TraceId; } } public string? TraceState { get { return _traceState; } init { _traceState = value; } } internal ActivityIdFormat IdFormat { get; } internal ActivityCreationOptions(ActivitySource source, string name, T parent, ActivityKind kind, IEnumerable> tags, IEnumerable links, ActivityIdFormat idFormat) { Source = source; Name = name; Kind = kind; Parent = parent; Tags = tags; Links = links; IdFormat = idFormat; if (IdFormat == ActivityIdFormat.Unknown && Activity.ForceDefaultIdFormat) { IdFormat = Activity.DefaultIdFormat; } _samplerTags = null; _traceState = null; if (parent is ActivityContext activityContext && activityContext != default(ActivityContext)) { _context = activityContext; if (IdFormat == ActivityIdFormat.Unknown) { IdFormat = ActivityIdFormat.W3C; } _traceState = activityContext.TraceState; } else if (parent is string traceParent) { if (IdFormat != ActivityIdFormat.Hierarchical) { if (ActivityContext.TryParse(traceParent, null, out _context)) { IdFormat = ActivityIdFormat.W3C; } if (IdFormat == ActivityIdFormat.Unknown) { IdFormat = ActivityIdFormat.Hierarchical; } } else { _context = default(ActivityContext); } } else { _context = default(ActivityContext); if (IdFormat == ActivityIdFormat.Unknown) { IdFormat = ((Activity.Current != null) ? Activity.Current.IdFormat : Activity.DefaultIdFormat); } } } internal void SetTraceState(string traceState) { Unsafe.AsRef(in _traceState) = traceState; } internal ActivityTagsCollection GetSamplingTags() { return _samplerTags; } internal ActivityContext GetContext() { return _context; } } public enum ActivitySamplingResult { None, PropagationData, AllData, AllDataAndRecorded } public readonly struct ActivityEvent { private static readonly IEnumerable> s_emptyTags = Array.Empty>(); private readonly Activity.TagsLinkedList _tags; public string Name { get; } public DateTimeOffset Timestamp { get; } public IEnumerable> Tags { get { IEnumerable> tags = _tags; return tags ?? s_emptyTags; } } public ActivityEvent(string name) : this(name, DateTimeOffset.UtcNow) { } public ActivityEvent(string name, DateTimeOffset timestamp = default(DateTimeOffset), ActivityTagsCollection? tags = null) : this(name, timestamp, tags, tags?.Count ?? 0) { } internal ActivityEvent(string name, DateTimeOffset timestamp, ref TagList tags) : this(name, timestamp, tags, tags.Count) { } private ActivityEvent(string name, DateTimeOffset timestamp, IEnumerable> tags, int tagsCount) { Name = name ?? string.Empty; Timestamp = ((timestamp != default(DateTimeOffset)) ? timestamp : DateTimeOffset.UtcNow); _tags = ((tagsCount > 0) ? new Activity.TagsLinkedList(tags) : null); } public Activity.Enumerator> EnumerateTagObjects() { return new Activity.Enumerator>(_tags?.First); } } public enum ActivityKind { Internal, Server, Client, Producer, Consumer } public readonly struct ActivityLink : IEquatable { private readonly Activity.TagsLinkedList _tags; public ActivityContext Context { get; } public IEnumerable>? Tags => _tags; public ActivityLink(ActivityContext context, ActivityTagsCollection? tags = null) { Context = context; _tags = ((tags != null && tags.Count > 0) ? new Activity.TagsLinkedList(tags) : null); } public override bool Equals([NotNullWhen(true)] object? obj) { if (obj is ActivityLink value) { return Equals(value); } return false; } public bool Equals(ActivityLink value) { if (Context == value.Context) { return value.Tags == Tags; } return false; } public static bool operator ==(ActivityLink left, ActivityLink right) { return left.Equals(right); } public static bool operator !=(ActivityLink left, ActivityLink right) { return !left.Equals(right); } public Activity.Enumerator> EnumerateTagObjects() { return new Activity.Enumerator>(_tags?.First); } public override int GetHashCode() { if (this == default(ActivityLink)) { return 0; } int num = 5381; num = (num << 5) + num + Context.GetHashCode(); if (Tags != null) { foreach (KeyValuePair tag in Tags) { num = (num << 5) + num + tag.Key.GetHashCode(); if (tag.Value != null) { num = (num << 5) + num + tag.Value.GetHashCode(); } } } return num; } } public delegate ActivitySamplingResult SampleActivity(ref ActivityCreationOptions options); public delegate void ExceptionRecorder(Activity activity, Exception exception, ref TagList tags); public sealed class ActivityListener : IDisposable { public Action? ActivityStarted { get; set; } public Action? ActivityStopped { get; set; } public ExceptionRecorder? ExceptionRecorder { get; set; } public Func? ShouldListenTo { get; set; } public SampleActivity? SampleUsingParentId { get; set; } public SampleActivity? Sample { get; set; } public void Dispose() { ActivitySource.DetachListener(this); } } public sealed class ActivitySource : IDisposable { internal delegate void Function(T item, ref ActivityCreationOptions data, ref ActivitySamplingResult samplingResult, ref ActivityCreationOptions dataWithContext); private static readonly SynchronizedList s_activeSources = new SynchronizedList(); private static readonly SynchronizedList s_allListeners = new SynchronizedList(); private SynchronizedList _listeners; public string Name { get; } public string? Version { get; } public IEnumerable>? Tags { get; } public string? TelemetrySchemaUrl { get; } public ActivitySource(string name) : this(name, "", null, null) { } [EditorBrowsable(EditorBrowsableState.Never)] public ActivitySource(string name, string? version = "") : this(name, version, null, null) { } public ActivitySource(string name, string? version = "", IEnumerable>? tags = null) : this(name, version, tags, null) { } public ActivitySource(ActivitySourceOptions options) : this((options ?? throw new ArgumentNullException("options")).Name, options.Version, options.Tags, options.TelemetrySchemaUrl) { } private ActivitySource(string name, string version, IEnumerable> tags, string telemetrySchemaUrl) { Name = name ?? throw new ArgumentNullException("name"); Version = version; TelemetrySchemaUrl = telemetrySchemaUrl; if (tags != null) { List> list = new List>(tags); list.Sort((KeyValuePair left, KeyValuePair right) => string.Compare(left.Key, right.Key, StringComparison.Ordinal)); Tags = list.AsReadOnly(); } s_activeSources.Add(this); s_allListeners.EnumWithAction(delegate(ActivityListener listener, object source) { Func shouldListenTo = listener.ShouldListenTo; if (shouldListenTo != null) { ActivitySource activitySource = (ActivitySource)source; if (shouldListenTo(activitySource)) { activitySource.AddListener(listener); } } }, this); GC.KeepAlive(DiagnosticSourceEventSource.Log); } public bool HasListeners() { SynchronizedList listeners = _listeners; if (listeners != null) { return listeners.Count > 0; } return false; } public Activity? CreateActivity(string name, ActivityKind kind) { return CreateActivity(name, kind, default(ActivityContext), null, null, null, default(DateTimeOffset), startIt: false); } public Activity? CreateActivity(string name, ActivityKind kind, ActivityContext parentContext, IEnumerable>? tags = null, IEnumerable? links = null, ActivityIdFormat idFormat = ActivityIdFormat.Unknown) { return CreateActivity(name, kind, parentContext, null, tags, links, default(DateTimeOffset), startIt: false, idFormat); } public Activity? CreateActivity(string name, ActivityKind kind, string? parentId, IEnumerable>? tags = null, IEnumerable? links = null, ActivityIdFormat idFormat = ActivityIdFormat.Unknown) { return CreateActivity(name, kind, default(ActivityContext), parentId, tags, links, default(DateTimeOffset), startIt: false, idFormat); } public Activity? StartActivity([CallerMemberName] string name = "", ActivityKind kind = ActivityKind.Internal) { return CreateActivity(name, kind, default(ActivityContext), null, null, null, default(DateTimeOffset)); } public Activity? StartActivity(string name, ActivityKind kind, ActivityContext parentContext, IEnumerable>? tags = null, IEnumerable? links = null, DateTimeOffset startTime = default(DateTimeOffset)) { return CreateActivity(name, kind, parentContext, null, tags, links, startTime); } public Activity? StartActivity(string name, ActivityKind kind, string? parentId, IEnumerable>? tags = null, IEnumerable? links = null, DateTimeOffset startTime = default(DateTimeOffset)) { return CreateActivity(name, kind, default(ActivityContext), parentId, tags, links, startTime); } public Activity? StartActivity(ActivityKind kind, ActivityContext parentContext = default(ActivityContext), IEnumerable>? tags = null, IEnumerable? links = null, DateTimeOffset startTime = default(DateTimeOffset), [CallerMemberName] string name = "") { return CreateActivity(name, kind, parentContext, null, tags, links, startTime); } private Activity CreateActivity(string name, ActivityKind kind, ActivityContext context, string parentId, IEnumerable> tags, IEnumerable links, DateTimeOffset startTime, bool startIt = true, ActivityIdFormat idFormat = ActivityIdFormat.Unknown) { SynchronizedList listeners = _listeners; if (listeners == null || listeners.Count == 0) { return null; } Activity result = null; ActivitySamplingResult samplingResult = ActivitySamplingResult.None; ActivityTagsCollection activityTagsCollection; string traceState; if (parentId != null) { ActivityCreationOptions activityCreationOptions = default(ActivityCreationOptions); ActivityCreationOptions dataWithContext = default(ActivityCreationOptions); activityCreationOptions = new ActivityCreationOptions(this, name, parentId, kind, tags, links, idFormat); if (activityCreationOptions.IdFormat == ActivityIdFormat.W3C) { dataWithContext = new ActivityCreationOptions(this, name, activityCreationOptions.GetContext(), kind, tags, links, ActivityIdFormat.W3C); } listeners.EnumWithFunc(delegate(ActivityListener listener, ref ActivityCreationOptions reference, ref ActivitySamplingResult reference3, ref ActivityCreationOptions reference2) { SampleActivity sampleUsingParentId = listener.SampleUsingParentId; if (sampleUsingParentId != null) { ActivitySamplingResult activitySamplingResult = sampleUsingParentId(ref reference); reference2.SetTraceState(reference.TraceState); if (activitySamplingResult > reference3) { reference3 = activitySamplingResult; } } else if (reference.IdFormat == ActivityIdFormat.W3C) { SampleActivity sample = listener.Sample; if (sample != null) { ActivitySamplingResult activitySamplingResult2 = sample(ref reference2); reference.SetTraceState(reference2.TraceState); if (activitySamplingResult2 > reference3) { reference3 = activitySamplingResult2; } } } }, ref activityCreationOptions, ref samplingResult, ref dataWithContext); if (context == default(ActivityContext)) { if (activityCreationOptions.GetContext() != default(ActivityContext)) { context = activityCreationOptions.GetContext(); parentId = null; } else if (dataWithContext.GetContext() != default(ActivityContext)) { context = dataWithContext.GetContext(); parentId = null; } } activityTagsCollection = activityCreationOptions.GetSamplingTags(); ActivityTagsCollection samplingTags = dataWithContext.GetSamplingTags(); if (samplingTags != null) { if (activityTagsCollection == null) { activityTagsCollection = samplingTags; } else { foreach (KeyValuePair item in samplingTags) { activityTagsCollection.Add(item); } } } idFormat = activityCreationOptions.IdFormat; traceState = activityCreationOptions.TraceState; } else { bool flag = context == default(ActivityContext) && Activity.Current != null; ActivityCreationOptions data = new ActivityCreationOptions(this, name, flag ? Activity.Current.Context : context, kind, tags, links, idFormat); listeners.EnumWithFunc(delegate(ActivityListener listener, ref ActivityCreationOptions options, ref ActivitySamplingResult reference, ref ActivityCreationOptions unused) { SampleActivity sample = listener.Sample; if (sample != null) { ActivitySamplingResult activitySamplingResult = sample(ref options); if (activitySamplingResult > reference) { reference = activitySamplingResult; } } }, ref data, ref samplingResult, ref data); if (!flag) { context = data.GetContext(); } activityTagsCollection = data.GetSamplingTags(); idFormat = data.IdFormat; traceState = data.TraceState; } if (samplingResult != ActivitySamplingResult.None) { result = Activity.Create(this, name, kind, parentId, context, tags, links, startTime, activityTagsCollection, samplingResult, startIt, idFormat, traceState); } return result; } public void Dispose() { _listeners = null; s_activeSources.Remove(this); } public static void AddActivityListener(ActivityListener listener) { ExceptionPolyfills.ThrowIfNull(listener, "listener"); if (!s_allListeners.AddIfNotExist(listener)) { return; } s_activeSources.EnumWithAction(delegate(ActivitySource source, object obj) { Func shouldListenTo = ((ActivityListener)obj).ShouldListenTo; if (shouldListenTo != null && shouldListenTo(source)) { source.AddListener((ActivityListener)obj); } }, listener); } internal void AddListener(ActivityListener listener) { if (_listeners == null) { Interlocked.CompareExchange(ref _listeners, new SynchronizedList(), null); } _listeners.AddIfNotExist(listener); } internal static void DetachListener(ActivityListener listener) { s_allListeners.Remove(listener); s_activeSources.EnumWithAction(delegate(ActivitySource source, object obj) { source._listeners?.Remove((ActivityListener)obj); }, listener); } internal void NotifyActivityStart(Activity activity) { SynchronizedList listeners = _listeners; if (listeners != null && listeners.Count > 0) { listeners.EnumWithAction(delegate(ActivityListener listener, object obj) { listener.ActivityStarted?.Invoke((Activity)obj); }, activity); } } internal void NotifyActivityStop(Activity activity) { SynchronizedList listeners = _listeners; if (listeners != null && listeners.Count > 0) { listeners.EnumWithAction(delegate(ActivityListener listener, object obj) { listener.ActivityStopped?.Invoke((Activity)obj); }, activity); } } internal void NotifyActivityAddException(Activity activity, Exception exception, ref TagList tags) { SynchronizedList listeners = _listeners; if (listeners != null && listeners.Count > 0) { listeners.EnumWithExceptionNotification(activity, exception, ref tags); } } } internal sealed class SynchronizedList { private readonly object _writeLock; private T[] _volatileArray; public int Count => _volatileArray.Length; public SynchronizedList() { _volatileArray = Array.Empty(); _writeLock = new object(); } public void Add(T item) { lock (_writeLock) { T[] array = new T[_volatileArray.Length + 1]; Array.Copy(_volatileArray, array, _volatileArray.Length); array[_volatileArray.Length] = item; _volatileArray = array; } } public bool AddIfNotExist(T item) { lock (_writeLock) { if (Array.IndexOf(_volatileArray, item) >= 0) { return false; } T[] array = new T[_volatileArray.Length + 1]; Array.Copy(_volatileArray, array, _volatileArray.Length); array[_volatileArray.Length] = item; _volatileArray = array; return true; } } public bool Remove(T item) { lock (_writeLock) { int num = Array.IndexOf(_volatileArray, item); if (num < 0) { return false; } T[] array = new T[_volatileArray.Length - 1]; Array.Copy(_volatileArray, array, num); Array.Copy(_volatileArray, num + 1, array, num, _volatileArray.Length - num - 1); _volatileArray = array; return true; } } public void EnumWithFunc(ActivitySource.Function func, ref ActivityCreationOptions data, ref ActivitySamplingResult samplingResult, ref ActivityCreationOptions dataWithContext) { T[] volatileArray = _volatileArray; foreach (T item in volatileArray) { func(item, ref data, ref samplingResult, ref dataWithContext); } } public void EnumWithAction(Action action, object arg) { T[] volatileArray = _volatileArray; foreach (T arg2 in volatileArray) { action(arg2, arg); } } public void EnumWithExceptionNotification(Activity activity, Exception exception, ref TagList tags) { if (!(typeof(T) != typeof(ActivityListener))) { T[] volatileArray = _volatileArray; for (int i = 0; i < volatileArray.Length; i++) { (volatileArray[i] as ActivityListener).ExceptionRecorder?.Invoke(activity, exception, ref tags); } } } } public class ActivitySourceOptions { private string _name; public string Name { get { return _name; } set { _name = value ?? throw new ArgumentNullException("value"); } } public string? Version { get; set; } = string.Empty; public IEnumerable>? Tags { get; set; } public string? TelemetrySchemaUrl { get; set; } public ActivitySourceOptions(string name) { _name = name ?? throw new ArgumentNullException("name"); } } public abstract class DiagnosticSource { internal const string WriteRequiresUnreferencedCode = "The type of object being written to DiagnosticSource cannot be discovered statically."; internal const string WriteOfTRequiresUnreferencedCode = "Only the properties of the T type will be preserved. Properties of referenced types and properties of derived types may be trimmed."; [RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public abstract void Write(string name, object? value); [RequiresUnreferencedCode("Only the properties of the T type will be preserved. Properties of referenced types and properties of derived types may be trimmed.")] public void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(string name, T value) { Write(name, (object?)value); } public abstract bool IsEnabled(string name); public virtual bool IsEnabled(string name, object? arg1, object? arg2 = null) { return IsEnabled(name); } [RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public Activity StartActivity(Activity activity, object? args) { activity.Start(); Write(activity.OperationName + ".Start", args); return activity; } [RequiresUnreferencedCode("Only the properties of the T type will be preserved. Properties of referenced types and properties of derived types may be trimmed.")] public Activity StartActivity<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(Activity activity, T args) { return StartActivity(activity, (object?)args); } [RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public void StopActivity(Activity activity, object? args) { if (activity.Duration == TimeSpan.Zero) { activity.SetEndTime(Activity.GetUtcNow()); } Write(activity.OperationName + ".Stop", args); activity.Stop(); } [RequiresUnreferencedCode("Only the properties of the T type will be preserved. Properties of referenced types and properties of derived types may be trimmed.")] public void StopActivity<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(Activity activity, T args) { StopActivity(activity, (object?)args); } public virtual void OnActivityImport(Activity activity, object? payload) { } public virtual void OnActivityExport(Activity activity, object? payload) { } } public class DiagnosticListener : DiagnosticSource, IObservable>, IDisposable { private sealed class DiagnosticSubscription : IDisposable { internal IObserver> Observer; internal Predicate IsEnabled1Arg; internal Func IsEnabled3Arg; internal Action OnActivityImport; internal Action OnActivityExport; internal DiagnosticListener Owner; internal DiagnosticSubscription Next; public void Dispose() { DiagnosticSubscription subscriptions; DiagnosticSubscription value; do { subscriptions = Owner._subscriptions; value = Remove(subscriptions, this); } while (Interlocked.CompareExchange(ref Owner._subscriptions, value, subscriptions) != subscriptions); } private static DiagnosticSubscription Remove(DiagnosticSubscription subscriptions, DiagnosticSubscription subscription) { if (subscriptions == null) { return null; } if (subscriptions.Observer == subscription.Observer && subscriptions.IsEnabled1Arg == subscription.IsEnabled1Arg && subscriptions.IsEnabled3Arg == subscription.IsEnabled3Arg) { return subscriptions.Next; } return new DiagnosticSubscription { Observer = subscriptions.Observer, Owner = subscriptions.Owner, IsEnabled1Arg = subscriptions.IsEnabled1Arg, IsEnabled3Arg = subscriptions.IsEnabled3Arg, Next = Remove(subscriptions.Next, subscription) }; } } private sealed class AllListenerObservable : IObservable { internal sealed class AllListenerSubscription : IDisposable { private readonly AllListenerObservable _owner; internal readonly IObserver Subscriber; internal AllListenerSubscription Next; internal AllListenerSubscription(AllListenerObservable owner, IObserver subscriber, AllListenerSubscription next) { _owner = owner; Subscriber = subscriber; Next = next; } public void Dispose() { if (_owner.Remove(this)) { Subscriber.OnCompleted(); } } } private AllListenerSubscription _subscriptions; public IDisposable Subscribe(IObserver observer) { lock (s_allListenersLock) { for (DiagnosticListener diagnosticListener = s_allListeners; diagnosticListener != null; diagnosticListener = diagnosticListener._next) { observer.OnNext(diagnosticListener); } _subscriptions = new AllListenerSubscription(this, observer, _subscriptions); return _subscriptions; } } internal void OnNewDiagnosticListener(DiagnosticListener diagnosticListener) { for (AllListenerSubscription allListenerSubscription = _subscriptions; allListenerSubscription != null; allListenerSubscription = allListenerSubscription.Next) { allListenerSubscription.Subscriber.OnNext(diagnosticListener); } } private bool Remove(AllListenerSubscription subscription) { lock (s_allListenersLock) { if (_subscriptions == subscription) { _subscriptions = subscription.Next; return true; } if (_subscriptions != null) { AllListenerSubscription allListenerSubscription = _subscriptions; while (allListenerSubscription.Next != null) { if (allListenerSubscription.Next == subscription) { allListenerSubscription.Next = allListenerSubscription.Next.Next; return true; } allListenerSubscription = allListenerSubscription.Next; } } return false; } } } private volatile DiagnosticSubscription _subscriptions; private DiagnosticListener _next; private bool _disposed; private static DiagnosticListener s_allListeners; private static volatile AllListenerObservable s_allListenerObservable; private static readonly object s_allListenersLock = new object(); public static IObservable AllListeners => s_allListenerObservable ?? Interlocked.CompareExchange(ref s_allListenerObservable, new AllListenerObservable(), null) ?? s_allListenerObservable; public string Name { get; } public override void OnActivityImport(Activity activity, object? payload) { for (DiagnosticSubscription diagnosticSubscription = _subscriptions; diagnosticSubscription != null; diagnosticSubscription = diagnosticSubscription.Next) { diagnosticSubscription.OnActivityImport?.Invoke(activity, payload); } } public override void OnActivityExport(Activity activity, object? payload) { for (DiagnosticSubscription diagnosticSubscription = _subscriptions; diagnosticSubscription != null; diagnosticSubscription = diagnosticSubscription.Next) { diagnosticSubscription.OnActivityExport?.Invoke(activity, payload); } } public virtual IDisposable Subscribe(IObserver> observer, Func? isEnabled, Action? onActivityImport = null, Action? onActivityExport = null) { if (isEnabled != null) { return SubscribeInternal(observer, (string name) => IsEnabled(name, null), isEnabled, onActivityImport, onActivityExport); } return SubscribeInternal(observer, null, null, onActivityImport, onActivityExport); } public virtual IDisposable Subscribe(IObserver> observer, Predicate? isEnabled) { if (isEnabled == null) { return SubscribeInternal(observer, null, null, null, null); } Predicate localIsEnabled = isEnabled; return SubscribeInternal(observer, isEnabled, (string name, object arg1, object arg2) => localIsEnabled(name), null, null); } public virtual IDisposable Subscribe(IObserver> observer, Func? isEnabled) { if (isEnabled != null) { return SubscribeInternal(observer, (string name) => IsEnabled(name, null), isEnabled, null, null); } return SubscribeInternal(observer, null, null, null, null); } public virtual IDisposable Subscribe(IObserver> observer) { return SubscribeInternal(observer, null, null, null, null); } public DiagnosticListener(string name) { Name = name; lock (s_allListenersLock) { s_allListenerObservable?.OnNewDiagnosticListener(this); _next = s_allListeners; s_allListeners = this; } GC.KeepAlive(DiagnosticSourceEventSource.Log); } public virtual void Dispose() { lock (s_allListenersLock) { if (_disposed) { return; } _disposed = true; if (s_allListeners == this) { s_allListeners = s_allListeners._next; } else { for (DiagnosticListener next = s_allListeners; next != null; next = next._next) { if (next._next == this) { next._next = _next; break; } } } _next = null; } DiagnosticSubscription value = null; for (value = Interlocked.Exchange(ref _subscriptions, value); value != null; value = value.Next) { value.Observer.OnCompleted(); } } public override string ToString() { return Name ?? string.Empty; } public bool IsEnabled() { return _subscriptions != null; } public override bool IsEnabled(string name) { for (DiagnosticSubscription diagnosticSubscription = _subscriptions; diagnosticSubscription != null; diagnosticSubscription = diagnosticSubscription.Next) { if (diagnosticSubscription.IsEnabled1Arg == null || diagnosticSubscription.IsEnabled1Arg(name)) { return true; } } return false; } public override bool IsEnabled(string name, object? arg1, object? arg2 = null) { for (DiagnosticSubscription diagnosticSubscription = _subscriptions; diagnosticSubscription != null; diagnosticSubscription = diagnosticSubscription.Next) { if (diagnosticSubscription.IsEnabled3Arg == null || diagnosticSubscription.IsEnabled3Arg(name, arg1, arg2)) { return true; } } return false; } [RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public override void Write(string name, object? value) { for (DiagnosticSubscription diagnosticSubscription = _subscriptions; diagnosticSubscription != null; diagnosticSubscription = diagnosticSubscription.Next) { diagnosticSubscription.Observer.OnNext(new KeyValuePair(name, value)); } } private DiagnosticSubscription SubscribeInternal(IObserver> observer, Predicate isEnabled1Arg, Func isEnabled3Arg, Action onActivityImport, Action onActivityExport) { if (_disposed) { return new DiagnosticSubscription { Owner = this }; } DiagnosticSubscription diagnosticSubscription = new DiagnosticSubscription { Observer = observer, IsEnabled1Arg = isEnabled1Arg, IsEnabled3Arg = isEnabled3Arg, OnActivityImport = onActivityImport, OnActivityExport = onActivityExport, Owner = this, Next = _subscriptions }; while (Interlocked.CompareExchange(ref _subscriptions, diagnosticSubscription, diagnosticSubscription.Next) != diagnosticSubscription.Next) { diagnosticSubscription.Next = _subscriptions; } return diagnosticSubscription; } } [EventSource(Name = "Microsoft-Diagnostics-DiagnosticSource")] internal sealed class DiagnosticSourceEventSource : EventSource { public static class Keywords { public const EventKeywords Messages = (EventKeywords)1L; public const EventKeywords Events = (EventKeywords)2L; public const EventKeywords IgnoreShortCutKeywords = (EventKeywords)2048L; public const EventKeywords AspNetCoreHosting = (EventKeywords)4096L; public const EventKeywords EntityFrameworkCoreCommands = (EventKeywords)8192L; } public static readonly DiagnosticSourceEventSource Log = new DiagnosticSourceEventSource(); private readonly string AspNetCoreHostingKeywordValue = "Microsoft.AspNetCore/Microsoft.AspNetCore.Hosting.BeginRequest@Activity1Start:-httpContext.Request.Method;httpContext.Request.Host;httpContext.Request.Path;httpContext.Request.QueryString\nMicrosoft.AspNetCore/Microsoft.AspNetCore.Hosting.EndRequest@Activity1Stop:-httpContext.TraceIdentifier;httpContext.Response.StatusCode"; private readonly string EntityFrameworkCoreCommandsKeywordValue = "Microsoft.EntityFrameworkCore/Microsoft.EntityFrameworkCore.BeforeExecuteCommand@Activity2Start:-Command.Connection.DataSource;Command.Connection.Database;Command.CommandText\nMicrosoft.EntityFrameworkCore/Microsoft.EntityFrameworkCore.AfterExecuteCommand@Activity2Stop:-"; private IDisposable _listener; private volatile bool _false; [Event(1, Keywords = (EventKeywords)1L)] public void Message(string Message) { WriteEvent(1, Message); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Arguments parameter is preserved by DynamicDependency")] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<, >))] [Event(2, Keywords = (EventKeywords)2L)] public void Event(string SourceName, string EventName, IEnumerable> Arguments) { WriteEvent(2, SourceName, EventName, Arguments); } [Event(3, Keywords = (EventKeywords)2L)] public void EventJson(string SourceName, string EventName, string ArgmentsJson) { WriteEvent(3, SourceName, EventName, ArgmentsJson); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Arguments parameter is preserved by DynamicDependency")] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<, >))] [Event(4, Keywords = (EventKeywords)2L)] public void Activity1Start(string SourceName, string EventName, IEnumerable> Arguments) { WriteEvent(4, SourceName, EventName, Arguments); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Arguments parameter is preserved by DynamicDependency")] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<, >))] [Event(5, Keywords = (EventKeywords)2L)] public void Activity1Stop(string SourceName, string EventName, IEnumerable> Arguments) { WriteEvent(5, SourceName, EventName, Arguments); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Arguments parameter is preserved by DynamicDependency")] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<, >))] [Event(6, Keywords = (EventKeywords)2L)] public void Activity2Start(string SourceName, string EventName, IEnumerable> Arguments) { WriteEvent(6, SourceName, EventName, Arguments); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Arguments parameter is preserved by DynamicDependency")] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<, >))] [Event(7, Keywords = (EventKeywords)2L)] public void Activity2Stop(string SourceName, string EventName, IEnumerable> Arguments) { WriteEvent(7, SourceName, EventName, Arguments); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Arguments parameter is preserved by DynamicDependency")] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<, >))] [Event(8, Keywords = (EventKeywords)2L, ActivityOptions = EventActivityOptions.Recursive)] public void RecursiveActivity1Start(string SourceName, string EventName, IEnumerable> Arguments) { WriteEvent(8, SourceName, EventName, Arguments); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Arguments parameter is preserved by DynamicDependency")] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<, >))] [Event(9, Keywords = (EventKeywords)2L, ActivityOptions = EventActivityOptions.Recursive)] public void RecursiveActivity1Stop(string SourceName, string EventName, IEnumerable> Arguments) { WriteEvent(9, SourceName, EventName, Arguments); } [Event(10, Keywords = (EventKeywords)2L)] public void NewDiagnosticListener(string SourceName) { WriteEvent(10, SourceName); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Arguments parameter is preserved by DynamicDependency")] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<, >))] [Event(11, Keywords = (EventKeywords)2L, ActivityOptions = EventActivityOptions.Recursive)] public void ActivityStart(string SourceName, string ActivityName, IEnumerable> Arguments) { WriteEvent(11, SourceName, ActivityName, Arguments); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Arguments parameter is preserved by DynamicDependency")] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<, >))] [Event(12, Keywords = (EventKeywords)2L, ActivityOptions = EventActivityOptions.Recursive)] public void ActivityStop(string SourceName, string ActivityName, IEnumerable> Arguments) { WriteEvent(12, SourceName, ActivityName, Arguments); } [Event(13, Keywords = (EventKeywords)1L)] public void Version(int Major, int Minor, int Patch) { WriteEvent(13, Major, Minor, Patch); } [NonEvent] protected override void OnEventCommand(EventCommandEventArgs command) { if (command.Command == EventCommand.Enable) { Version(ThisAssembly.AssemblyFileVersion.Major, ThisAssembly.AssemblyFileVersion.Minor, ThisAssembly.AssemblyFileVersion.Build); } BreakPointWithDebuggerFuncEval(); lock (this) { if ((command.Command == EventCommand.Update || command.Command == EventCommand.Enable) && IsEnabled(EventLevel.Informational, (EventKeywords)2L)) { string value = null; command.Arguments.TryGetValue("FilterAndPayloadSpecs", out value); if (!IsEnabled(EventLevel.Informational, (EventKeywords)2048L)) { if (IsEnabled(EventLevel.Informational, (EventKeywords)4096L)) { value = NewLineSeparate(value, AspNetCoreHostingKeywordValue); } if (IsEnabled(EventLevel.Informational, (EventKeywords)8192L)) { value = NewLineSeparate(value, EntityFrameworkCoreCommandsKeywordValue); } } _listener?.Dispose(); _listener = DsesFilterAndTransform.ParseFilterAndPayloadSpecs(this, value); } else if (command.Command == EventCommand.Update || command.Command == EventCommand.Disable) { _listener?.Dispose(); } } } private DiagnosticSourceEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } private static string NewLineSeparate(string str1, string str2) { if (string.IsNullOrEmpty(str1)) { return str2; } return str1 + "\n" + str2; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] [NonEvent] private void BreakPointWithDebuggerFuncEval() { new object(); while (_false) { _false = false; } } } internal sealed class DiagNode { public T Value; public DiagNode Next; public DiagNode(T value) { Value = value; } } internal sealed class DiagLinkedList : IEnumerable, IEnumerable { private DiagNode _first; private DiagNode _last; public DiagNode First => _first; public DiagLinkedList() { } public DiagLinkedList(T firstValue) { _last = (_first = new DiagNode(firstValue)); } public DiagLinkedList(IEnumerator e) { _last = (_first = new DiagNode(e.Current)); while (e.MoveNext()) { _last.Next = new DiagNode(e.Current); _last = _last.Next; } } public void Clear() { lock (this) { _first = (_last = null); } } private void UnsafeAdd(DiagNode newNode) { if (_first == null) { _first = (_last = newNode); return; } _last.Next = newNode; _last = newNode; } public void Add(T value) { DiagNode newNode = new DiagNode(value); lock (this) { UnsafeAdd(newNode); } } public bool AddIfNotExist(T value, Func compare) { lock (this) { for (DiagNode diagNode = _first; diagNode != null; diagNode = diagNode.Next) { if (compare(value, diagNode.Value)) { return false; } } DiagNode newNode = new DiagNode(value); UnsafeAdd(newNode); return true; } } public T Remove(T value, Func compare) { lock (this) { DiagNode diagNode = _first; if (diagNode == null) { return default(T); } if (compare(diagNode.Value, value)) { _first = diagNode.Next; if (_first == null) { _last = null; } return diagNode.Value; } for (DiagNode next = diagNode.Next; next != null; next = next.Next) { if (compare(next.Value, value)) { diagNode.Next = next.Next; if (_last == next) { _last = diagNode; } return next.Value; } diagNode = next; } return default(T); } } public void AddFront(T value) { DiagNode diagNode = new DiagNode(value); lock (this) { diagNode.Next = _first; _first = diagNode; } } public DiagEnumerator GetEnumerator() { return new DiagEnumerator(_first); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private static void ActivityLinkToString(ref ActivityLink al, ref System.Text.ValueStringBuilder vsb) { ActivityContext context = al.Context; vsb.Append("("); vsb.Append(context.TraceId.ToHexString()); vsb.Append(",\u200b"); vsb.Append(context.SpanId.ToHexString()); vsb.Append(",\u200b"); vsb.Append(context.TraceFlags.ToString()); vsb.Append(",\u200b"); vsb.Append(context.TraceState ?? "null"); vsb.Append(",\u200b"); vsb.Append(context.IsRemote ? "true" : "false"); if (al.Tags != null) { vsb.Append(",\u200b["); string s = ""; Activity.Enumerator> enumerator = al.EnumerateTagObjects().GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; vsb.Append(s); vsb.Append(current.Key); vsb.Append(":\u200b"); vsb.Append(current.Value?.ToString() ?? "null"); s = ",\u200b"; } vsb.Append("]"); } vsb.Append(")"); } private static void ActivityEventToString(ref ActivityEvent ae, ref System.Text.ValueStringBuilder vsb) { vsb.Append("("); vsb.Append(ae.Name); vsb.Append(",\u200b"); vsb.Append(ae.Timestamp.ToString("o")); if (ae.Tags != null) { vsb.Append(",\u200b["); string s = ""; Activity.Enumerator> enumerator = ae.EnumerateTagObjects().GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; vsb.Append(s); vsb.Append(current.Key); vsb.Append(":\u200b"); vsb.Append(current.Value?.ToString() ?? "null"); s = ",\u200b"; } vsb.Append("]"); } vsb.Append(")"); } public override string ToString() { lock (this) { DiagNode diagNode = _first; if (diagNode == null) { return "[]"; } Span initialBuffer = stackalloc char[256]; System.Text.ValueStringBuilder vsb = new System.Text.ValueStringBuilder(initialBuffer); vsb.Append("["); if (typeof(T) == typeof(ActivityLink)) { while (diagNode != null) { ActivityLink al = (ActivityLink)(object)diagNode.Value; ActivityLinkToString(ref al, ref vsb); diagNode = diagNode.Next; if (diagNode != null) { vsb.Append(",\u200b"); } } } else if (typeof(T) == typeof(ActivityEvent)) { while (diagNode != null) { ActivityEvent ae = (ActivityEvent)(object)diagNode.Value; ActivityEventToString(ref ae, ref vsb); diagNode = diagNode.Next; if (diagNode != null) { vsb.Append(",\u200b"); } } } else { while (diagNode != null) { vsb.Append(diagNode.Value?.ToString() ?? "null"); diagNode = diagNode.Next; if (diagNode != null) { vsb.Append(",\u200b"); } } } vsb.Append("]"); return vsb.ToString(); } } } internal struct DiagEnumerator : IEnumerator, IEnumerator, IDisposable { private static readonly DiagNode s_Empty = new DiagNode(default(T)); private DiagNode _nextNode; private DiagNode _currentNode; public T Current => _currentNode.Value; object IEnumerator.Current => Current; public DiagEnumerator(DiagNode head) { _nextNode = head; _currentNode = s_Empty; } public bool MoveNext() { if (_nextNode == null) { _currentNode = s_Empty; return false; } _currentNode = _nextNode; _nextNode = _nextNode.Next; return true; } public void Reset() { throw new NotSupportedException(); } public void Dispose() { } } [Flags] internal enum DsesActivityEvents { None = 0, ActivityStart = 1, ActivityStop = 2, All = 3 } internal sealed class DsesActivitySourceListener : IDisposable { private readonly struct SpecLookupKey { public readonly string activitySourceName; public readonly string activityName; public SpecLookupKey(string activitySourceName, string activityName) { this.activitySourceName = activitySourceName; this.activityName = activityName; } } private sealed class SpecLookupKeyComparer : IEqualityComparer { public static readonly SpecLookupKeyComparer Instance = new SpecLookupKeyComparer(); public bool Equals(SpecLookupKey x, SpecLookupKey y) { if (string.Equals(x.activitySourceName, y.activitySourceName, StringComparison.OrdinalIgnoreCase)) { return string.Equals(x.activityName, y.activityName, StringComparison.OrdinalIgnoreCase); } return false; } public int GetHashCode(SpecLookupKey obj) { int num = 5381; num = (num << 5) + num + StringComparer.OrdinalIgnoreCase.GetHashCode(obj.activitySourceName); return (num << 5) + num + ((obj.activityName != null) ? StringComparer.OrdinalIgnoreCase.GetHashCode(obj.activityName) : 0); } } private readonly DiagnosticSourceEventSource _eventSource; private DsesFilterAndTransform _wildcardSpec; private Dictionary _specsBySourceNameAndActivityName; private HashSet _listenToActivitySourceNames; private bool _hasActivityNameSpecDefined; private ActivityListener _activityListener; public static DsesActivitySourceListener Create(DiagnosticSourceEventSource eventSource, DsesFilterAndTransform activitySourceSpecs) { DsesActivitySourceListener dsesActivitySourceListener = new DsesActivitySourceListener(eventSource); dsesActivitySourceListener.NormalizeActivitySourceSpecsList(activitySourceSpecs); dsesActivitySourceListener.CreateActivityListener(); return dsesActivitySourceListener; } private DsesActivitySourceListener(DiagnosticSourceEventSource eventSource) { _eventSource = eventSource; } public void Dispose() { _activityListener?.Dispose(); _activityListener = null; _wildcardSpec = null; _specsBySourceNameAndActivityName = null; _listenToActivitySourceNames = null; } private void NormalizeActivitySourceSpecsList(DsesFilterAndTransform activitySourceSpecs) { while (activitySourceSpecs != null) { DsesFilterAndTransform dsesFilterAndTransform = activitySourceSpecs; activitySourceSpecs = activitySourceSpecs.Next; if (dsesFilterAndTransform.SourceName == "*") { if (_wildcardSpec != null) { if (_eventSource.IsEnabled(EventLevel.Warning, (EventKeywords)1L)) { _eventSource.Message("DiagnosticSource: Ignoring wildcard activity source filterAndPayloadSpec rule because a previous rule was defined"); } } else { _wildcardSpec = dsesFilterAndTransform; } continue; } Dictionary dictionary = _specsBySourceNameAndActivityName ?? (_specsBySourceNameAndActivityName = new Dictionary(SpecLookupKeyComparer.Instance)); HashSet hashSet = _listenToActivitySourceNames ?? (_listenToActivitySourceNames = new HashSet(StringComparer.OrdinalIgnoreCase)); SpecLookupKey key = new SpecLookupKey(dsesFilterAndTransform.SourceName, dsesFilterAndTransform.ActivityName); if (dictionary.ContainsKey(key)) { LogIgnoredSpecRule(dsesFilterAndTransform.SourceName, dsesFilterAndTransform.ActivityName); continue; } dictionary[key] = dsesFilterAndTransform; hashSet.Add(key.activitySourceName); if (key.activityName != null) { _hasActivityNameSpecDefined = true; } } void LogIgnoredSpecRule(string activitySourceName, string activityName) { if (_eventSource.IsEnabled(EventLevel.Warning, (EventKeywords)1L)) { if (activityName == null) { _eventSource.Message("DiagnosticSource: Ignoring filterAndPayloadSpec rule for '[AS]" + activitySourceName + "' because a previous rule was defined"); } else { _eventSource.Message("DiagnosticSource: Ignoring filterAndPayloadSpec rule for '[AS]" + activitySourceName + "+" + activityName + "' because a previous rule was defined"); } } } } private void CreateActivityListener() { _activityListener = new ActivityListener(); _activityListener.SampleUsingParentId = OnSampleUsingParentId; _activityListener.Sample = OnSample; _activityListener.ShouldListenTo = (ActivitySource activitySource) => _wildcardSpec != null || (_listenToActivitySourceNames != null && _listenToActivitySourceNames.Contains(activitySource.Name)); _activityListener.ActivityStarted = OnActivityStarted; _activityListener.ActivityStopped = OnActivityStopped; ActivitySource.AddActivityListener(_activityListener); } private bool TryFindSpecForActivity(string activitySourceName, string activityName, [NotNullWhen(true)] out DsesFilterAndTransform spec) { if (_specsBySourceNameAndActivityName != null) { if (_hasActivityNameSpecDefined && _specsBySourceNameAndActivityName.TryGetValue(new SpecLookupKey(activitySourceName, activityName), out spec)) { return true; } if (_specsBySourceNameAndActivityName.TryGetValue(new SpecLookupKey(activitySourceName, null), out spec)) { return true; } } return (spec = _wildcardSpec) != null; } [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(Activity))] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(ActivityContext))] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(ActivityEvent))] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(ActivityLink))] [DynamicDependency("Ticks", typeof(DateTime))] [DynamicDependency("Ticks", typeof(TimeSpan))] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Activity's properties are being preserved with the DynamicDependencies on OnActivityStarted.")] private void OnActivityStarted(Activity activity) { if (TryFindSpecForActivity(activity.Source.Name, activity.OperationName, out var spec) && (spec.Events & DsesActivityEvents.ActivityStart) != DsesActivityEvents.None) { _eventSource.ActivityStart(activity.Source.Name, activity.OperationName, spec.Morph(activity)); } } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Activity's properties are being preserved with the DynamicDependencies on OnActivityStarted.")] private void OnActivityStopped(Activity activity) { if (TryFindSpecForActivity(activity.Source.Name, activity.OperationName, out var spec) && (spec.Events & DsesActivityEvents.ActivityStop) != DsesActivityEvents.None) { _eventSource.ActivityStop(activity.Source.Name, activity.OperationName, spec.Morph(activity)); } } private ActivitySamplingResult OnSampleUsingParentId(ref ActivityCreationOptions options) { ActivityCreationOptions options2 = default(ActivityCreationOptions); return OnSample(options.Source.Name, options.Name, hasActivityContext: false, ref options2); } private ActivitySamplingResult OnSample(ref ActivityCreationOptions options) { return OnSample(options.Source.Name, options.Name, hasActivityContext: true, ref options); } private ActivitySamplingResult OnSample(string activitySourceName, string activityName, bool hasActivityContext, ref ActivityCreationOptions options) { if (!TryFindSpecForActivity(activitySourceName, activityName, out var spec)) { return ActivitySamplingResult.None; } return spec.SampleFunc(hasActivityContext, ref options); } } internal delegate ActivitySamplingResult DsesSampleActivityFunc(bool hasActivityContext, ref ActivityCreationOptions options); internal static class DsesSamplerBuilder { public static DsesSampleActivityFunc CreateParentRatioSampler(double ratio) { long idUpperBound = ((ratio <= 0.0) ? long.MinValue : ((ratio >= 1.0) ? long.MaxValue : ((long)(ratio * 9.223372036854776E+18)))); return delegate(bool hasActivityContext, ref ActivityCreationOptions options) { if (hasActivityContext && options.TraceId != default(ActivityTraceId)) { ActivityContext parentContext = options.Parent; ActivitySamplingResult activitySamplingResult = ParentRatioSampler(idUpperBound, in parentContext, options.TraceId); if (activitySamplingResult != ActivitySamplingResult.None || (!(parentContext == default(ActivityContext)) && !parentContext.IsRemote)) { return activitySamplingResult; } return ActivitySamplingResult.PropagationData; } return ActivitySamplingResult.None; }; } public static ActivitySamplingResult ParentRatioSampler(long idUpperBound, in ActivityContext parentContext, ActivityTraceId traceId) { if (parentContext.TraceId != default(ActivityTraceId)) { if (!parentContext.TraceFlags.HasFlag(ActivityTraceFlags.Recorded)) { return ActivitySamplingResult.None; } return ActivitySamplingResult.AllDataAndRecorded; } Span span = stackalloc byte[16]; traceId.CopyTo(span); if (Math.Abs(GetLowerLong(span)) >= idUpperBound) { return ActivitySamplingResult.None; } return ActivitySamplingResult.AllDataAndRecorded; static long GetLowerLong(ReadOnlySpan bytes) { long num = 0L; for (int i = 0; i < 8; i++) { num <<= 8; num |= bytes[i] & 0xFF; } return num; } } public static DsesSampleActivityFunc CreateParentRateLimitingSampler(int maximumRatePerSecond) { RateLimiter rateLimiter = new RateLimiter(maximumRatePerSecond); return delegate(bool hasActivityContext, ref ActivityCreationOptions options) { if (hasActivityContext && options.TraceId != default(ActivityTraceId)) { ActivityContext parent = options.Parent; if (!(parent == default(ActivityContext)) && !parent.IsRemote) { if (!parent.TraceFlags.HasFlag(ActivityTraceFlags.Recorded)) { return ActivitySamplingResult.None; } return ActivitySamplingResult.AllDataAndRecorded; } if (!rateLimiter.TryAcquire()) { return ActivitySamplingResult.None; } return ActivitySamplingResult.AllDataAndRecorded; } return ActivitySamplingResult.None; }; } } public abstract class DistributedContextPropagator { public delegate void PropagatorGetterCallback(object? carrier, string fieldName, out string? fieldValue, out IEnumerable? fieldValues); public delegate void PropagatorSetterCallback(object? carrier, string fieldName, string fieldValue); private static DistributedContextPropagator s_current = CreateDefaultPropagator(); internal const string TraceParent = "traceparent"; internal const string RequestId = "Request-Id"; internal const string TraceState = "tracestate"; internal const string Baggage = "baggage"; internal const string CorrelationContext = "Correlation-Context"; internal const char Space = ' '; internal const char Tab = '\t'; internal const char Comma = ','; internal const char Semicolon = ';'; internal const string CommaWithSpace = ", "; internal static readonly char[] s_trimmingSpaceCharacters = new char[2] { ' ', '\t' }; public abstract IReadOnlyCollection Fields { get; } public static DistributedContextPropagator Current { get { return s_current; } set { s_current = value ?? throw new ArgumentNullException("value"); } } public abstract void Inject(Activity? activity, object? carrier, PropagatorSetterCallback? setter); public abstract void ExtractTraceIdAndState(object? carrier, PropagatorGetterCallback? getter, out string? traceId, out string? traceState); public abstract IEnumerable>? ExtractBaggage(object? carrier, PropagatorGetterCallback? getter); public static DistributedContextPropagator CreateDefaultPropagator() { return W3CPropagator.Instance; } public static DistributedContextPropagator CreatePassThroughPropagator() { return PassThroughPropagator.Instance; } public static DistributedContextPropagator CreateW3CPropagator() { return W3CPropagator.Instance; } public static DistributedContextPropagator CreatePreW3CPropagator() { return LegacyPropagator.Instance; } public static DistributedContextPropagator CreateNoOutputPropagator() { return NoOutputPropagator.Instance; } internal static void InjectBaggage(object carrier, IEnumerable> baggage, PropagatorSetterCallback setter) { using IEnumerator> enumerator = baggage.GetEnumerator(); if (enumerator.MoveNext()) { StringBuilder stringBuilder = new StringBuilder(); do { KeyValuePair current = enumerator.Current; stringBuilder.Append(WebUtility.UrlEncode(current.Key)).Append('=').Append(WebUtility.UrlEncode(current.Value)) .Append(", "); } while (enumerator.MoveNext()); setter(carrier, "Correlation-Context", stringBuilder.ToString(0, stringBuilder.Length - 2)); } } } internal sealed class DsesFilterAndTransform : IDisposable { private sealed class ParsedFilterAndPayloadSpecs : IDisposable { private DsesFilterAndTransform _specList; private DsesActivitySourceListener _activitySourceListener; public ParsedFilterAndPayloadSpecs(DsesFilterAndTransform specList, DsesActivitySourceListener activitySourceListener) { _specList = specList; _activitySourceListener = activitySourceListener; } public void Dispose() { _activitySourceListener?.Dispose(); _activitySourceListener = null; DsesFilterAndTransform dsesFilterAndTransform = _specList; _specList = null; while (dsesFilterAndTransform != null) { dsesFilterAndTransform.Dispose(); dsesFilterAndTransform = dsesFilterAndTransform.Next; } } } private sealed class ImplicitTransformEntry { public Type Type; public TransformSpec Transforms; } private sealed class TransformSpec { private sealed class PropertySpec { private class PropertyFetch { private sealed class RefTypedFetchProperty : PropertyFetch { private readonly Func _propertyFetch; public RefTypedFetchProperty(Type type, PropertyInfo property) : base(type) { _propertyFetch = (Func)property.GetMethod.CreateDelegate(typeof(Func)); } public override object Fetch(object obj) { return _propertyFetch((TObject)obj); } } private delegate TProperty StructFunc(ref TStruct thisArg); private sealed class ValueTypedFetchProperty : PropertyFetch { private readonly StructFunc _propertyFetch; public ValueTypedFetchProperty(Type type, PropertyInfo property) : base(type) { _propertyFetch = (StructFunc)property.GetMethod.CreateDelegate(typeof(StructFunc)); } public override object Fetch(object obj) { TStruct thisArg = (TStruct)obj; return _propertyFetch(ref thisArg); } } private sealed class CurrentActivityPropertyFetch : PropertyFetch { public CurrentActivityPropertyFetch() : base(null) { } public override object Fetch(object obj) { return Activity.Current; } } private sealed class EnumeratePropertyFetch : PropertyFetch { public EnumeratePropertyFetch(Type type) : base(type) { } public override object Fetch(object obj) { return string.Join(",", (IEnumerable)obj); } } internal Type Type { get; } public PropertyFetch(Type type) { Type = type; } [RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public static PropertyFetch FetcherForProperty(DiagnosticSourceEventSource eventSource, Type type, string propertyName) { if (propertyName == null) { return new PropertyFetch(type); } if (propertyName == "*Activity") { return new CurrentActivityPropertyFetch(); } TypeInfo typeInfo = type.GetTypeInfo(); if (propertyName == "*Enumerate") { Type[] interfaces = typeInfo.GetInterfaces(); for (int i = 0; i < interfaces.Length; i++) { TypeInfo typeInfo2 = interfaces[i].GetTypeInfo(); if (typeInfo2.IsGenericType && !(typeInfo2.GetGenericTypeDefinition() != typeof(IEnumerable<>))) { return CreateEnumeratePropertyFetch(type, typeInfo2); } } eventSource.Message($"*Enumerate applied to non-enumerable type {type}"); return new PropertyFetch(type); } PropertyInfo propertyInfo = typeInfo.GetDeclaredProperty(propertyName); if (propertyInfo == null) { PropertyInfo[] properties = typeInfo.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo2 in properties) { if (propertyInfo2.Name == propertyName) { propertyInfo = propertyInfo2; break; } } } if (propertyInfo == null) { eventSource.Message($"Property {propertyName} not found on {type}. Ensure the name is spelled correctly. If you published the application with PublishTrimmed=true, ensure the property was not trimmed away."); return new PropertyFetch(type); } MethodInfo? getMethod = propertyInfo.GetMethod; if ((object)getMethod == null || !getMethod.IsStatic) { MethodInfo? setMethod = propertyInfo.SetMethod; if ((object)setMethod == null || !setMethod.IsStatic) { return CreatePropertyFetch(typeInfo, propertyInfo); } } eventSource.Message("Property " + propertyName + " is static."); return new PropertyFetch(type); } [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", Justification = "MakeGenericType is only called when IsDynamicCodeSupported is true or only with ref types.")] private static PropertyFetch CreateEnumeratePropertyFetch(Type type, TypeInfo enumerableOfTType) { Type type2 = enumerableOfTType.GetGenericArguments()[0]; return (PropertyFetch)Activator.CreateInstance(typeof(EnumeratePropertyFetch<>).GetTypeInfo().MakeGenericType(type2), type); } [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", Justification = "MakeGenericType is only called when IsDynamicCodeSupported is true or only with ref types.")] private static PropertyFetch CreatePropertyFetch(Type type, PropertyInfo propertyInfo) { return (PropertyFetch)Activator.CreateInstance((type.IsValueType ? typeof(ValueTypedFetchProperty<, >) : typeof(RefTypedFetchProperty<, >)).GetTypeInfo().MakeGenericType(propertyInfo.DeclaringType, propertyInfo.PropertyType), type, propertyInfo); } public virtual object Fetch(object obj) { return null; } } private const string CurrentActivityPropertyName = "*Activity"; private const string EnumeratePropertyName = "*Enumerate"; private readonly DiagnosticSourceEventSource _eventSource; private readonly string _propertyName; private volatile PropertyFetch _fetchForExpectedType; public bool IsStatic { get; } public PropertySpec Next { get; } public PropertySpec(DiagnosticSourceEventSource eventSource, string propertyName, PropertySpec next) { _eventSource = eventSource; _propertyName = propertyName; Next = next; if (_propertyName == "*Activity") { IsStatic = true; } } [RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public object Fetch(object obj) { PropertyFetch propertyFetch = _fetchForExpectedType; Type type = obj?.GetType(); if (propertyFetch == null || propertyFetch.Type != type) { propertyFetch = (_fetchForExpectedType = PropertyFetch.FetcherForProperty(_eventSource, type, _propertyName)); } object result = null; try { result = propertyFetch.Fetch(obj); } catch (Exception arg) { _eventSource.Message($"Property {type}.{_propertyName} threw the exception {arg}"); } return result; } } public TransformSpec Next; private readonly string _outputName; private readonly PropertySpec _fetches; public TransformSpec(DiagnosticSourceEventSource eventSource, string transformSpec, int startIdx, int endIdx, TransformSpec next = null) { Next = next; int num = transformSpec.IndexOf('=', startIdx, endIdx - startIdx); if (0 <= num) { _outputName = transformSpec.Substring(startIdx, num - startIdx); startIdx = num + 1; } while (startIdx < endIdx) { int num2 = transformSpec.LastIndexOf('.', endIdx - 1, endIdx - startIdx); int num3 = startIdx; if (0 <= num2) { num3 = num2 + 1; } string text = transformSpec.Substring(num3, endIdx - num3); _fetches = new PropertySpec(eventSource, text, _fetches); if (_outputName == null) { _outputName = text; } endIdx = num2; } } [RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public KeyValuePair Morph(object obj) { for (PropertySpec propertySpec = _fetches; propertySpec != null; propertySpec = propertySpec.Next) { if (obj != null || propertySpec.IsStatic) { obj = propertySpec.Fetch(obj); } } return new KeyValuePair(_outputName, obj?.ToString()); } } private sealed class CallbackObserver : IObserver { private readonly Action _callback; public CallbackObserver(Action callback) { _callback = callback; } public void OnCompleted() { } public void OnError(Exception error) { } public void OnNext(T value) { _callback(value); } } private sealed class Subscriptions { public IDisposable Subscription; public Subscriptions Next; public Subscriptions(IDisposable subscription, Subscriptions next) { Subscription = subscription; Next = next; } } private const string c_ActivitySourcePrefix = "[AS]"; private const string c_ParentRatioSamplerPrefix = "ParentRatioSampler("; private const string c_ParentRateLimitingSamplerPrefix = "ParentRateLimitingSampler("; private readonly DiagnosticSourceEventSource _eventSource; private IDisposable _diagnosticsListenersSubscription; private Subscriptions _liveSubscriptions; private readonly bool _noImplicitTransforms; private ImplicitTransformEntry _firstImplicitTransformsEntry; private ConcurrentDictionary _implicitTransformsTable; private readonly TransformSpec _explicitTransforms; public DsesFilterAndTransform Next { get; } internal string SourceName { get; } internal string ActivityName { get; } internal DsesActivityEvents Events { get; } internal DsesSampleActivityFunc SampleFunc { get; } public static IDisposable ParseFilterAndPayloadSpecs(DiagnosticSourceEventSource eventSource, string filterAndPayloadSpecs) { if (filterAndPayloadSpecs == null) { filterAndPayloadSpecs = ""; } DsesFilterAndTransform dsesFilterAndTransform = null; DsesFilterAndTransform dsesFilterAndTransform2 = null; int num = filterAndPayloadSpecs.Length; while (true) { if (0 < num && char.IsWhiteSpace(filterAndPayloadSpecs[num - 1])) { num--; continue; } int num2 = filterAndPayloadSpecs.LastIndexOf('\n', num - 1, num); int i = 0; if (0 <= num2) { i = num2 + 1; } for (; i < num && char.IsWhiteSpace(filterAndPayloadSpecs[i]); i++) { } if (IsActivitySourceEntry(filterAndPayloadSpecs, i, num)) { dsesFilterAndTransform2 = CreateActivitySourceTransform(eventSource, filterAndPayloadSpecs, i, num, dsesFilterAndTransform2); } else { dsesFilterAndTransform = CreateTransform(eventSource, filterAndPayloadSpecs, i, num, dsesFilterAndTransform); } num = num2; if (num < 0) { break; } } DsesActivitySourceListener activitySourceListener = ((dsesFilterAndTransform2 != null) ? DsesActivitySourceListener.Create(eventSource, dsesFilterAndTransform2) : null); return new ParsedFilterAndPayloadSpecs(dsesFilterAndTransform, activitySourceListener); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsActivitySourceEntry(string filterAndPayloadSpec, int startIdx, int endIdx) { return filterAndPayloadSpec.AsSpan(startIdx, endIdx - startIdx).StartsWith("[AS]".AsSpan(), StringComparison.Ordinal); } private static DsesFilterAndTransform CreateTransform(DiagnosticSourceEventSource eventSource, string filterAndPayloadSpec, int startIdx, int endIdx, DsesFilterAndTransform next) { string text = null; string text2 = null; string activityName = null; bool noImplicitTransforms = false; TransformSpec transformSpec = null; int num = startIdx; int num2 = endIdx; int num3 = filterAndPayloadSpec.IndexOf(':', startIdx, endIdx - startIdx); if (0 <= num3) { num2 = num3; num = num3 + 1; } int num4 = filterAndPayloadSpec.IndexOf('/', startIdx, num2 - startIdx); if (0 <= num4) { text = filterAndPayloadSpec.Substring(startIdx, num4 - startIdx); int num5 = filterAndPayloadSpec.IndexOf('@', num4 + 1, num2 - num4 - 1); if (0 <= num5) { activityName = filterAndPayloadSpec.Substring(num5 + 1, num2 - num5 - 1); text2 = filterAndPayloadSpec.Substring(num4 + 1, num5 - num4 - 1); } else { text2 = filterAndPayloadSpec.Substring(num4 + 1, num2 - num4 - 1); } } else if (startIdx < num2) { text = filterAndPayloadSpec.Substring(startIdx, num2 - startIdx); } eventSource.Message("DiagnosticSource: Enabling '" + (text ?? "*") + "/" + (text2 ?? "*") + "'"); if (num < endIdx && filterAndPayloadSpec[num] == '-') { eventSource.Message("DiagnosticSource: suppressing implicit transforms."); noImplicitTransforms = true; num++; } if (num < endIdx) { while (true) { int num6 = num; int num7 = filterAndPayloadSpec.LastIndexOf(';', endIdx - 1, endIdx - num); if (0 <= num7) { num6 = num7 + 1; } if (num6 < endIdx) { if (eventSource.IsEnabled(EventLevel.Informational, (EventKeywords)1L)) { eventSource.Message("DiagnosticSource: Parsing Explicit Transform '" + filterAndPayloadSpec.Substring(num6, endIdx - num6) + "'"); } transformSpec = new TransformSpec(eventSource, filterAndPayloadSpec, num6, endIdx, transformSpec); } if (num == num6) { break; } endIdx = num7; } } DsesFilterAndTransform dsesFilterAndTransform = new DsesFilterAndTransform(eventSource, next, noImplicitTransforms, transformSpec, null, null, DsesActivityEvents.None, null); dsesFilterAndTransform.SetupDiagnosticListenerSubscription(text, text2, activityName); return dsesFilterAndTransform; } private static DsesFilterAndTransform CreateActivitySourceTransform(DiagnosticSourceEventSource eventSource, string filterAndPayloadSpec, int startIdx, int endIdx, DsesFilterAndTransform next) { bool noImplicitTransforms = false; TransformSpec transformSpec = null; DsesActivityEvents activityEvents = DsesActivityEvents.All; DsesSampleActivityFunc sampleFunc = delegate { return ActivitySamplingResult.AllDataAndRecorded; }; int num = filterAndPayloadSpec.IndexOf(':', startIdx + "[AS]".Length, endIdx - startIdx - "[AS]".Length); ReadOnlySpan readOnlySpan = filterAndPayloadSpec.AsSpan(startIdx + "[AS]".Length, ((num >= 0) ? num : endIdx) - startIdx - "[AS]".Length).Trim(); int num2 = readOnlySpan.IndexOf('/'); ReadOnlySpan span; if (num2 >= 0) { span = readOnlySpan.Slice(0, num2).Trim(); ReadOnlySpan readOnlySpan2 = readOnlySpan.Slice(num2 + 1).Trim(); int num3 = readOnlySpan2.IndexOf('-'); ReadOnlySpan span2; if (num3 >= 0) { span2 = readOnlySpan2.Slice(0, num3).Trim(); readOnlySpan2 = readOnlySpan2.Slice(num3 + 1).Trim(); if (readOnlySpan2.Length > 0) { if (MemoryExtensions.Equals(readOnlySpan2, "Propagate".AsSpan(), StringComparison.OrdinalIgnoreCase)) { sampleFunc = delegate { return ActivitySamplingResult.PropagationData; }; } else if (MemoryExtensions.Equals(readOnlySpan2, "Record".AsSpan(), StringComparison.OrdinalIgnoreCase)) { sampleFunc = delegate { return ActivitySamplingResult.AllData; }; } else if (readOnlySpan2.StartsWith("ParentRatioSampler(".AsSpan(), StringComparison.OrdinalIgnoreCase)) { int num4 = readOnlySpan2.IndexOf(')'); if (num4 < 0 || !double.TryParse(readOnlySpan2.Slice("ParentRatioSampler(".Length, num4 - "ParentRatioSampler(".Length).ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { if (eventSource.IsEnabled(EventLevel.Warning, (EventKeywords)1L)) { eventSource.Message("DiagnosticSource: Ignoring filterAndPayloadSpec '[AS]" + readOnlySpan.ToString() + "' because sampling ratio was invalid"); } return next; } sampleFunc = DsesSamplerBuilder.CreateParentRatioSampler(result); } else { if (!readOnlySpan2.StartsWith("ParentRateLimitingSampler(".AsSpan(), StringComparison.OrdinalIgnoreCase)) { if (eventSource.IsEnabled(EventLevel.Warning, (EventKeywords)1L)) { eventSource.Message("DiagnosticSource: Ignoring filterAndPayloadSpec '[AS]" + readOnlySpan.ToString() + "' because sampling method was invalid"); } return next; } int num5 = readOnlySpan2.IndexOf(')'); if (num5 < 0 || !int.TryParse(readOnlySpan2.Slice("ParentRateLimitingSampler(".Length, num5 - "ParentRateLimitingSampler(".Length).ToString(), NumberStyles.None, CultureInfo.InvariantCulture, out var result2) || result2 <= 0) { if (eventSource.IsEnabled(EventLevel.Warning, (EventKeywords)1L)) { eventSource.Message("DiagnosticSource: Ignoring filterAndPayloadSpec '[AS]" + readOnlySpan.ToString() + "' because rate limiting sampling was invalid"); } return next; } sampleFunc = DsesSamplerBuilder.CreateParentRateLimitingSampler(result2); } } } else { span2 = readOnlySpan2; } if (span2.Length > 0) { if (MemoryExtensions.Equals(span2, "Start".AsSpan(), StringComparison.OrdinalIgnoreCase)) { activityEvents = DsesActivityEvents.ActivityStart; } else { if (!MemoryExtensions.Equals(span2, "Stop".AsSpan(), StringComparison.OrdinalIgnoreCase)) { if (eventSource.IsEnabled(EventLevel.Warning, (EventKeywords)1L)) { eventSource.Message("DiagnosticSource: Ignoring filterAndPayloadSpec '[AS]" + readOnlySpan.ToString() + "' because event name was invalid"); } return next; } activityEvents = DsesActivityEvents.ActivityStop; } } } else { span = readOnlySpan; } string text = null; int num6 = span.IndexOf('+'); if (num6 >= 0) { text = span.Slice(num6 + 1).Trim().ToString(); span = span.Slice(0, num6).Trim(); if (text.Length > 0 && span.Length == 1 && span[0] == '*') { if (eventSource.IsEnabled(EventLevel.Warning, (EventKeywords)1L)) { eventSource.Message("DiagnosticSource: Ignoring filterAndPayloadSpec '[AS]" + readOnlySpan.ToString() + "' because activity name cannot be specified for wildcard activity sources"); } return next; } } if (num >= 0) { int num7 = num + 1; if (num7 < endIdx && filterAndPayloadSpec[num7] == '-') { eventSource.Message("DiagnosticSource: suppressing implicit transforms."); noImplicitTransforms = true; num7++; } if (num7 < endIdx) { while (true) { int num8 = num7; int num9 = filterAndPayloadSpec.LastIndexOf(';', endIdx - 1, endIdx - num7); if (0 <= num9) { num8 = num9 + 1; } if (num8 < endIdx) { if (eventSource.IsEnabled(EventLevel.Informational, (EventKeywords)1L)) { eventSource.Message("DiagnosticSource: Parsing Explicit Transform '" + filterAndPayloadSpec.Substring(num8, endIdx - num8) + "'"); } transformSpec = new TransformSpec(eventSource, filterAndPayloadSpec, num8, endIdx, transformSpec); } if (num7 == num8) { break; } endIdx = num9; } } } return new DsesFilterAndTransform(eventSource, next, noImplicitTransforms, transformSpec, span.ToString(), text, activityEvents, sampleFunc); } private DsesFilterAndTransform(DiagnosticSourceEventSource eventSource, DsesFilterAndTransform next, bool noImplicitTransforms, TransformSpec explicitTransforms, string sourceName, string activityName, DsesActivityEvents activityEvents, DsesSampleActivityFunc sampleFunc) { _eventSource = eventSource; _noImplicitTransforms = noImplicitTransforms; _explicitTransforms = explicitTransforms; Next = next; SourceName = sourceName; ActivityName = activityName; Events = activityEvents; SampleFunc = sampleFunc; } public void Dispose() { if (_diagnosticsListenersSubscription != null) { _diagnosticsListenersSubscription.Dispose(); _diagnosticsListenersSubscription = null; } if (_liveSubscriptions != null) { Subscriptions subscriptions = _liveSubscriptions; _liveSubscriptions = null; while (subscriptions != null) { subscriptions.Subscription.Dispose(); subscriptions = subscriptions.Next; } } } [RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public List> Morph(object args) { List> list = new List>(); if (args != null) { if (!_noImplicitTransforms) { Type type = args.GetType(); ImplicitTransformEntry firstImplicitTransformsEntry = _firstImplicitTransformsEntry; TransformSpec transformSpec; if (firstImplicitTransformsEntry != null && firstImplicitTransformsEntry.Type == type) { transformSpec = firstImplicitTransformsEntry.Transforms; } else if (firstImplicitTransformsEntry == null) { transformSpec = MakeImplicitTransforms(_eventSource, type); Interlocked.CompareExchange(ref _firstImplicitTransformsEntry, new ImplicitTransformEntry { Type = type, Transforms = transformSpec }, null); } else { if (_implicitTransformsTable == null) { Interlocked.CompareExchange(ref _implicitTransformsTable, new ConcurrentDictionary(1, 8), null); } transformSpec = _implicitTransformsTable.GetOrAdd(type, (Type t) => MakeImplicitTransforms(_eventSource, t)); } if (transformSpec != null) { for (TransformSpec transformSpec2 = transformSpec; transformSpec2 != null; transformSpec2 = transformSpec2.Next) { list.Add(transformSpec2.Morph(args)); } } } if (_explicitTransforms != null) { for (TransformSpec transformSpec3 = _explicitTransforms; transformSpec3 != null; transformSpec3 = transformSpec3.Next) { KeyValuePair item = transformSpec3.Morph(args); if (item.Value != null) { list.Add(item); } } } } return list; } private void SetupDiagnosticListenerSubscription(string listenerNameFilter, string eventNameFilter, string activityName) { Action>> writeEvent = null; if (activityName != null && activityName.Contains("Activity")) { writeEvent = activityName switch { "Activity1Start" => _eventSource.Activity1Start, "Activity1Stop" => _eventSource.Activity1Stop, "Activity2Start" => _eventSource.Activity2Start, "Activity2Stop" => _eventSource.Activity2Stop, "RecursiveActivity1Start" => _eventSource.RecursiveActivity1Start, "RecursiveActivity1Stop" => _eventSource.RecursiveActivity1Stop, _ => null, }; if (writeEvent == null) { _eventSource.Message("DiagnosticSource: Could not find Event to log Activity " + activityName); } } if (writeEvent == null) { writeEvent = _eventSource.Event; } _diagnosticsListenersSubscription = DiagnosticListener.AllListeners.Subscribe(new CallbackObserver(delegate(DiagnosticListener newListener) { if (listenerNameFilter == null || listenerNameFilter == newListener.Name) { _eventSource.NewDiagnosticListener(newListener.Name); Predicate isEnabled = null; if (eventNameFilter != null) { isEnabled = (string eventName) => eventNameFilter == eventName; } IDisposable subscription = newListener.Subscribe(new CallbackObserver>(OnEventWritten), isEnabled); _liveSubscriptions = new Subscriptions(subscription, _liveSubscriptions); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "DiagnosticSource.Write is marked with RequiresUnreferencedCode.")] void OnEventWritten(KeyValuePair evnt) { if (eventNameFilter == null || !(eventNameFilter != evnt.Key)) { List> arg = Morph(evnt.Value); string key = evnt.Key; writeEvent(newListener.Name, key, arg); } } })); } [RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] private static TransformSpec MakeImplicitTransforms(DiagnosticSourceEventSource eventSource, Type type) { TransformSpec transformSpec = null; PropertyInfo[] properties = type.GetTypeInfo().GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.GetMethod == null) && propertyInfo.GetMethod.GetParameters().Length == 0) { transformSpec = new TransformSpec(eventSource, propertyInfo.Name, 0, propertyInfo.Name.Length, transformSpec); } } return Reverse(transformSpec); } private static TransformSpec Reverse(TransformSpec list) { TransformSpec transformSpec = null; while (list != null) { TransformSpec next = list.Next; list.Next = transformSpec; transformSpec = list; list = next; } return transformSpec; } } internal static class Helpers { internal static string FormatTags(IEnumerable> tags) { if (tags == null) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); bool flag = true; foreach (KeyValuePair tag in tags) { if (flag) { flag = false; } else { stringBuilder.Append(','); } stringBuilder.Append(tag.Key).Append('=').Append(tag.Value); } return stringBuilder.ToString(); } internal static string FormatTags(KeyValuePair[] labels) { if (labels == null || labels.Length == 0) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < labels.Length; i++) { stringBuilder.Append(labels[i].Key).Append('=').Append(labels[i].Value); if (i != labels.Length - 1) { stringBuilder.Append(','); } } return stringBuilder.ToString(); } internal static string FormatObjectHash(object obj) { if (obj != null) { return RuntimeHelpers.GetHashCode(obj).ToString(CultureInfo.InvariantCulture); } return string.Empty; } } internal sealed class LegacyPropagator : DistributedContextPropagator { internal static DistributedContextPropagator Instance { get; } = new LegacyPropagator(); public override IReadOnlyCollection Fields { get; } = new ReadOnlyCollection(new string[5] { "traceparent", "Request-Id", "tracestate", "baggage", "Correlation-Context" }); public override void Inject(Activity activity, object carrier, PropagatorSetterCallback setter) { if (activity == null || setter == null) { return; } string id = activity.Id; if (id == null) { return; } if (activity.IdFormat == ActivityIdFormat.W3C) { setter(carrier, "traceparent", id); if (!string.IsNullOrEmpty(activity.TraceStateString)) { setter(carrier, "tracestate", activity.TraceStateString); } } else { setter(carrier, "Request-Id", id); } DistributedContextPropagator.InjectBaggage(carrier, activity.Baggage, setter); } public override void ExtractTraceIdAndState(object carrier, PropagatorGetterCallback getter, out string traceId, out string traceState) { if (getter == null) { traceId = null; traceState = null; return; } getter(carrier, "traceparent", out traceId, out var fieldValues); if (traceId == null) { getter(carrier, "Request-Id", out traceId, out fieldValues); } getter(carrier, "tracestate", out traceState, out fieldValues); } public override IEnumerable> ExtractBaggage(object carrier, PropagatorGetterCallback getter) { if (getter == null) { return null; } getter(carrier, "baggage", out var fieldValue, out var fieldValues); IEnumerable> baggage = null; if (fieldValue == null || !TryExtractBaggage(fieldValue, out baggage)) { getter(carrier, "Correlation-Context", out fieldValue, out fieldValues); if (fieldValue != null) { TryExtractBaggage(fieldValue, out baggage); } } return baggage; } internal static bool TryExtractBaggage(string baggageString, out IEnumerable> baggage) { baggage = null; List> list = null; if (string.IsNullOrEmpty(baggageString)) { return true; } int i = 0; while (true) { if (i < baggageString.Length && (baggageString[i] == ' ' || baggageString[i] == '\t')) { i++; continue; } if (i >= baggageString.Length) { break; } int num = i; for (; i < baggageString.Length && baggageString[i] != ' ' && baggageString[i] != '\t' && baggageString[i] != '='; i++) { } if (i >= baggageString.Length) { break; } int num2 = i; if (baggageString[i] != '=') { for (; i < baggageString.Length && (baggageString[i] == ' ' || baggageString[i] == '\t'); i++) { } if (i >= baggageString.Length || baggageString[i] != '=') { break; } } for (i++; i < baggageString.Length && (baggageString[i] == ' ' || baggageString[i] == '\t'); i++) { } if (i >= baggageString.Length) { break; } int num3 = i; for (; i < baggageString.Length && baggageString[i] != ' ' && baggageString[i] != '\t' && baggageString[i] != ',' && baggageString[i] != ';'; i++) { } if (num < num2 && num3 < i) { if (list == null) { list = new List>(); } list.Insert(0, new KeyValuePair(WebUtility.UrlDecode(baggageString.Substring(num, num2 - num)).Trim(DistributedContextPropagator.s_trimmingSpaceCharacters), WebUtility.UrlDecode(baggageString.Substring(num3, i - num3)).Trim(DistributedContextPropagator.s_trimmingSpaceCharacters))); } for (; i < baggageString.Length && baggageString[i] != ','; i++) { } i++; if (i >= baggageString.Length) { break; } } baggage = list; return list != null; } } internal sealed class NoOutputPropagator : DistributedContextPropagator { internal static DistributedContextPropagator Instance { get; } = new NoOutputPropagator(); public override IReadOnlyCollection Fields { get; } = LegacyPropagator.Instance.Fields; public override void Inject(Activity activity, object carrier, PropagatorSetterCallback setter) { } public override void ExtractTraceIdAndState(object carrier, PropagatorGetterCallback getter, out string traceId, out string traceState) { LegacyPropagator.Instance.ExtractTraceIdAndState(carrier, getter, out traceId, out traceState); } public override IEnumerable> ExtractBaggage(object carrier, PropagatorGetterCallback getter) { return LegacyPropagator.Instance.ExtractBaggage(carrier, getter); } } internal sealed class PassThroughPropagator : DistributedContextPropagator { internal static DistributedContextPropagator Instance { get; } = new PassThroughPropagator(); public override IReadOnlyCollection Fields { get; } = LegacyPropagator.Instance.Fields; public override void Inject(Activity activity, object carrier, PropagatorSetterCallback setter) { if (setter == null) { return; } GetRootId(out var parentId, out var traceState, out var isW3c, out var baggage); if (parentId != null) { setter(carrier, isW3c ? "traceparent" : "Request-Id", parentId); if (!string.IsNullOrEmpty(traceState)) { setter(carrier, "tracestate", traceState); } if (baggage != null) { DistributedContextPropagator.InjectBaggage(carrier, baggage, setter); } } } public override void ExtractTraceIdAndState(object carrier, PropagatorGetterCallback getter, out string traceId, out string traceState) { LegacyPropagator.Instance.ExtractTraceIdAndState(carrier, getter, out traceId, out traceState); } public override IEnumerable> ExtractBaggage(object carrier, PropagatorGetterCallback getter) { return LegacyPropagator.Instance.ExtractBaggage(carrier, getter); } private static void GetRootId(out string parentId, out string traceState, out bool isW3c, out IEnumerable> baggage) { Activity activity = Activity.Current; while (true) { Activity activity2 = activity?.Parent; if (activity2 == null) { break; } activity = activity2; } traceState = activity?.TraceStateString; parentId = activity?.ParentId ?? activity?.Id; isW3c = parentId != null && Activity.TryConvertIdToContext(parentId, traceState, isRemote: false, out var _); baggage = activity?.Baggage; } } internal sealed class RateLimiter { private readonly int _maxOperationsPerSecond; private readonly Stopwatch _stopwatch; private readonly long _ticksPerSecond; private int _currentOperationCount; private long _intervalStartTicks; internal RateLimiter(int maxOperationsPerSecond) { _maxOperationsPerSecond = maxOperationsPerSecond; _stopwatch = new Stopwatch(); _stopwatch.Start(); _intervalStartTicks = _stopwatch.ElapsedTicks; _currentOperationCount = 0; _ticksPerSecond = Stopwatch.Frequency; } internal bool TryAcquire() { while (true) { long elapsedTicks = _stopwatch.ElapsedTicks; long num = Interlocked.Read(in _intervalStartTicks); int num2 = Volatile.Read(in _currentOperationCount); if (elapsedTicks - num < _ticksPerSecond) { break; } if (Interlocked.CompareExchange(ref _currentOperationCount, 1, num2) == num2) { Interlocked.CompareExchange(ref _intervalStartTicks, elapsedTicks, num); return true; } } return Interlocked.Increment(ref _currentOperationCount) <= _maxOperationsPerSecond; } } internal sealed class RandomNumberGenerator { [ThreadStatic] private static RandomNumberGenerator t_random; private ulong _s0; private ulong _s1; private ulong _s2; private ulong _s3; public static RandomNumberGenerator Current => t_random ?? (t_random = new RandomNumberGenerator()); public unsafe RandomNumberGenerator() { do { Guid guid = Guid.NewGuid(); Guid guid2 = Guid.NewGuid(); ulong* ptr = (ulong*)(&guid); ulong* ptr2 = (ulong*)(&guid2); _s0 = *ptr; _s1 = ptr[1]; _s2 = *ptr2; _s3 = ptr2[1]; _s0 = (_s0 & 0xFFFFFFFFFFFFFFFL) | (_s1 & 0xF000000000000000uL); _s2 = (_s2 & 0xFFFFFFFFFFFFFFFL) | (_s3 & 0xF000000000000000uL); _s1 = (_s1 & 0xFFFFFFFFFFFFFF3FuL) | (_s0 & 0xC0); _s3 = (_s3 & 0xFFFFFFFFFFFFFF3FuL) | (_s2 & 0xC0); } while ((_s0 | _s1 | _s2 | _s3) == 0L); } private static ulong Rol64(ulong x, int k) { return (x << k) | (x >> 64 - k); } public long Next() { ulong result = Rol64(_s1 * 5, 7) * 9; ulong num = _s1 << 17; _s2 ^= _s0; _s3 ^= _s1; _s1 ^= _s2; _s0 ^= _s3; _s2 ^= num; _s3 = Rol64(_s3, 45); return (long)result; } } internal sealed class W3CPropagator : DistributedContextPropagator { private const int MaxBaggageEntriesToEmit = 64; private const int MaxBaggageEncodedLength = 8192; private const int MaxTraceStateEncodedLength = 256; private const char Equal = '='; private const char Percent = '%'; private const char Replacement = '\ufffd'; private static ulong[] s_invalidBaggageKeyCharsMask = new ulong[2] { 18158675351536926719uL, 2882303762456641537uL }; private static ulong[] ValidTraceStateKeyCharsMask = new ulong[2] { 288129221081956352uL, 576460745860972545uL }; private static ulong[] s_traceStateValueMask = new ulong[2] { 16140883463719878656uL, 9223372036854775807uL }; private static ulong[] s_baggageOctet = new ulong[2] { 17870265566011326464uL, 9223372036586340351uL }; private static ulong[] s_traceParentMask = new ulong[2] { 287948901175001088uL, 541165879296uL }; internal static DistributedContextPropagator Instance { get; } = new W3CPropagator(); public override IReadOnlyCollection Fields { get; } = new ReadOnlyCollection(new string[4] { "traceparent", "tracestate", "baggage", "Correlation-Context" }); public override void Inject(Activity activity, object carrier, PropagatorSetterCallback setter) { if (activity == null || setter == null || activity.IdFormat != ActivityIdFormat.W3C) { return; } string id = activity.Id; if (id != null) { setter(carrier, "traceparent", id); string traceStateString = activity.TraceStateString; if (traceStateString != null && traceStateString.Length > 0) { InjectTraceState(traceStateString, carrier, setter); } InjectW3CBaggage(carrier, activity.Baggage, setter); } } public override void ExtractTraceIdAndState(object carrier, PropagatorGetterCallback getter, out string traceId, out string traceState) { if (getter == null) { traceId = null; traceState = null; return; } getter(carrier, "traceparent", out traceId, out var fieldValues); if (IsInvalidTraceParent(traceId)) { traceId = null; } getter(carrier, "tracestate", out var fieldValue, out fieldValues); traceState = ValidateTraceState(fieldValue); } public override IEnumerable> ExtractBaggage(object carrier, PropagatorGetterCallback getter) { if (getter == null) { return null; } getter(carrier, "baggage", out var fieldValue, out var fieldValues); if (fieldValue == null) { getter(carrier, "Correlation-Context", out fieldValue, out fieldValues); } TryExtractBaggage(fieldValue, out var baggage); return baggage; } internal static bool TryExtractBaggage(string baggageString, out IEnumerable> baggage) { baggage = null; List> list = null; if (string.IsNullOrEmpty(baggageString)) { return true; } ReadOnlySpan readOnlySpan = baggageString.AsSpan(); do { int num = readOnlySpan.IndexOf(','); ReadOnlySpan span = ((num >= 0) ? readOnlySpan.Slice(0, num) : readOnlySpan); int num2 = span.IndexOf('='); if (num2 <= 0 || num2 >= span.Length - 1) { break; } ReadOnlySpan keySpan = span.Slice(0, num2); ReadOnlySpan valueSpan = span.Slice(num2 + 1); if (TryDecodeBaggageKey(keySpan, out var key) && TryDecodeBaggageValue(valueSpan, out var value)) { if (list == null) { list = new List>(); } list.Add(new KeyValuePair(key, value)); } readOnlySpan = ((num >= 0) ? readOnlySpan.Slice(num + 1) : ReadOnlySpan.Empty); } while (readOnlySpan.Length > 0); list?.Reverse(); baggage = list; return list != null; } internal static string ValidateTraceState(string traceState) { if (string.IsNullOrEmpty(traceState)) { return null; } int i; int num2; for (i = 0; i < traceState.Length; i += num2) { ReadOnlySpan readOnlySpan = traceState.AsSpan(i); int num = readOnlySpan.IndexOf(','); ReadOnlySpan span = ((num >= 0) ? readOnlySpan.Slice(0, num) : readOnlySpan); num2 = span.Length + ((num >= 0) ? 1 : 0); if (i + num2 > 256) { break; } int num3 = span.IndexOf('='); if (num3 <= 0 || num3 >= span.Length - 1 || IsInvalidTraceStateKey(Trim(span.Slice(0, num3))) || IsInvalidTraceStateValue(TrimSpaceOnly(span.Slice(num3 + 1)))) { break; } } if (i > 0) { if (traceState[i - 1] == ',') { i--; } if (i > 0) { if (i < traceState.Length) { return traceState.AsSpan(0, i).ToString(); } return traceState; } } return null; } internal static void InjectTraceState(string traceState, object carrier, PropagatorSetterCallback setter) { string text = ValidateTraceState(traceState); if (text != null) { setter(carrier, "tracestate", text); } } internal static void InjectW3CBaggage(object carrier, IEnumerable> baggage, PropagatorSetterCallback setter) { using IEnumerator> enumerator = baggage.GetEnumerator(); if (!enumerator.MoveNext()) { return; } Span initialBuffer = stackalloc char[256]; System.Text.ValueStringBuilder vsb = new System.Text.ValueStringBuilder(initialBuffer); int num = 0; int num2 = 0; do { KeyValuePair current = enumerator.Current; if (EncodeBaggageKey(current.Key.AsSpan(), ref vsb)) { vsb.Append(' '); vsb.Append('='); vsb.Append(' '); if (!string.IsNullOrEmpty(current.Value)) { EncodeBaggageValue(current.Value.AsSpan(), ref vsb); } vsb.Append(", "); num++; if (vsb.Length < 8192) { num2 = vsb.Length; } } } while (enumerator.MoveNext() && num < 64 && vsb.Length < 8192); if (num2 - 2 > 0) { setter(carrier, "baggage", vsb.AsSpan(0, num2 - 2).ToString()); } vsb.Dispose(); } private static bool TryDecodeBaggageKey(ReadOnlySpan keySpan, out string key) { key = null; keySpan = Trim(keySpan); if (keySpan.IsEmpty || IsInvalidBaggageKey(keySpan)) { return false; } key = keySpan.ToString(); return true; } private static bool TryDecodeBaggageValue(ReadOnlySpan valueSpan, out string value) { value = null; valueSpan = Trim(valueSpan); Span initialBuffer = stackalloc char[128]; using System.Text.ValueStringBuilder valueStringBuilder = new System.Text.ValueStringBuilder(initialBuffer); for (int i = 0; i < valueSpan.Length; i++) { char c = valueSpan[i]; if (c > '\u007f') { return false; } if (c != '%') { valueStringBuilder.Append(c); continue; } if (!TryDecodeEscapedByte(valueSpan.Slice(i), out var value2)) { return false; } if (value2 <= 127) { valueStringBuilder.Append((char)value2); i += 2; continue; } switch (value2) { case 194: case 195: case 196: case 197: case 198: case 199: case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: case 208: case 209: case 210: case 211: case 212: case 213: case 214: case 215: case 216: case 217: case 218: case 219: case 220: case 221: case 222: case 223: { if (i + 5 >= valueSpan.Length || valueSpan[i + 3] != '%' || !TryDecodeEscapedByte(valueSpan.Slice(i + 3), out var value6) || (value6 & 0xC0) != 128) { valueStringBuilder.Append('\ufffd'); i += 2; } else { valueStringBuilder.Append((char)(((value2 & 0x1F) << 6) | (value6 & 0x3F))); i += 5; } break; } case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: { if (i + 8 >= valueSpan.Length || valueSpan[i + 3] != '%' || valueSpan[i + 6] != '%' || !TryDecodeEscapedByte(valueSpan.Slice(i + 3), out var value7) || !TryDecodeEscapedByte(valueSpan.Slice(i + 6), out var value8) || (value2 == 224 && value7 < 160) || (value2 == 237 && value7 >= 160)) { valueStringBuilder.Append('\ufffd'); i += 2; } else { valueStringBuilder.Append((char)(((value2 & 0xF) << 12) | ((value7 & 0x3F) << 6) | (value8 & 0x3F))); i += 8; } break; } case 240: case 241: case 242: case 243: case 244: { if (i + 11 >= valueSpan.Length || valueSpan[i + 3] != '%' || valueSpan[i + 6] != '%' || valueSpan[i + 9] != '%' || !TryDecodeEscapedByte(valueSpan.Slice(i + 3), out var value3) || !TryDecodeEscapedByte(valueSpan.Slice(i + 6), out var value4) || !TryDecodeEscapedByte(valueSpan.Slice(i + 9), out var value5) || (value3 & 0xC0) != 128 || (value4 & 0xC0) != 128 || (value5 & 0xC0) != 128) { valueStringBuilder.Append('\ufffd'); i += 2; break; } int num = ((value2 & 7) << 18) | ((value3 & 0x3F) << 12) | ((value4 & 0x3F) << 6) | (value5 & 0x3F); if (num < 65536 || num > 1114111) { valueStringBuilder.Append('\ufffd'); i += 2; break; } num -= 65536; valueStringBuilder.Append((char)((num >> 10) + 55296)); valueStringBuilder.Append((char)((num & 0x3FF) + 56320)); i += 11; break; } default: valueStringBuilder.Append('\ufffd'); i += 2; break; } } value = valueStringBuilder.ToString(); return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool TryDecodeEscapedByte(ReadOnlySpan span, out byte value) { if (span.Length < 3 || !TryDecodeHexDigit(span[1], out var value2) || !TryDecodeHexDigit(span[2], out var value3)) { value = 0; return false; } value = (byte)((value2 << 4) + value3); return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool TryDecodeHexDigit(char c, out byte value) { value = (byte)System.HexConverter.FromChar(c); return value != byte.MaxValue; } private static bool IsInvalidBaggageKey(ReadOnlySpan span) { ReadOnlySpan readOnlySpan = span; for (int i = 0; i < readOnlySpan.Length; i++) { char c = readOnlySpan[i]; if (c >= '\u007f' || (s_invalidBaggageKeyCharsMask[(int)c >> 6] & (ulong)(1L << (int)c)) != 0L) { return true; } } return false; } private static bool IsInvalidTraceStateKey(ReadOnlySpan key) { if (key.IsEmpty || ((uint)(122 - key[0]) > 25u && (uint)(57 - key[0]) > 9u)) { return true; } ReadOnlySpan readOnlySpan = key; for (int i = 0; i < readOnlySpan.Length; i++) { char c = readOnlySpan[i]; if (c >= '\u007f' || (ValidTraceStateKeyCharsMask[(int)c >> 6] & (ulong)(1L << (int)c)) == 0L) { return true; } } return false; } private static bool IsInvalidTraceStateValue(ReadOnlySpan value) { if (value.IsEmpty) { return true; } ReadOnlySpan readOnlySpan = value; for (int i = 0; i < readOnlySpan.Length; i++) { char c = readOnlySpan[i]; if (c >= '\u007f' || (s_traceStateValueMask[(int)c >> 6] & (ulong)(1L << (int)c)) == 0L) { return true; } } return false; } internal static bool EncodeBaggageKey(ReadOnlySpan key, ref System.Text.ValueStringBuilder vsb) { key = Trim(key); if (key.IsEmpty || IsInvalidBaggageKey(key)) { return false; } vsb.Append(key); return true; } internal static void EncodeBaggageValue(ReadOnlySpan value, ref System.Text.ValueStringBuilder vsb) { value = Trim(value); for (int i = 0; i < value.Length; i++) { char c = value[i]; if (!NeedToEscapeBaggageValueCharacter(c)) { vsb.Append(c); } else if ((uint)c <= 127u) { EmitEscapedByte((byte)c, ref vsb); } else if ((uint)c <= 2047u) { EmitEscapedByte((byte)((uint)(c + 12288) >> 6), ref vsb); EmitEscapedByte((byte)((c & 0x3F) + 128), ref vsb); } else if (char.IsSurrogate(c)) { if (i < value.Length - 1 && char.IsSurrogatePair(c, value[i + 1])) { int num = char.ConvertToUtf32(c, value[i + 1]); EmitEscapedByte((byte)((uint)(num + 62914560) >> 18), ref vsb); EmitEscapedByte((byte)(((num & 0x3F000) >>> 12) + 128), ref vsb); EmitEscapedByte((byte)(((num & 0xFC0) >>> 6) + 128), ref vsb); EmitEscapedByte((byte)((num & 0x3F) + 128), ref vsb); i++; } else { EmitEscapedByte(239, ref vsb); EmitEscapedByte(191, ref vsb); EmitEscapedByte(189, ref vsb); } } else { EmitEscapedByte((byte)(c + 917504 >> 12), ref vsb); EmitEscapedByte((byte)(((c & 0xFC0) >>> 6) + 128), ref vsb); EmitEscapedByte((byte)((c & 0x3F) + 128), ref vsb); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool NeedToEscapeBaggageValueCharacter(char c) { if (c >= '\u007f') { return true; } return (s_baggageOctet[(int)c >> 6] & (ulong)(1L << (int)c)) == 0; } private static bool IsInvalidTraceParent(string traceParent) { if (string.IsNullOrEmpty(traceParent) || traceParent.Length < 55) { return true; } if ((traceParent[0] == 'f' && traceParent[1] == 'f') || IsInvalidTraceParentCharacter(traceParent[0]) || IsInvalidTraceParentCharacter(traceParent[1])) { return true; } if (traceParent[0] == '0' && traceParent[1] == '0') { if (traceParent.Length != 55) { return true; } } else if (traceParent.Length > 55 && traceParent[55] != '-') { return true; } if (traceParent[2] != '-' || traceParent[35] != '-' || traceParent[52] != '-') { return true; } bool flag = true; for (int i = 3; i < 35; i++) { if (IsInvalidTraceParentCharacter(traceParent[i])) { return true; } flag &= traceParent[i] == '0'; } if (flag) { return true; } flag = true; for (int j = 36; j < 52; j++) { if (IsInvalidTraceParentCharacter(traceParent[j])) { return true; } flag &= traceParent[j] == '0'; } if (flag) { return true; } if (IsInvalidTraceParentCharacter(traceParent[53]) || IsInvalidTraceParentCharacter(traceParent[54])) { return true; } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsInvalidTraceParentCharacter(char c) { if (c >= '\u007f') { return true; } return (s_traceParentMask[(int)c >> 6] & (ulong)(1L << (int)c)) == 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void EmitEscapedByte(byte b, ref System.Text.ValueStringBuilder vsb) { vsb.Append('%'); vsb.Append("0123456789ABCDEF"[(b >> 4) & 0xF]); vsb.Append("0123456789ABCDEF"[b & 0xF]); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan TrimSpaceOnly(ReadOnlySpan span) { return span.Trim(' '); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan Trim(ReadOnlySpan span) { return span.Trim(" \t".AsSpan()); } } internal static class DiagnosticsHelper { internal static bool CompareTags(IList> sortedTags, IEnumerable> tags2) { if (sortedTags == tags2) { return true; } if (sortedTags == null || tags2 == null) { return false; } int count = sortedTags.Count; int num = count / 64 + 1; Span bitMap = (((uint)num > 100u) ? ((Span)new ulong[num]) : stackalloc ulong[num]); BitMapper bitMapper = new BitMapper(bitMap); if (tags2 is ICollection> collection) { if (collection.Count != count) { return false; } if (collection is IList> list) { for (int i = 0; i < count; i++) { KeyValuePair keyValuePair = list[i]; for (int j = 0; j < count; j++) { if (!bitMapper.IsSet(j)) { KeyValuePair keyValuePair2 = sortedTags[j]; int num2 = string.CompareOrdinal(keyValuePair.Key, keyValuePair2.Key); if (num2 == 0 && object.Equals(keyValuePair.Value, keyValuePair2.Value)) { bitMapper.SetBit(j); break; } if (num2 < 0 || j == count - 1) { return false; } } } } return true; } } int num3 = 0; using IEnumerator> enumerator = tags2.GetEnumerator(); while (enumerator.MoveNext()) { num3++; if (num3 > sortedTags.Count) { return false; } KeyValuePair current = enumerator.Current; for (int k = 0; k < count; k++) { if (!bitMapper.IsSet(k)) { KeyValuePair keyValuePair3 = sortedTags[k]; int num4 = string.CompareOrdinal(current.Key, keyValuePair3.Key); if (num4 == 0 && object.Equals(current.Value, keyValuePair3.Value)) { bitMapper.SetBit(k); break; } if (num4 < 0 || k == count - 1) { return false; } } } } return num3 == sortedTags.Count; } } internal ref struct BitMapper { private int _maxIndex; private Span _bitMap; public int MaxIndex => _maxIndex; public BitMapper(Span bitMap) { _bitMap = bitMap; _bitMap.Clear(); _maxIndex = bitMap.Length * 8 * 8; } private static void GetIndexAndMask(int index, out int bitIndex, out ulong mask) { bitIndex = index >> 6; int num = index & 0x3F; mask = (ulong)(1L << num); } public bool SetBit(int index) { GetIndexAndMask(index, out var bitIndex, out var mask); ulong num = _bitMap[bitIndex]; _bitMap[bitIndex] = num | mask; return true; } public bool IsSet(int index) { GetIndexAndMask(index, out var bitIndex, out var mask); return (_bitMap[bitIndex] & mask) != 0; } } public struct TagList : IList>, ICollection>, IEnumerable>, IEnumerable, IReadOnlyList>, IReadOnlyCollection> { public struct Enumerator : IEnumerator>, IEnumerator, IDisposable { private TagList _tagList; private int _index; public KeyValuePair Current => _tagList[_index]; object IEnumerator.Current => _tagList[_index]; internal Enumerator(in TagList tagList) { _index = -1; _tagList = tagList; } public void Dispose() { _index = _tagList.Count; } public bool MoveNext() { _index++; return _index < _tagList.Count; } public void Reset() { _index = -1; } } internal KeyValuePair Tag1; internal KeyValuePair Tag2; internal KeyValuePair Tag3; internal KeyValuePair Tag4; internal KeyValuePair Tag5; internal KeyValuePair Tag6; internal KeyValuePair Tag7; internal KeyValuePair Tag8; private int _tagsCount; private KeyValuePair[] _overflowTags; private const int OverflowAdditionalCapacity = 8; public readonly int Count => _tagsCount; public readonly bool IsReadOnly => false; public KeyValuePair this[int index] { readonly get { if ((uint)index >= (uint)_tagsCount) { throw new ArgumentOutOfRangeException("index"); } if (_overflowTags != null) { return _overflowTags[index]; } return index switch { 0 => Tag1, 1 => Tag2, 2 => Tag3, 3 => Tag4, 4 => Tag5, 5 => Tag6, 6 => Tag7, 7 => Tag8, _ => default(KeyValuePair), }; } set { if ((uint)index >= (uint)_tagsCount) { throw new ArgumentOutOfRangeException("index"); } if (_overflowTags != null) { _overflowTags[index] = value; return; } switch (index) { case 0: Tag1 = value; break; case 1: Tag2 = value; break; case 2: Tag3 = value; break; case 3: Tag4 = value; break; case 4: Tag5 = value; break; case 5: Tag6 = value; break; case 6: Tag7 = value; break; case 7: Tag8 = value; break; } } } internal readonly KeyValuePair[]? Tags => _overflowTags; public TagList([ParamCollection] scoped ReadOnlySpan> tagList) { this = default(TagList); _tagsCount = tagList.Length; switch (_tagsCount) { case 8: Tag8 = tagList[7]; goto case 7; case 7: Tag7 = tagList[6]; goto case 6; case 6: Tag6 = tagList[5]; goto case 5; case 5: Tag5 = tagList[4]; goto case 4; case 4: Tag4 = tagList[3]; goto case 3; case 3: Tag3 = tagList[2]; goto case 2; case 2: Tag2 = tagList[1]; goto case 1; case 1: Tag1 = tagList[0]; break; case 0: break; default: _overflowTags = new KeyValuePair[_tagsCount + 8]; tagList.CopyTo(_overflowTags); break; } } public void Add(string key, object? value) { Add(new KeyValuePair(key, value)); } public void Add(KeyValuePair tag) { if (_overflowTags != null) { if (_tagsCount == _overflowTags.Length) { Array.Resize(ref _overflowTags, _tagsCount + 8); } _overflowTags[_tagsCount++] = tag; return; } switch (_tagsCount) { default: return; case 0: Tag1 = tag; break; case 1: Tag2 = tag; break; case 2: Tag3 = tag; break; case 3: Tag4 = tag; break; case 4: Tag5 = tag; break; case 5: Tag6 = tag; break; case 6: Tag7 = tag; break; case 7: Tag8 = tag; break; case 8: MoveTagsToTheArray(); _overflowTags[8] = tag; break; } _tagsCount++; } public readonly void CopyTo(Span> tags) { if (tags.Length < _tagsCount) { throw new ArgumentException(System.SR.Arg_BufferTooSmall); } if (_overflowTags != null) { _overflowTags.AsSpan(0, _tagsCount).CopyTo(tags); return; } switch (_tagsCount) { default: return; case 8: tags[7] = Tag8; goto case 7; case 7: tags[6] = Tag7; goto case 6; case 6: tags[5] = Tag6; goto case 5; case 5: tags[4] = Tag5; goto case 4; case 4: tags[3] = Tag4; goto case 3; case 3: tags[2] = Tag3; goto case 2; case 2: tags[1] = Tag2; break; case 1: break; case 0: return; } tags[0] = Tag1; } public readonly void CopyTo(KeyValuePair[] array, int arrayIndex) { ExceptionPolyfills.ThrowIfNull(array, "array"); if ((uint)arrayIndex >= array.Length) { throw new ArgumentOutOfRangeException("arrayIndex"); } CopyTo(array.AsSpan(arrayIndex)); } public void Insert(int index, KeyValuePair item) { if ((uint)index > (uint)_tagsCount) { throw new ArgumentOutOfRangeException("index"); } if (index == _tagsCount) { Add(item); return; } if (_tagsCount == 8 && _overflowTags == null) { MoveTagsToTheArray(); } if (_overflowTags != null) { if (_tagsCount == _overflowTags.Length) { Array.Resize(ref _overflowTags, _tagsCount + 8); } for (int num = _tagsCount; num > index; num--) { _overflowTags[num] = _overflowTags[num - 1]; } _overflowTags[index] = item; _tagsCount++; return; } switch (index) { default: return; case 0: Tag8 = Tag7; Tag7 = Tag6; Tag6 = Tag5; Tag5 = Tag4; Tag4 = Tag3; Tag3 = Tag2; Tag2 = Tag1; Tag1 = item; break; case 1: Tag8 = Tag7; Tag7 = Tag6; Tag6 = Tag5; Tag5 = Tag4; Tag4 = Tag3; Tag3 = Tag2; Tag2 = item; break; case 2: Tag8 = Tag7; Tag7 = Tag6; Tag6 = Tag5; Tag5 = Tag4; Tag4 = Tag3; Tag3 = item; break; case 3: Tag8 = Tag7; Tag7 = Tag6; Tag6 = Tag5; Tag5 = Tag4; Tag4 = item; break; case 4: Tag8 = Tag7; Tag7 = Tag6; Tag6 = Tag5; Tag5 = item; break; case 5: Tag8 = Tag7; Tag7 = Tag6; Tag6 = item; break; case 6: Tag8 = Tag7; Tag7 = item; break; } _tagsCount++; } public void RemoveAt(int index) { if ((uint)index >= (uint)_tagsCount) { throw new ArgumentOutOfRangeException("index"); } if (_overflowTags != null) { for (int i = index; i < _tagsCount - 1; i++) { _overflowTags[i] = _overflowTags[i + 1]; } _tagsCount--; return; } switch (index) { case 0: Tag1 = Tag2; goto case 1; case 1: Tag2 = Tag3; goto case 2; case 2: Tag3 = Tag4; goto case 3; case 3: Tag4 = Tag5; goto case 4; case 4: Tag5 = Tag6; goto case 5; case 5: Tag6 = Tag7; goto case 6; case 6: Tag7 = Tag8; break; } _tagsCount--; } public void Clear() { _tagsCount = 0; } public readonly bool Contains(KeyValuePair item) { return IndexOf(item) >= 0; } public bool Remove(KeyValuePair item) { int num = IndexOf(item); if (num >= 0) { RemoveAt(num); return true; } return false; } public readonly IEnumerator> GetEnumerator() { return new Enumerator(in this); } readonly IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(in this); } public readonly int IndexOf(KeyValuePair item) { if (_overflowTags != null) { for (int i = 0; i < _tagsCount; i++) { if (TagsEqual(_overflowTags[i], item)) { return i; } } return -1; } switch (_tagsCount) { case 1: if (TagsEqual(Tag1, item)) { return 0; } break; case 2: if (TagsEqual(Tag1, item)) { return 0; } if (TagsEqual(Tag2, item)) { return 1; } break; case 3: if (TagsEqual(Tag1, item)) { return 0; } if (TagsEqual(Tag2, item)) { return 1; } if (TagsEqual(Tag3, item)) { return 2; } break; case 4: if (TagsEqual(Tag1, item)) { return 0; } if (TagsEqual(Tag2, item)) { return 1; } if (TagsEqual(Tag3, item)) { return 2; } if (TagsEqual(Tag4, item)) { return 3; } break; case 5: if (TagsEqual(Tag1, item)) { return 0; } if (TagsEqual(Tag2, item)) { return 1; } if (TagsEqual(Tag3, item)) { return 2; } if (TagsEqual(Tag4, item)) { return 3; } if (TagsEqual(Tag5, item)) { return 4; } break; case 6: if (TagsEqual(Tag1, item)) { return 0; } if (TagsEqual(Tag2, item)) { return 1; } if (TagsEqual(Tag3, item)) { return 2; } if (TagsEqual(Tag4, item)) { return 3; } if (TagsEqual(Tag5, item)) { return 4; } if (TagsEqual(Tag6, item)) { return 5; } break; case 7: if (TagsEqual(Tag1, item)) { return 0; } if (TagsEqual(Tag2, item)) { return 1; } if (TagsEqual(Tag3, item)) { return 2; } if (TagsEqual(Tag4, item)) { return 3; } if (TagsEqual(Tag5, item)) { return 4; } if (TagsEqual(Tag6, item)) { return 5; } if (TagsEqual(Tag7, item)) { return 6; } break; case 8: if (TagsEqual(Tag1, item)) { return 0; } if (TagsEqual(Tag2, item)) { return 1; } if (TagsEqual(Tag3, item)) { return 2; } if (TagsEqual(Tag4, item)) { return 3; } if (TagsEqual(Tag5, item)) { return 4; } if (TagsEqual(Tag6, item)) { return 5; } if (TagsEqual(Tag7, item)) { return 6; } if (TagsEqual(Tag8, item)) { return 7; } break; } return -1; } private static bool TagsEqual(KeyValuePair tag1, KeyValuePair tag2) { if (tag1.Key != tag2.Key) { return false; } if (tag1.Value == null) { if (tag2.Value != null) { return false; } } else if (!tag1.Value.Equals(tag2.Value)) { return false; } return true; } private void MoveTagsToTheArray() { _overflowTags = new KeyValuePair[16]; _overflowTags[0] = Tag1; _overflowTags[1] = Tag2; _overflowTags[2] = Tag3; _overflowTags[3] = Tag4; _overflowTags[4] = Tag5; _overflowTags[5] = Tag6; _overflowTags[6] = Tag7; _overflowTags[7] = Tag8; } } internal static class ThisAssembly { private const string BuildAssemblyFileVersion = "10.0.1126.37416"; public static Version AssemblyFileVersion { get; } = new Version("10.0.1126.37416"); } } namespace System.Diagnostics.CodeAnalysis { [CompilerLoweringPreserve] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)] internal sealed class DynamicallyAccessedMembersAttribute : Attribute { public DynamicallyAccessedMemberTypes MemberTypes { get; } public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes) { MemberTypes = memberTypes; } } [Flags] internal enum DynamicallyAccessedMemberTypes { None = 0, PublicParameterlessConstructor = 1, PublicConstructors = 3, NonPublicConstructors = 4, PublicMethods = 8, NonPublicMethods = 0x10, PublicFields = 0x20, NonPublicFields = 0x40, PublicNestedTypes = 0x80, NonPublicNestedTypes = 0x100, PublicProperties = 0x200, NonPublicProperties = 0x400, PublicEvents = 0x800, NonPublicEvents = 0x1000, Interfaces = 0x2000, NonPublicConstructorsWithInherited = 0x4004, NonPublicMethodsWithInherited = 0x8010, NonPublicFieldsWithInherited = 0x10040, NonPublicNestedTypesWithInherited = 0x20100, NonPublicPropertiesWithInherited = 0x40400, NonPublicEventsWithInherited = 0x81000, PublicConstructorsWithInherited = 0x100003, PublicNestedTypesWithInherited = 0x200080, AllConstructors = 0x104007, AllMethods = 0x8018, AllFields = 0x10060, AllNestedTypes = 0x220180, AllProperties = 0x40600, AllEvents = 0x81800, [EditorBrowsable(EditorBrowsableState.Never)] All = -1 } [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Field, AllowMultiple = true, Inherited = false)] internal sealed class DynamicDependencyAttribute : Attribute { public string MemberSignature { get; } public DynamicallyAccessedMemberTypes MemberTypes { get; } public Type Type { get; } public string TypeName { get; } public string AssemblyName { get; } [Obsolete("This property is no longer supported.")] [EditorBrowsable(EditorBrowsableState.Never)] public string Condition { get; set; } public DynamicDependencyAttribute(string memberSignature) { MemberSignature = memberSignature; } public DynamicDependencyAttribute(string memberSignature, Type type) { MemberSignature = memberSignature; Type = type; } public DynamicDependencyAttribute(string memberSignature, string typeName, string assemblyName) { MemberSignature = memberSignature; TypeName = typeName; AssemblyName = assemblyName; } public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, Type type) { MemberTypes = memberTypes; Type = type; } public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, string typeName, string assemblyName) { MemberTypes = memberTypes; TypeName = typeName; AssemblyName = assemblyName; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)] internal sealed class RequiresDynamicCodeAttribute : Attribute { public bool ExcludeStatics { get; set; } public string Message { get; } public string Url { get; set; } public RequiresDynamicCodeAttribute(string message) { Message = message; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)] internal sealed class RequiresUnreferencedCodeAttribute : Attribute { public bool ExcludeStatics { get; set; } public string Message { get; } public string Url { get; set; } public RequiresUnreferencedCodeAttribute(string message) { Message = message; } } [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] internal sealed class UnconditionalSuppressMessageAttribute : Attribute { public string Category { get; } public string CheckId { get; } public string Scope { get; set; } public string Target { get; set; } public string MessageId { get; set; } public string Justification { get; set; } public UnconditionalSuppressMessageAttribute(string category, string checkId) { Category = category; CheckId = checkId; } } [AttributeUsage(AttributeTargets.Property, Inherited = false)] internal sealed class FeatureSwitchDefinitionAttribute : Attribute { public string SwitchName { get; } public FeatureSwitchDefinitionAttribute(string switchName) { SwitchName = switchName; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class DisallowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class MaybeNullWhenAttribute : Attribute { public bool ReturnValue { get; } public MaybeNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] internal sealed class NotNullIfNotNullAttribute : Attribute { public string ParameterName { get; } public NotNullIfNotNullAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Method, Inherited = false)] internal sealed class DoesNotReturnAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } } namespace System.Diagnostics.Metrics { [SecuritySafeCritical] internal sealed class AggregationManager { public const double MinCollectionTimeSecs = 0.1; private static readonly QuantileAggregation s_defaultHistogramConfig = new QuantileAggregation(0.5, 0.95, 0.99); private readonly List> _instrumentConfigFuncs = new List>(); private Dictionary _instruments = new Dictionary(); private readonly ConcurrentDictionary _instrumentStates = new ConcurrentDictionary(); private readonly CancellationTokenSource _cts = new CancellationTokenSource(); private Thread _collectThread; private readonly MeterListener _listener; private int _currentTimeSeries; private int _currentHistograms; private readonly Action _collectMeasurement; private readonly Action _beginCollection; private readonly Action _endCollection; private readonly Action _beginInstrumentMeasurements; private readonly Action _endInstrumentMeasurements; private readonly Action _instrumentPublished; private readonly Action _initialInstrumentEnumerationComplete; private readonly Action _collectionError; private readonly Action _timeSeriesLimitReached; private readonly Action _histogramLimitReached; private readonly Action _observableInstrumentCallbackError; private DateTime _startTime; private DateTime _intervalStartTime; private DateTime _nextIntervalStartTime; private Func _histogramAggregatorFactory = () => new ExponentialHistogramAggregator(s_defaultHistogramConfig); public TimeSpan CollectionPeriod { get; private set; } public int MaxTimeSeries { get; } public int MaxHistograms { get; } public AggregationManager(int maxTimeSeries, int maxHistograms, Action collectMeasurement, Action beginCollection, Action endCollection, Action beginInstrumentMeasurements, Action endInstrumentMeasurements, Action instrumentPublished, Action initialInstrumentEnumerationComplete, Action collectionError, Action timeSeriesLimitReached, Action histogramLimitReached, Action observableInstrumentCallbackError) { MaxTimeSeries = maxTimeSeries; MaxHistograms = maxHistograms; _collectMeasurement = collectMeasurement; _beginCollection = beginCollection; _endCollection = endCollection; _beginInstrumentMeasurements = beginInstrumentMeasurements; _endInstrumentMeasurements = endInstrumentMeasurements; _instrumentPublished = instrumentPublished; _initialInstrumentEnumerationComplete = initialInstrumentEnumerationComplete; _collectionError = collectionError; _timeSeriesLimitReached = timeSeriesLimitReached; _histogramLimitReached = histogramLimitReached; _observableInstrumentCallbackError = observableInstrumentCallbackError; _listener = new MeterListener(); MeterListener listener = _listener; listener.InstrumentPublished = (Action)Delegate.Combine(listener.InstrumentPublished, new Action(PublishedInstrument)); MeterListener listener2 = _listener; listener2.MeasurementsCompleted = (Action)Delegate.Combine(listener2.MeasurementsCompleted, new Action(CompletedMeasurements)); _listener.SetMeasurementEventCallback(delegate(Instrument i, double m, ReadOnlySpan> l, object c) { ((InstrumentState)c).Update(m, l); }); _listener.SetMeasurementEventCallback(delegate(Instrument i, float m, ReadOnlySpan> l, object c) { ((InstrumentState)c).Update(m, l); }); _listener.SetMeasurementEventCallback(delegate(Instrument i, long m, ReadOnlySpan> l, object c) { ((InstrumentState)c).Update(m, l); }); _listener.SetMeasurementEventCallback(delegate(Instrument i, int m, ReadOnlySpan> l, object c) { ((InstrumentState)c).Update(m, l); }); _listener.SetMeasurementEventCallback(delegate(Instrument i, short m, ReadOnlySpan> l, object c) { ((InstrumentState)c).Update(m, l); }); _listener.SetMeasurementEventCallback(delegate(Instrument i, byte m, ReadOnlySpan> l, object c) { ((InstrumentState)c).Update((int)m, l); }); _listener.SetMeasurementEventCallback(delegate(Instrument i, decimal m, ReadOnlySpan> l, object c) { ((InstrumentState)c).Update((double)m, l); }); } public void Include(string meterName) { Include((Instrument i) => i.Meter.Name.Equals(meterName, StringComparison.OrdinalIgnoreCase)); } public void IncludeAll() { Include((Instrument i) => true); } public void IncludePrefix(string meterNamePrefix) { Include((Instrument i) => i.Meter.Name.StartsWith(meterNamePrefix, StringComparison.OrdinalIgnoreCase)); } public void Include(string meterName, string instrumentName) { Include((Instrument i) => i.Meter.Name.Equals(meterName, StringComparison.OrdinalIgnoreCase) && i.Name.Equals(instrumentName, StringComparison.OrdinalIgnoreCase)); } private void Include(Predicate instrumentFilter) { lock (this) { _instrumentConfigFuncs.Add(instrumentFilter); } } public void SetHistogramAggregation(Func histogramAggregatorFactory) { lock (this) { _histogramAggregatorFactory = histogramAggregatorFactory; } } public AggregationManager SetCollectionPeriod(TimeSpan collectionPeriod) { lock (this) { CollectionPeriod = collectionPeriod; return this; } } private void CompletedMeasurements(Instrument instrument, object cookie) { _instruments.Remove(instrument); _endInstrumentMeasurements(instrument, (InstrumentState)cookie); RemoveInstrumentState(instrument); } private void PublishedInstrument(Instrument instrument, MeterListener _) { InstrumentState instrumentState = GetInstrumentState(instrument); _instrumentPublished(instrument, instrumentState); if (instrumentState != null) { _beginInstrumentMeasurements(instrument, instrumentState); if (!_instruments.ContainsKey(instrument)) { _listener.EnableMeasurementEvents(instrument, instrumentState); _instruments.Add(instrument, value: true); } } } public void Start() { _intervalStartTime = (_nextIntervalStartTime = (_startTime = DateTime.UtcNow)); _collectThread = new Thread(CollectWorker); _collectThread.IsBackground = true; _collectThread.Name = "MetricsEventSource CollectWorker"; _collectThread.Start(); _listener.Start(); _initialInstrumentEnumerationComplete(); } public void Update() { using (MeterListener meterListener = new MeterListener()) { meterListener.InstrumentPublished = (Action)Delegate.Combine(meterListener.InstrumentPublished, new Action(PublishedInstrument)); meterListener.MeasurementsCompleted = (Action)Delegate.Combine(meterListener.MeasurementsCompleted, new Action(CompletedMeasurements)); meterListener.Start(); } _initialInstrumentEnumerationComplete(); } private TimeSpan CalculateDelayTime(double collectionIntervalSecs) { _intervalStartTime = _nextIntervalStartTime; DateTime utcNow = DateTime.UtcNow; double value = Math.Ceiling((utcNow - _startTime).TotalSeconds / collectionIntervalSecs) * collectionIntervalSecs; _nextIntervalStartTime = _startTime.AddSeconds(value); DateTime dateTime = _intervalStartTime.AddSeconds(collectionIntervalSecs); if (_nextIntervalStartTime <= dateTime) { _nextIntervalStartTime = dateTime; } return _nextIntervalStartTime - utcNow; } private void CollectWorker() { try { double collectionIntervalSecs = -1.0; CancellationToken token; lock (this) { collectionIntervalSecs = CollectionPeriod.TotalSeconds; token = _cts.Token; } _ = DateTime.UtcNow; while (!_cts.Token.IsCancellationRequested) { TimeSpan timeout = CalculateDelayTime(collectionIntervalSecs); if (!token.WaitHandle.WaitOne(timeout)) { _beginCollection(_intervalStartTime, _nextIntervalStartTime); Collect(); _endCollection(_intervalStartTime, _nextIntervalStartTime); continue; } break; } } catch (Exception obj) { _collectionError(obj); } } public void Dispose() { _cts.Cancel(); _collectThread?.Join(); _collectThread = null; _listener.Dispose(); } private void RemoveInstrumentState(Instrument instrument) { _instrumentStates.TryRemove(instrument, out var _); } private InstrumentState GetInstrumentState(Instrument instrument) { if (!_instrumentStates.TryGetValue(instrument, out var value)) { lock (this) { foreach (Predicate instrumentConfigFunc in _instrumentConfigFuncs) { if (instrumentConfigFunc(instrument)) { value = BuildInstrumentState(instrument); if (value != null) { _instrumentStates.TryAdd(instrument, value); _instrumentStates.TryGetValue(instrument, out value); } break; } } } } return value; } [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", Justification = "MakeGenericType is creating instances over reference types that works fine in AOT.")] internal InstrumentState BuildInstrumentState(Instrument instrument) { Func aggregatorFactory = GetAggregatorFactory(instrument); if (aggregatorFactory == null) { return null; } Type type = aggregatorFactory.GetType().GenericTypeArguments[0]; return (InstrumentState)Activator.CreateInstance(typeof(InstrumentState<>).MakeGenericType(type), aggregatorFactory); } private Func GetAggregatorFactory(Instrument instrument) { Type type = instrument.GetType(); Type type2 = null; type2 = (type.IsGenericType ? type.GetGenericTypeDefinition() : null); if (type2 == typeof(Counter<>)) { return delegate { lock (this) { return CheckTimeSeriesAllowed() ? new CounterAggregator(isMonotonic: true) : null; } }; } if (type2 == typeof(ObservableCounter<>)) { return delegate { lock (this) { return CheckTimeSeriesAllowed() ? new ObservableCounterAggregator(isMonotonic: true) : null; } }; } if (type2 == typeof(ObservableGauge<>)) { return delegate { lock (this) { return CheckTimeSeriesAllowed() ? new LastValue() : null; } }; } if (type2 == typeof(Gauge<>)) { return delegate { lock (this) { return CheckTimeSeriesAllowed() ? new SynchronousLastValue() : null; } }; } if (type2 == typeof(Histogram<>)) { return delegate { lock (this) { return (!CheckHistogramAllowed() || !CheckTimeSeriesAllowed()) ? null : _histogramAggregatorFactory(); } }; } if (type2 == typeof(UpDownCounter<>)) { return delegate { lock (this) { return CheckTimeSeriesAllowed() ? new CounterAggregator(isMonotonic: false) : null; } }; } if (type2 == typeof(ObservableUpDownCounter<>)) { return delegate { lock (this) { return CheckTimeSeriesAllowed() ? new ObservableCounterAggregator(isMonotonic: false) : null; } }; } return null; } private bool CheckTimeSeriesAllowed() { if (_currentTimeSeries < MaxTimeSeries) { _currentTimeSeries++; return true; } if (_currentTimeSeries == MaxTimeSeries) { _currentTimeSeries++; _timeSeriesLimitReached(); return false; } return false; } private bool CheckHistogramAllowed() { if (_currentHistograms < MaxHistograms) { _currentHistograms++; return true; } if (_currentHistograms == MaxHistograms) { _currentHistograms++; _histogramLimitReached(); return false; } return false; } internal void Collect() { try { _listener.RecordObservableInstruments(); } catch (Exception obj) { _observableInstrumentCallbackError(obj); } foreach (KeyValuePair kv in _instrumentStates) { kv.Value.Collect(kv.Key, delegate(LabeledAggregationStatistics labeledAggStats) { _collectMeasurement(kv.Key, labeledAggStats, kv.Value); }); } } } internal abstract class Aggregator { public abstract void Update(double measurement); public abstract IAggregationStatistics Collect(); } internal interface IAggregationStatistics { } internal readonly struct QuantileValue { public double Quantile { get; } public double Value { get; } public QuantileValue(double quantile, double value) { Quantile = quantile; Value = value; } } internal sealed class HistogramStatistics : IAggregationStatistics { public QuantileValue[] Quantiles { get; } public int Count { get; } public double Sum { get; } internal HistogramStatistics(QuantileValue[] quantiles, int count, double sum) { Quantiles = quantiles; Count = count; Sum = sum; } } internal sealed class Base2ExponentialHistogramStatistics : IAggregationStatistics { public int Scale { get; } public long ZeroCount { get; } public double Sum { get; } public long Count { get; } public double Minimum { get; } public double Maximum { get; } public long[] PositiveBuckets { get; } internal Base2ExponentialHistogramStatistics(int scale, long zeroCount, double sum, long count, double min, double max, long[] buckets) { Scale = scale; ZeroCount = zeroCount; Sum = sum; Count = count; Minimum = min; Maximum = max; PositiveBuckets = buckets; } } internal sealed class LabeledAggregationStatistics { public KeyValuePair[] Labels { get; } public IAggregationStatistics AggregationStatistics { get; } public LabeledAggregationStatistics(IAggregationStatistics stats, params KeyValuePair[] labels) { AggregationStatistics = stats; Labels = labels; } } [SecuritySafeCritical] internal struct AggregatorStore where TAggregator : Aggregator { private volatile object _stateUnion; private volatile AggregatorLookupFunc _cachedLookupFunc; private readonly Func _createAggregatorFunc; public AggregatorStore(Func createAggregator) { _stateUnion = null; _cachedLookupFunc = null; _createAggregatorFunc = createAggregator; } public TAggregator GetAggregator(ReadOnlySpan> labels) { AggregatorLookupFunc cachedLookupFunc = _cachedLookupFunc; if (cachedLookupFunc != null && cachedLookupFunc(labels, out var aggregator)) { return aggregator; } return GetAggregatorSlow(labels); } private TAggregator GetAggregatorSlow(ReadOnlySpan> labels) { (_cachedLookupFunc = LabelInstructionCompiler.Create(ref this, _createAggregatorFunc, labels))(labels, out var aggregator); return aggregator; } public void Collect(Action visitFunc) { _ = _stateUnion; object stateUnion = _stateUnion; if (!(stateUnion is TAggregator val)) { if (!(stateUnion is FixedSizeLabelNameDictionary fixedSizeLabelNameDictionary)) { if (!(stateUnion is FixedSizeLabelNameDictionary fixedSizeLabelNameDictionary2)) { if (!(stateUnion is FixedSizeLabelNameDictionary fixedSizeLabelNameDictionary3)) { if (!(stateUnion is FixedSizeLabelNameDictionary fixedSizeLabelNameDictionary4)) { if (stateUnion is MultiSizeLabelNameDictionary multiSizeLabelNameDictionary) { multiSizeLabelNameDictionary.Collect(visitFunc); } } else { fixedSizeLabelNameDictionary4.Collect(visitFunc); } } else { fixedSizeLabelNameDictionary3.Collect(visitFunc); } } else { fixedSizeLabelNameDictionary2.Collect(visitFunc); } } else { fixedSizeLabelNameDictionary.Collect(visitFunc); } } else { IAggregationStatistics stats = val.Collect(); visitFunc(new LabeledAggregationStatistics(stats)); } } public TAggregator GetAggregator() { MultiSizeLabelNameDictionary multiSizeLabelNameDictionary2; while (true) { object stateUnion = _stateUnion; if (stateUnion == null) { TAggregator val = _createAggregatorFunc(); if (val == null) { return val; } if (Interlocked.CompareExchange(ref _stateUnion, val, null) == null) { return val; } continue; } if (stateUnion is TAggregator result) { return result; } if (stateUnion is MultiSizeLabelNameDictionary multiSizeLabelNameDictionary) { return multiSizeLabelNameDictionary.GetNoLabelAggregator(_createAggregatorFunc); } multiSizeLabelNameDictionary2 = new MultiSizeLabelNameDictionary(stateUnion); if (Interlocked.CompareExchange(ref _stateUnion, multiSizeLabelNameDictionary2, stateUnion) == stateUnion) { break; } } return multiSizeLabelNameDictionary2.GetNoLabelAggregator(_createAggregatorFunc); } public ConcurrentDictionary GetLabelValuesDictionary(in TStringSequence names) where TStringSequence : IStringSequence, IEquatable where TObjectSequence : IObjectSequence, IEquatable { MultiSizeLabelNameDictionary multiSizeLabelNameDictionary2; while (true) { object stateUnion = _stateUnion; if (stateUnion == null) { FixedSizeLabelNameDictionary fixedSizeLabelNameDictionary = new FixedSizeLabelNameDictionary(); if (Interlocked.CompareExchange(ref _stateUnion, fixedSizeLabelNameDictionary, null) == null) { return fixedSizeLabelNameDictionary.GetValuesDictionary(in names); } continue; } if (stateUnion is FixedSizeLabelNameDictionary fixedSizeLabelNameDictionary2) { return fixedSizeLabelNameDictionary2.GetValuesDictionary(in names); } if (stateUnion is MultiSizeLabelNameDictionary multiSizeLabelNameDictionary) { return multiSizeLabelNameDictionary.GetFixedSizeLabelNameDictionary().GetValuesDictionary(in names); } multiSizeLabelNameDictionary2 = new MultiSizeLabelNameDictionary(stateUnion); if (Interlocked.CompareExchange(ref _stateUnion, multiSizeLabelNameDictionary2, stateUnion) == stateUnion) { break; } } return multiSizeLabelNameDictionary2.GetFixedSizeLabelNameDictionary().GetValuesDictionary(in names); } } internal sealed class MultiSizeLabelNameDictionary where TAggregator : Aggregator { private TAggregator NoLabelAggregator; private FixedSizeLabelNameDictionary Label1; private FixedSizeLabelNameDictionary Label2; private FixedSizeLabelNameDictionary Label3; private FixedSizeLabelNameDictionary LabelMany; public MultiSizeLabelNameDictionary(object initialLabelNameDict) { NoLabelAggregator = null; Label1 = null; Label2 = null; Label3 = null; LabelMany = null; if (!(initialLabelNameDict is TAggregator noLabelAggregator)) { if (!(initialLabelNameDict is FixedSizeLabelNameDictionary label)) { if (!(initialLabelNameDict is FixedSizeLabelNameDictionary label2)) { if (!(initialLabelNameDict is FixedSizeLabelNameDictionary label3)) { if (initialLabelNameDict is FixedSizeLabelNameDictionary labelMany) { LabelMany = labelMany; } } else { Label3 = label3; } } else { Label2 = label2; } } else { Label1 = label; } } else { NoLabelAggregator = noLabelAggregator; } } public TAggregator GetNoLabelAggregator(Func createFunc) { if (NoLabelAggregator == null) { TAggregator val = createFunc(); if (val != null) { Interlocked.CompareExchange(ref NoLabelAggregator, val, null); } } return NoLabelAggregator; } public FixedSizeLabelNameDictionary GetFixedSizeLabelNameDictionary() where TStringSequence : IStringSequence, IEquatable where TObjectSequence : IObjectSequence, IEquatable { TStringSequence val = default(TStringSequence); if (!(val is StringSequence1)) { if (!(val is StringSequence2)) { if (!(val is StringSequence3)) { if (val is StringSequenceMany) { if (LabelMany == null) { Interlocked.CompareExchange(ref LabelMany, new FixedSizeLabelNameDictionary(), null); } return (FixedSizeLabelNameDictionary)(object)LabelMany; } return null; } if (Label3 == null) { Interlocked.CompareExchange(ref Label3, new FixedSizeLabelNameDictionary(), null); } return (FixedSizeLabelNameDictionary)(object)Label3; } if (Label2 == null) { Interlocked.CompareExchange(ref Label2, new FixedSizeLabelNameDictionary(), null); } return (FixedSizeLabelNameDictionary)(object)Label2; } if (Label1 == null) { Interlocked.CompareExchange(ref Label1, new FixedSizeLabelNameDictionary(), null); } return (FixedSizeLabelNameDictionary)(object)Label1; } public void Collect(Action visitFunc) { if (NoLabelAggregator != null) { IAggregationStatistics stats = NoLabelAggregator.Collect(); visitFunc(new LabeledAggregationStatistics(stats)); } Label1?.Collect(visitFunc); Label2?.Collect(visitFunc); Label3?.Collect(visitFunc); LabelMany?.Collect(visitFunc); } } internal readonly struct LabelInstruction { public int SourceIndex { get; } public string LabelName { get; } public LabelInstruction(int sourceIndex, string labelName) { SourceIndex = sourceIndex; LabelName = labelName; } } internal delegate bool AggregatorLookupFunc(ReadOnlySpan> labels, out TAggregator aggregator); [SecurityCritical] internal static class LabelInstructionCompiler { public static AggregatorLookupFunc Create(ref AggregatorStore aggregatorStore, Func createAggregatorFunc, ReadOnlySpan> labels) where TAggregator : Aggregator { LabelInstruction[] array = Compile(labels); Array.Sort(array, (LabelInstruction a, LabelInstruction b) => string.CompareOrdinal(a.LabelName, b.LabelName)); int expectedLabels = labels.Length; switch (array.Length) { case 0: { TAggregator defaultAggregator = aggregatorStore.GetAggregator(); return delegate(ReadOnlySpan> l, out TAggregator aggregator) { if (l.Length != expectedLabels) { aggregator = null; return false; } aggregator = defaultAggregator; return true; }; } case 1: { ConcurrentDictionary labelValuesDictionary2 = aggregatorStore.GetLabelValuesDictionary(new StringSequence1(array[0].LabelName)); return new LabelInstructionInterpreter(expectedLabels, array, labelValuesDictionary2, createAggregatorFunc).GetAggregator; } case 2: { ConcurrentDictionary labelValuesDictionary4 = aggregatorStore.GetLabelValuesDictionary(new StringSequence2(array[0].LabelName, array[1].LabelName)); return new LabelInstructionInterpreter(expectedLabels, array, labelValuesDictionary4, createAggregatorFunc).GetAggregator; } case 3: { ConcurrentDictionary labelValuesDictionary3 = aggregatorStore.GetLabelValuesDictionary(new StringSequence3(array[0].LabelName, array[1].LabelName, array[2].LabelName)); return new LabelInstructionInterpreter(expectedLabels, array, labelValuesDictionary3, createAggregatorFunc).GetAggregator; } default: { string[] array2 = new string[array.Length]; for (int num = 0; num < array.Length; num++) { array2[num] = array[num].LabelName; } ConcurrentDictionary labelValuesDictionary = aggregatorStore.GetLabelValuesDictionary(new StringSequenceMany(array2)); return new LabelInstructionInterpreter(expectedLabels, array, labelValuesDictionary, createAggregatorFunc).GetAggregator; } } } private static LabelInstruction[] Compile(ReadOnlySpan> labels) { LabelInstruction[] array = new LabelInstruction[labels.Length]; for (int i = 0; i < labels.Length; i++) { int num = i; int sourceIndex = i; KeyValuePair keyValuePair = labels[i]; array[num] = new LabelInstruction(sourceIndex, keyValuePair.Key); } return array; } } [SecurityCritical] internal sealed class LabelInstructionInterpreter where TObjectSequence : struct, IObjectSequence, IEquatable where TAggregator : Aggregator { private readonly int _expectedLabelCount; private readonly LabelInstruction[] _instructions; private readonly ConcurrentDictionary _valuesDict; private readonly Func _createAggregator; public LabelInstructionInterpreter(int expectedLabelCount, LabelInstruction[] instructions, ConcurrentDictionary valuesDict, Func createAggregator) { _expectedLabelCount = expectedLabelCount; _instructions = instructions; _valuesDict = valuesDict; _createAggregator = (TObjectSequence _) => createAggregator(); } public bool GetAggregator(ReadOnlySpan> labels, out TAggregator aggregator) { aggregator = null; if (labels.Length != _expectedLabelCount) { return false; } TObjectSequence val = default(TObjectSequence); if (val is ObjectSequenceMany) { val = (TObjectSequence)(object)new ObjectSequenceMany(new object[_expectedLabelCount]); } for (int i = 0; i < _instructions.Length; i++) { LabelInstruction labelInstruction = _instructions[i]; string labelName = labelInstruction.LabelName; KeyValuePair keyValuePair = labels[labelInstruction.SourceIndex]; if (labelName != keyValuePair.Key) { return false; } int i2 = i; keyValuePair = labels[labelInstruction.SourceIndex]; val[i2] = keyValuePair.Value; } if (!_valuesDict.TryGetValue(val, out aggregator)) { aggregator = _createAggregator(val); if (aggregator == null) { return true; } aggregator = _valuesDict.GetOrAdd(val, aggregator); } return true; } } internal sealed class FixedSizeLabelNameDictionary : ConcurrentDictionary> where TStringSequence : IStringSequence, IEquatable where TObjectSequence : IObjectSequence, IEquatable where TAggregator : Aggregator { public void Collect(Action visitFunc) { using IEnumerator>> enumerator = GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair> current = enumerator.Current; TStringSequence key = current.Key; foreach (KeyValuePair item in current.Value) { TObjectSequence key2 = item.Key; KeyValuePair[] array = new KeyValuePair[key.Length]; for (int i = 0; i < array.Length; i++) { array[i] = new KeyValuePair(key[i], key2[i]?.ToString() ?? ""); } IAggregationStatistics stats = item.Value.Collect(); visitFunc(new LabeledAggregationStatistics(stats, array)); } } } public ConcurrentDictionary GetValuesDictionary(in TStringSequence names) { return GetOrAdd(names, (TStringSequence _) => new ConcurrentDictionary()); } } internal sealed class Base2ExponentialHistogramAggregator : Aggregator { private const int MinScale = -11; private const int MaxScale = 20; private const int MinBuckets = 2; private const long FractionMask = 4503599627370495L; private const long ExponentMask = 9218868437227405312L; private const int FractionWidth = 52; private int _scale; private double _maxMeasurement; private double _minMeasurement; private double _sum; private long _count; private bool _reportDeltas; private double _scalingFactor; internal CircularBufferBuckets PositiveBuckets { get; } internal int Scale { get { return _scale; } set { _scale = value; _scalingFactor = BitConverter.Int64BitsToDouble(0x71547652B82FEL | (1023L + (long)value << 52)); } } internal long Count => _count; internal double Sum => _sum; internal double MinMeasurement => _minMeasurement; internal double MaxMeasurement => _maxMeasurement; internal double ScalingFactor => _scalingFactor; internal long ZeroCount { get; private set; } private static ReadOnlySpan LeadingZeroLookupTable => new byte[256] { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; public Base2ExponentialHistogramAggregator(int maxBuckets = 160, int scale = 20, bool reportDeltas = false) { if (scale < -11 || scale > 20) { throw new ArgumentOutOfRangeException("scale", System.SR.Format(System.SR.InvalidHistogramScale, scale, -11, 20)); } if (maxBuckets < 2) { throw new ArgumentOutOfRangeException("maxBuckets", System.SR.Format(System.SR.InvalidHistogramMaxBuckets, maxBuckets, 2)); } Scale = scale; _reportDeltas = reportDeltas; _minMeasurement = double.MaxValue; _maxMeasurement = double.MinValue; PositiveBuckets = new CircularBufferBuckets(maxBuckets); } public override IAggregationStatistics Collect() { lock (this) { Base2ExponentialHistogramStatistics result = new Base2ExponentialHistogramStatistics(Scale, ZeroCount, _sum, _count, _minMeasurement, _maxMeasurement, PositiveBuckets.ToArray()); if (_reportDeltas) { _sum = 0.0; _minMeasurement = double.MaxValue; _maxMeasurement = double.MinValue; ZeroCount = 0L; _count = 0L; PositiveBuckets.Clear(); } return result; } } public override void Update(double measurement) { if (!IsFinite(measurement)) { return; } int num = measurement.CompareTo(0.0); if (num < 0) { return; } lock (this) { _maxMeasurement = Math.Max(_maxMeasurement, measurement); _minMeasurement = Math.Min(_minMeasurement, measurement); _count++; if (num == 0) { ZeroCount++; return; } _sum += measurement; int num2 = MapToIndex(measurement); int num3 = PositiveBuckets.TryIncrement(num2, 1L); if (num3 != 0) { PositiveBuckets.ScaleDown(num3); Scale -= num3; if (Scale < -11) { Scale = -11; } else if (Scale > 20) { Scale = 20; } num3 = PositiveBuckets.TryIncrement(num2 >> num3, 1L); } } } public int MapToIndex(double value) { long num = BitConverter.DoubleToInt64Bits(value); long num2 = num & 0xFFFFFFFFFFFFFL; if (Scale > 0) { if (num2 == 0L) { return ((int)((num & 0x7FF0000000000000L) >> 52) - 1023 << Scale) - 1; } return (int)Math.Ceiling(Math.Log(value) * _scalingFactor) - 1; } int num3 = (int)((num & 0x7FF0000000000000L) >> 52); if (num3 == 0) { num3 -= LeadingZero64(num2 - 1) - 12; } else if (num2 == 0L) { num3--; } return num3 - 1023 >> -Scale; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsFinite(double value) { if (!double.IsInfinity(value)) { return !double.IsNaN(value); } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LeadingZero64(long value) { int num = (int)(value >> 32); if (num != 0) { return LeadingZero32(num); } return LeadingZero32((int)value) + 32; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LeadingZero32(int value) { short num = (short)(value >> 16); if (num != 0) { return LeadingZero16(num); } return LeadingZero16((short)value) + 16; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LeadingZero16(short value) { byte b = (byte)(value >> 8); if (b != 0) { return LeadingZero8(b); } return LeadingZero8((byte)value) + 8; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LeadingZero8(byte value) { return LeadingZeroLookupTable[value]; } } internal sealed class CircularBufferBuckets { private long[] _trait; private int _begin; private int _end = -1; public int Capacity { get; } public int Size => _end - _begin + 1; public long this[int index] => _trait[ModuloIndex(index)]; public CircularBufferBuckets(int capacity) { if (capacity < 1) { throw new ArgumentOutOfRangeException("capacity", "Capacity must be greater than 0."); } Capacity = capacity; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int TryIncrement(int index, long value = 1L) { int capacity = Capacity; if (_trait == null) { _trait = new long[capacity]; _begin = index; _end = index; _trait[ModuloIndex(index)] += value; return 0; } int num = _begin; int num2 = _end; if (index > num2) { num2 = index; } else { if (index >= num) { _trait[ModuloIndex(index)] += value; return 0; } num = index; } int num3 = num2 - num; if (num3 >= capacity || num3 < 0) { return CalculateScaleReduction(num, num2, capacity); } _begin = num; _end = num2; _trait[ModuloIndex(index)] += value; return 0; [MethodImpl(MethodImplOptions.AggressiveInlining)] static int CalculateScaleReduction(int begin, int end, int num6) { int num4 = 0; int num5 = end - begin; while (num5 >= num6 || num5 < 0) { begin >>= 1; end >>= 1; num5 = end - begin; num4++; } return num4; } } public void ScaleDown(int level = 1) { if (_trait == null) { return; } uint capacity = (uint)Capacity; uint num = (uint)ModuloIndex(_begin); int num2 = _begin; int num3 = _end; for (int i = 0; i < level; i++) { int num4 = num2 >> 1; int num5 = num3 >> 1; if (num2 != num3) { if (num2 % 2 == 0) { ScaleDownInternal(_trait, num, num2, num3, capacity); } else { num2++; if (num2 != num3) { ScaleDownInternal(_trait, num + 1, num2, num3, capacity); } } } num2 = num4; num3 = num5; } _begin = num2; _end = num3; if (capacity > 1) { AdjustPosition(_trait, num, (uint)ModuloIndex(num2), (uint)(num3 - num2 + 1), capacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] static void AdjustPosition(long[] array, uint src, uint dst, uint size, uint num7) { uint num6 = (dst + num7 - src) % num7; if (num6 != 0) { if (size - 1 == num6 && num6 << 1 == num7) { Exchange(array, src++, dst++); size -= 2; } else if (num6 < size) { src = src + size - 1; dst = dst + size - 1; while (size-- != 0) { Move(array, src-- % num7, dst-- % num7); } return; } while (size-- != 0) { Move(array, src++ % num7, dst++ % num7); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] static void Consolidate(long[] array, uint src, uint dst) { array[dst] += array[src]; array[src] = 0L; } [MethodImpl(MethodImplOptions.AggressiveInlining)] static void Exchange(long[] array, uint src, uint dst) { long num6 = array[dst]; array[dst] = array[src]; array[src] = num6; } [MethodImpl(MethodImplOptions.AggressiveInlining)] static void Move(long[] array, uint src, uint dst) { array[dst] = array[src]; array[src] = 0L; } [MethodImpl(MethodImplOptions.AggressiveInlining)] static void ScaleDownInternal(long[] array, uint offset, int begin, int end, uint num6) { for (int j = begin + 1; j < end; j++) { Consolidate(array, (uint)((int)offset + (j - begin)) % num6, (uint)((int)offset + ((j >> 1) - (begin >> 1))) % num6); } Consolidate(array, (uint)((int)offset + (end - begin)) % num6, (uint)((int)offset + ((end >> 1) - (begin >> 1))) % num6); } } public long[] ToArray() { int size = Size; if (_trait == null || size <= 0) { return Array.Empty(); } long[] array = new long[size]; for (int i = 0; i < size; i++) { array[i] = _trait[ModuloIndex(_begin + i)]; } return array; } internal void Clear() { if (_trait != null) { Array.Clear(_trait, 0, _trait.Length); } _begin = 0; _end = -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private int ModuloIndex(int value) { return PositiveModulo32(value, Capacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int PositiveModulo32(int value, int divisor) { value %= divisor; if (value < 0) { value += divisor; } return value; } } public sealed class Counter : Instrument where T : struct { internal Counter(Meter meter, string name, string unit, string description) : this(meter, name, unit, description, (IEnumerable>)null) { } internal Counter(Meter meter, string name, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { Publish(); } public void Add(T delta) { RecordMeasurement(delta); } public void Add(T delta, KeyValuePair tag) { RecordMeasurement(delta, tag); } public void Add(T delta, KeyValuePair tag1, KeyValuePair tag2) { RecordMeasurement(delta, tag1, tag2); } public void Add(T delta, KeyValuePair tag1, KeyValuePair tag2, KeyValuePair tag3) { RecordMeasurement(delta, tag1, tag2, tag3); } public void Add(T delta, [ParamCollection] scoped ReadOnlySpan> tags) { RecordMeasurement(delta, tags); } public void Add(T delta, params KeyValuePair[] tags) { RecordMeasurement(delta, tags.AsSpan()); } public void Add(T delta, in TagList tagList) { RecordMeasurement(delta, in tagList); } } internal sealed class QuantileAggregation { public double[] Quantiles { get; set; } public double MaxRelativeError { get; set; } = 0.001; public QuantileAggregation(params double[] quantiles) { Quantiles = quantiles; Array.Sort(Quantiles); } } internal sealed class ExponentialHistogramAggregator : Aggregator { private struct Bucket { public double Value; public int Count; public Bucket(double value, int count) { Value = value; Count = count; } } private const int ExponentArraySize = 4096; private const int ExponentShift = 52; private const double MinRelativeError = 0.0001; private const int PositiveIntAndNan = 2047; private const int NegativeIntAndNan = 4095; private readonly QuantileAggregation _config; private int[][] _counters; private int _count; private double _sum; private readonly int _mantissaMax; private readonly int _mantissaMask; private readonly int _mantissaShift; public ExponentialHistogramAggregator(QuantileAggregation config) { _config = config; _counters = new int[4096][]; if (_config.MaxRelativeError < 0.0001) { throw new ArgumentException(); } int num = (int)Math.Ceiling(Math.Log(1.0 / _config.MaxRelativeError, 2.0)) - 1; _mantissaShift = 52 - num; _mantissaMax = 1 << num; _mantissaMask = _mantissaMax - 1; } public override IAggregationStatistics Collect() { int[][] counters; int count; double sum; lock (this) { counters = _counters; count = _count; sum = _sum; _counters = new int[4096][]; _count = 0; _sum = 0.0; } QuantileValue[] array = new QuantileValue[_config.Quantiles.Length]; int num = 0; if (num == _config.Quantiles.Length) { return new HistogramStatistics(array, count, sum); } int num2 = QuantileToRank(_config.Quantiles[num], count); int num3 = 0; foreach (Bucket item in IterateBuckets(counters)) { num3 += item.Count; while (num3 > num2) { array[num] = new QuantileValue(_config.Quantiles[num], item.Value); num++; if (num == _config.Quantiles.Length) { return new HistogramStatistics(array, count, sum); } num2 = QuantileToRank(_config.Quantiles[num], count); } } return new HistogramStatistics(Array.Empty(), count, sum); } private IEnumerable IterateBuckets(int[][] counters) { for (int exponent = 4094; exponent >= 2048; exponent--) { int[] mantissaCounts = counters[exponent]; if (mantissaCounts != null) { for (int mantissa = _mantissaMax - 1; mantissa >= 0; mantissa--) { int num = mantissaCounts[mantissa]; if (num > 0) { yield return new Bucket(GetBucketCanonicalValue(exponent, mantissa), num); } } } } for (int exponent = 0; exponent < 2047; exponent++) { int[] mantissaCounts = counters[exponent]; if (mantissaCounts == null) { continue; } for (int mantissa = 0; mantissa < _mantissaMax; mantissa++) { int num2 = mantissaCounts[mantissa]; if (num2 > 0) { yield return new Bucket(GetBucketCanonicalValue(exponent, mantissa), num2); } } } } public override void Update(double measurement) { lock (this) { long num = BitConverter.DoubleToInt64Bits(measurement); int num2 = (int)(num >>> 52); int num3 = (int)(num >>> _mantissaShift) & _mantissaMask; ref int[] reference = ref _counters[num2]; if (reference == null) { reference = new int[_mantissaMax]; } reference[num3]++; if (num2 != 2047 && num2 != 4095) { _count++; _sum += measurement; } } } private static int QuantileToRank(double quantile, int count) { return Math.Min(Math.Max(0, (int)(quantile * (double)count)), count - 1); } private double GetBucketCanonicalValue(int exponent, int mantissa) { return BitConverter.Int64BitsToDouble(((long)exponent << 52) | ((long)mantissa << _mantissaShift)); } } public sealed class Gauge : Instrument where T : struct { internal Gauge(Meter meter, string name, string unit, string description) : this(meter, name, unit, description, (IEnumerable>)null) { } internal Gauge(Meter meter, string name, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { Publish(); } public void Record(T value) { RecordMeasurement(value); } public void Record(T value, KeyValuePair tag) { RecordMeasurement(value, tag); } public void Record(T value, KeyValuePair tag1, KeyValuePair tag2) { RecordMeasurement(value, tag1, tag2); } public void Record(T value, KeyValuePair tag1, KeyValuePair tag2, KeyValuePair tag3) { RecordMeasurement(value, tag1, tag2, tag3); } public void Record(T value, [ParamCollection] scoped ReadOnlySpan> tags) { RecordMeasurement(value, tags); } public void Record(T value, params KeyValuePair[] tags) { RecordMeasurement(value, tags.AsSpan()); } public void Record(T value, in TagList tagList) { RecordMeasurement(value, in tagList); } } public sealed class Histogram : Instrument where T : struct { internal Histogram(Meter meter, string name, string unit, string description) : this(meter, name, unit, description, (IEnumerable>)null, (InstrumentAdvice)null) { } internal Histogram(Meter meter, string name, string unit, string description, IEnumerable> tags, InstrumentAdvice advice) : base(meter, name, unit, description, tags, advice) { Publish(); } public void Record(T value) { RecordMeasurement(value); } public void Record(T value, KeyValuePair tag) { RecordMeasurement(value, tag); } public void Record(T value, KeyValuePair tag1, KeyValuePair tag2) { RecordMeasurement(value, tag1, tag2); } public void Record(T value, KeyValuePair tag1, KeyValuePair tag2, KeyValuePair tag3) { RecordMeasurement(value, tag1, tag2, tag3); } public void Record(T value, [ParamCollection] scoped ReadOnlySpan> tags) { RecordMeasurement(value, tags); } public void Record(T value, params KeyValuePair[] tags) { RecordMeasurement(value, tags.AsSpan()); } public void Record(T value, in TagList tagList) { RecordMeasurement(value, in tagList); } } public sealed class InstrumentAdvice where T : struct { private readonly ReadOnlyCollection _HistogramBucketBoundaries; public IReadOnlyList? HistogramBucketBoundaries { get { return _HistogramBucketBoundaries; } init { ExceptionPolyfills.ThrowIfNull(value, "value"); List list = new List(value); if (!IsSortedAndDistinct(list)) { throw new ArgumentException(System.SR.InvalidHistogramExplicitBucketBoundaries, "value"); } _HistogramBucketBoundaries = new ReadOnlyCollection(list); } } public InstrumentAdvice() { Instrument.ValidateTypeParameter(); } private static bool IsSortedAndDistinct(List values) { Comparer comparer = Comparer.Default; for (int i = 1; i < values.Count; i++) { if (comparer.Compare(values[i - 1], values[i]) >= 0) { return false; } } return true; } } public interface IMeterFactory : IDisposable { Meter Create(MeterOptions options); } public abstract class Instrument { internal readonly DiagLinkedList _subscriptions = new DiagLinkedList(); internal static KeyValuePair[] EmptyTags => Array.Empty>(); internal static object SyncObject { get; } = new object(); public Meter Meter { get; } public string Name { get; } public string? Description { get; } public string? Unit { get; } public IEnumerable>? Tags { get; } public bool Enabled => _subscriptions.First != null; public virtual bool IsObservable => false; protected Instrument(Meter meter, string name) : this(meter, name, null, null, null) { } [EditorBrowsable(EditorBrowsableState.Never)] protected Instrument(Meter meter, string name, string? unit, string? description) : this(meter, name, unit, description, null) { } protected Instrument(Meter meter, string name, string? unit = null, string? description = null, IEnumerable>? tags = null) { Meter = meter ?? throw new ArgumentNullException("meter"); Name = name ?? throw new ArgumentNullException("name"); Description = description; Unit = unit; if (tags != null) { List> list = new List>(tags); list.Sort((KeyValuePair left, KeyValuePair right) => string.Compare(left.Key, right.Key, StringComparison.Ordinal)); Tags = list; } } protected void Publish() { if (!System.Diagnostics.Metrics.Meter.IsSupported) { return; } List list = null; lock (SyncObject) { if (Meter.Disposed || !Meter.AddInstrument(this)) { return; } list = MeterListener.GetAllListeners(); } if (list == null) { return; } foreach (MeterListener item in list) { item.InstrumentPublished?.Invoke(this, item); } } internal void NotifyForUnpublishedInstrument() { for (DiagNode diagNode = _subscriptions.First; diagNode != null; diagNode = diagNode.Next) { diagNode.Value.Listener.DisableMeasurementEvents(this); } _subscriptions.Clear(); } internal static void ValidateTypeParameter() { Type typeFromHandle = typeof(T); if (typeFromHandle != typeof(byte) && typeFromHandle != typeof(short) && typeFromHandle != typeof(int) && typeFromHandle != typeof(long) && typeFromHandle != typeof(double) && typeFromHandle != typeof(float) && typeFromHandle != typeof(decimal)) { throw new InvalidOperationException(System.SR.Format(System.SR.UnsupportedType, typeFromHandle)); } } internal object EnableMeasurement(ListenerSubscription subscription, out bool oldStateStored) { oldStateStored = false; if (!_subscriptions.AddIfNotExist(subscription, (ListenerSubscription s1, ListenerSubscription s2) => s1.Listener == s2.Listener)) { ListenerSubscription listenerSubscription = _subscriptions.Remove(subscription, (ListenerSubscription s1, ListenerSubscription s2) => s1.Listener == s2.Listener); _subscriptions.AddIfNotExist(subscription, (ListenerSubscription s1, ListenerSubscription s2) => s1.Listener == s2.Listener); oldStateStored = listenerSubscription.Listener == subscription.Listener; return listenerSubscription.State; } return false; } internal object DisableMeasurements(MeterListener listener) { return _subscriptions.Remove(new ListenerSubscription(listener), (ListenerSubscription s1, ListenerSubscription s2) => s1.Listener == s2.Listener).State; } internal virtual void Observe(MeterListener listener) { throw new InvalidOperationException(); } internal object GetSubscriptionState(MeterListener listener) { for (DiagNode diagNode = _subscriptions.First; diagNode != null; diagNode = diagNode.Next) { if (listener == diagNode.Value.Listener) { return diagNode.Value.State; } } return null; } } [DebuggerDisplay("Name = {Name}, Meter = {Meter.Name}")] public abstract class Instrument : Instrument where T : struct { [ThreadStatic] private static KeyValuePair[] ts_tags; private const int MaxTagsCount = 8; public InstrumentAdvice? Advice { get; } protected Instrument(Meter meter, string name) : this(meter, name, (string?)null, (string?)null, (IEnumerable>?)null, (InstrumentAdvice?)null) { } [EditorBrowsable(EditorBrowsableState.Never)] protected Instrument(Meter meter, string name, string? unit, string? description) : this(meter, name, unit, description, (IEnumerable>?)null, (InstrumentAdvice?)null) { } [EditorBrowsable(EditorBrowsableState.Never)] protected Instrument(Meter meter, string name, string? unit, string? description, IEnumerable>? tags) : this(meter, name, unit, description, tags, (InstrumentAdvice?)null) { } protected Instrument(Meter meter, string name, string? unit = null, string? description = null, IEnumerable>? tags = null, InstrumentAdvice? advice = null) : base(meter, name, unit, description, tags) { Advice = advice; Instrument.ValidateTypeParameter(); } protected void RecordMeasurement(T measurement) { RecordMeasurement(measurement, Instrument.EmptyTags.AsSpan()); } protected void RecordMeasurement(T measurement, ReadOnlySpan> tags) { for (DiagNode diagNode = _subscriptions.First; diagNode != null; diagNode = diagNode.Next) { diagNode.Value.Listener.NotifyMeasurement(this, measurement, tags, diagNode.Value.State); } } protected void RecordMeasurement(T measurement, KeyValuePair tag) { KeyValuePair[] array = ts_tags ?? new KeyValuePair[8]; ts_tags = null; array[0] = tag; RecordMeasurement(measurement, array.AsSpan(0, 1)); ts_tags = array; } protected void RecordMeasurement(T measurement, KeyValuePair tag1, KeyValuePair tag2) { KeyValuePair[] array = ts_tags ?? new KeyValuePair[8]; ts_tags = null; array[0] = tag1; array[1] = tag2; RecordMeasurement(measurement, array.AsSpan(0, 2)); ts_tags = array; } protected void RecordMeasurement(T measurement, KeyValuePair tag1, KeyValuePair tag2, KeyValuePair tag3) { KeyValuePair[] array = ts_tags ?? new KeyValuePair[8]; ts_tags = null; array[0] = tag1; array[1] = tag2; array[2] = tag3; RecordMeasurement(measurement, array.AsSpan(0, 3)); ts_tags = array; } protected void RecordMeasurement(T measurement, in TagList tagList) { KeyValuePair[] tags = tagList.Tags; if (tags != null) { RecordMeasurement(measurement, tags.AsSpan(0, tagList.Count)); return; } tags = ts_tags ?? new KeyValuePair[8]; switch (tagList.Count) { default: return; case 8: tags[7] = tagList.Tag8; goto case 7; case 7: tags[6] = tagList.Tag7; goto case 6; case 6: tags[5] = tagList.Tag6; goto case 5; case 5: tags[4] = tagList.Tag5; goto case 4; case 4: tags[3] = tagList.Tag4; goto case 3; case 3: tags[2] = tagList.Tag3; goto case 2; case 2: tags[1] = tagList.Tag2; goto case 1; case 1: tags[0] = tagList.Tag1; break; case 0: break; } ts_tags = null; RecordMeasurement(measurement, tags.AsSpan(0, tagList.Count)); ts_tags = tags; } } internal abstract class InstrumentState { public abstract int ID { get; } [SecuritySafeCritical] public abstract void Update(double measurement, ReadOnlySpan> labels); public abstract void Collect(Instrument instrument, Action aggregationVisitFunc); } internal sealed class InstrumentState : InstrumentState where TAggregator : Aggregator { private AggregatorStore _aggregatorStore; private static int s_idCounter; public override int ID { get; } public InstrumentState(Func createAggregatorFunc) { ID = Interlocked.Increment(ref s_idCounter); _aggregatorStore = new AggregatorStore(createAggregatorFunc); } public override void Collect(Instrument instrument, Action aggregationVisitFunc) { _aggregatorStore.Collect(aggregationVisitFunc); } [SecuritySafeCritical] public override void Update(double measurement, ReadOnlySpan> labels) { _aggregatorStore.GetAggregator(labels)?.Update(measurement); } } internal sealed class LastValue : Aggregator { private double? _lastValue; public override void Update(double value) { _lastValue = value; } public override IAggregationStatistics Collect() { lock (this) { LastValueStatistics result = new LastValueStatistics(_lastValue); _lastValue = null; return result; } } } internal sealed class LastValueStatistics : IAggregationStatistics { public double? LastValue { get; } internal LastValueStatistics(double? lastValue) { LastValue = lastValue; } } internal sealed class SynchronousLastValue : Aggregator { private double _lastValue; public override void Update(double value) { Volatile.Write(ref _lastValue, value); } public override IAggregationStatistics Collect() { return new SynchronousLastValueStatistics(Volatile.Read(in _lastValue)); } } internal sealed class SynchronousLastValueStatistics : IAggregationStatistics { public double LastValue { get; } internal SynchronousLastValueStatistics(double lastValue) { LastValue = lastValue; } } public readonly struct Measurement where T : struct { private readonly KeyValuePair[] _tags; public ReadOnlySpan> Tags => _tags.AsSpan(); public T Value { get; } public Measurement(T value) { _tags = Instrument.EmptyTags; Value = value; } public Measurement(T value, IEnumerable>? tags) { _tags = tags?.ToArray() ?? Instrument.EmptyTags; Value = value; } public Measurement(T value, params KeyValuePair[]? tags) { if (tags != null) { _tags = new KeyValuePair[tags.Length]; tags.CopyTo(_tags, 0); } else { _tags = Instrument.EmptyTags; } Value = value; } public Measurement(T value, [ParamCollection] scoped ReadOnlySpan> tags) { _tags = tags.ToArray(); Value = value; } public Measurement(T value, in TagList tags) { if (tags.Count > 0) { _tags = new KeyValuePair[tags.Count]; tags.CopyTo(_tags.AsSpan()); } else { _tags = Instrument.EmptyTags; } Value = value; } } [DebuggerDisplay("Name = {Name}, Instruments = {_instruments.Count}")] public class Meter : IDisposable { private static readonly List s_allMeters = new List(); private List _instruments = new List(); private Dictionary> _nonObservableInstrumentsCache = new Dictionary>(); internal bool Disposed { get; private set; } [FeatureSwitchDefinition("System.Diagnostics.Metrics.Meter.IsSupported")] internal static bool IsSupported { get; } = InitializeIsSupported(); public string Name { get; private set; } public string? Version { get; private set; } public IEnumerable>? Tags { get; private set; } public object? Scope { get; private set; } public string? TelemetrySchemaUrl { get; private set; } private static bool InitializeIsSupported() { if (!AppContext.TryGetSwitch("System.Diagnostics.Metrics.Meter.IsSupported", out var isEnabled)) { return true; } return isEnabled; } public Meter(MeterOptions options) { ExceptionPolyfills.ThrowIfNull(options, "options"); Initialize(options.Name, options.Version, options.Tags, options.Scope, options.TelemetrySchemaUrl); } public Meter(string name) : this(name, null, null) { } public Meter(string name, string? version) : this(name, version, null) { } public Meter(string name, string? version, IEnumerable>? tags, object? scope = null) { Initialize(name, version, tags, scope); } private void Initialize(string name, string version, IEnumerable> tags, object scope = null, string telemetrySchemaUrl = null) { Name = name ?? throw new ArgumentNullException("name"); Version = version; if (tags != null) { List> list = new List>(tags); list.Sort((KeyValuePair left, KeyValuePair right) => string.Compare(left.Key, right.Key, StringComparison.Ordinal)); Tags = list.AsReadOnly(); } Scope = scope; TelemetrySchemaUrl = telemetrySchemaUrl; if (IsSupported) { lock (Instrument.SyncObject) { s_allMeters.Add(this); } GC.KeepAlive(MetricsEventSource.Log); } } public Counter CreateCounter(string name, string? unit = null, string? description = null) where T : struct { return CreateCounter(name, unit, description, null); } public Counter CreateCounter(string name, string? unit, string? description, IEnumerable>? tags) where T : struct { return (Counter)GetOrCreateInstrument(typeof(Counter), name, unit, description, tags, () => new Counter(this, name, unit, description, tags)); } public Gauge CreateGauge(string name) where T : struct { return CreateGauge(name, null, null, null); } public Gauge CreateGauge(string name, string? unit = null, string? description = null, IEnumerable>? tags = null) where T : struct { return (Gauge)GetOrCreateInstrument(typeof(Gauge), name, unit, description, tags, () => new Gauge(this, name, unit, description, tags)); } public Histogram CreateHistogram(string name) where T : struct { return CreateHistogram(name, null, null, null, null); } [EditorBrowsable(EditorBrowsableState.Never)] public Histogram CreateHistogram(string name, string? unit, string? description) where T : struct { return CreateHistogram(name, unit, description, null, null); } [EditorBrowsable(EditorBrowsableState.Never)] public Histogram CreateHistogram(string name, string? unit, string? description, IEnumerable>? tags) where T : struct { return CreateHistogram(name, unit, description, tags, null); } public Histogram CreateHistogram(string name, string? unit = null, string? description = null, IEnumerable>? tags = null, InstrumentAdvice? advice = null) where T : struct { return (Histogram)GetOrCreateInstrument(typeof(Histogram), name, unit, description, tags, () => new Histogram(this, name, unit, description, tags, advice)); } public UpDownCounter CreateUpDownCounter(string name, string? unit = null, string? description = null) where T : struct { return CreateUpDownCounter(name, unit, description, null); } public UpDownCounter CreateUpDownCounter(string name, string? unit, string? description, IEnumerable>? tags) where T : struct { return (UpDownCounter)GetOrCreateInstrument(typeof(UpDownCounter), name, unit, description, tags, () => new UpDownCounter(this, name, unit, description, tags)); } public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func observeValue, string? unit = null, string? description = null) where T : struct { return new ObservableUpDownCounter(this, name, observeValue, unit, description, null); } public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func observeValue, string? unit, string? description, IEnumerable>? tags) where T : struct { return new ObservableUpDownCounter(this, name, observeValue, unit, description, tags); } public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func> observeValue, string? unit = null, string? description = null) where T : struct { return new ObservableUpDownCounter(this, name, observeValue, unit, description, null); } public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func> observeValue, string? unit, string? description, IEnumerable>? tags) where T : struct { return new ObservableUpDownCounter(this, name, observeValue, unit, description, tags); } public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func>> observeValues, string? unit = null, string? description = null) where T : struct { return new ObservableUpDownCounter(this, name, observeValues, unit, description, null); } public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func>> observeValues, string? unit, string? description, IEnumerable>? tags) where T : struct { return new ObservableUpDownCounter(this, name, observeValues, unit, description, tags); } public ObservableCounter CreateObservableCounter(string name, Func observeValue, string? unit = null, string? description = null) where T : struct { return new ObservableCounter(this, name, observeValue, unit, description, null); } public ObservableCounter CreateObservableCounter(string name, Func observeValue, string? unit, string? description, IEnumerable>? tags) where T : struct { return new ObservableCounter(this, name, observeValue, unit, description, tags); } public ObservableCounter CreateObservableCounter(string name, Func> observeValue, string? unit = null, string? description = null) where T : struct { return new ObservableCounter(this, name, observeValue, unit, description, null); } public ObservableCounter CreateObservableCounter(string name, Func> observeValue, string? unit, string? description, IEnumerable>? tags) where T : struct { return new ObservableCounter(this, name, observeValue, unit, description, tags); } public ObservableCounter CreateObservableCounter(string name, Func>> observeValues, string? unit = null, string? description = null) where T : struct { return new ObservableCounter(this, name, observeValues, unit, description, null); } public ObservableCounter CreateObservableCounter(string name, Func>> observeValues, string? unit, string? description, IEnumerable>? tags) where T : struct { return new ObservableCounter(this, name, observeValues, unit, description, tags); } public ObservableGauge CreateObservableGauge(string name, Func observeValue, string? unit = null, string? description = null) where T : struct { return new ObservableGauge(this, name, observeValue, unit, description, null); } public ObservableGauge CreateObservableGauge(string name, Func observeValue, string? unit, string? description, IEnumerable>? tags) where T : struct { return new ObservableGauge(this, name, observeValue, unit, description, tags); } public ObservableGauge CreateObservableGauge(string name, Func> observeValue, string? unit = null, string? description = null) where T : struct { return new ObservableGauge(this, name, observeValue, unit, description, null); } public ObservableGauge CreateObservableGauge(string name, Func> observeValue, string? unit, string? description, IEnumerable>? tags) where T : struct { return new ObservableGauge(this, name, observeValue, unit, description, tags); } public ObservableGauge CreateObservableGauge(string name, Func>> observeValues, string? unit = null, string? description = null) where T : struct { return new ObservableGauge(this, name, observeValues, unit, description, null); } public ObservableGauge CreateObservableGauge(string name, Func>> observeValues, string? unit, string? description, IEnumerable>? tags) where T : struct { return new ObservableGauge(this, name, observeValues, unit, description, tags); } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { if (!disposing) { return; } List list = null; lock (Instrument.SyncObject) { if (Disposed) { return; } Disposed = true; s_allMeters.Remove(this); list = _instruments; _instruments = new List(); } lock (_nonObservableInstrumentsCache) { _nonObservableInstrumentsCache.Clear(); } if (list == null) { return; } foreach (Instrument item in list) { item.NotifyForUnpublishedInstrument(); } } private static Instrument GetCachedInstrument(List instrumentList, Type instrumentType, string unit, string description, IEnumerable> tags) { foreach (Instrument instrument in instrumentList) { if (instrument.GetType() == instrumentType && instrument.Unit == unit && instrument.Description == description && DiagnosticsHelper.CompareTags(instrument.Tags as List>, tags)) { return instrument; } } return null; } private Instrument GetOrCreateInstrument(Type instrumentType, string name, string unit, string description, IEnumerable> tags, Func instrumentCreator) { List value; lock (_nonObservableInstrumentsCache) { if (!_nonObservableInstrumentsCache.TryGetValue(name, out value)) { value = new List(); _nonObservableInstrumentsCache.Add(name, value); } } lock (value) { Instrument cachedInstrument = GetCachedInstrument(value, instrumentType, unit, description, tags); if (cachedInstrument != null) { return cachedInstrument; } } Instrument instrument = instrumentCreator(); lock (value) { Instrument cachedInstrument2 = GetCachedInstrument(value, instrumentType, unit, description, tags); if (cachedInstrument2 != null) { return cachedInstrument2; } value.Add(instrument); return instrument; } } internal bool AddInstrument(Instrument instrument) { if (!_instruments.Contains(instrument)) { _instruments.Add(instrument); return true; } return false; } internal static List GetPublishedInstruments() { List list = null; if (s_allMeters.Count > 0) { list = new List(); foreach (Meter s_allMeter in s_allMeters) { foreach (Instrument instrument in s_allMeter._instruments) { list.Add(instrument); } } } return list; } } public static class MeterFactoryExtensions { public static Meter Create(this IMeterFactory meterFactory, string name, string? version = null, IEnumerable>? tags = null) { ExceptionPolyfills.ThrowIfNull(meterFactory, "meterFactory"); return meterFactory.Create(new MeterOptions(name) { Version = version, Tags = tags, Scope = meterFactory }); } } public delegate void MeasurementCallback(Instrument instrument, T measurement, ReadOnlySpan> tags, object? state) where T : struct; public sealed class MeterListener : IDisposable { private static readonly List s_allStartedListeners = new List(); private readonly DiagLinkedList _enabledMeasurementInstruments = new DiagLinkedList(); private bool _disposed; private MeasurementCallback _byteMeasurementCallback = delegate { }; private MeasurementCallback _shortMeasurementCallback = delegate { }; private MeasurementCallback _intMeasurementCallback = delegate { }; private MeasurementCallback _longMeasurementCallback = delegate { }; private MeasurementCallback _floatMeasurementCallback = delegate { }; private MeasurementCallback _doubleMeasurementCallback = delegate { }; private MeasurementCallback _decimalMeasurementCallback = delegate { }; public Action? InstrumentPublished { get; set; } public Action? MeasurementsCompleted { get; set; } public void EnableMeasurementEvents(Instrument instrument, object? state = null) { if (!Meter.IsSupported) { return; } bool oldStateStored = false; bool flag = false; object arg = null; lock (Instrument.SyncObject) { if (instrument != null && !_disposed && !instrument.Meter.Disposed) { _enabledMeasurementInstruments.AddIfNotExist(instrument, object.ReferenceEquals); arg = instrument.EnableMeasurement(new ListenerSubscription(this, state), out oldStateStored); flag = true; } } if (flag) { if (oldStateStored && MeasurementsCompleted != null) { MeasurementsCompleted?.Invoke(instrument, arg); } } else { MeasurementsCompleted?.Invoke(instrument, state); } } public object? DisableMeasurementEvents(Instrument instrument) { if (!Meter.IsSupported) { return null; } object obj = null; lock (Instrument.SyncObject) { if (instrument == null || _enabledMeasurementInstruments.Remove(instrument, object.ReferenceEquals) == null) { return null; } obj = instrument.DisableMeasurements(this); } MeasurementsCompleted?.Invoke(instrument, obj); return obj; } public void SetMeasurementEventCallback(MeasurementCallback? measurementCallback) where T : struct { if (!Meter.IsSupported) { return; } if (measurementCallback == null) { measurementCallback = delegate { }; } if (typeof(T) == typeof(byte)) { _byteMeasurementCallback = (MeasurementCallback)(object)measurementCallback; return; } if (typeof(T) == typeof(int)) { _intMeasurementCallback = (MeasurementCallback)(object)measurementCallback; return; } if (typeof(T) == typeof(float)) { _floatMeasurementCallback = (MeasurementCallback)(object)measurementCallback; return; } if (typeof(T) == typeof(double)) { _doubleMeasurementCallback = (MeasurementCallback)(object)measurementCallback; return; } if (typeof(T) == typeof(decimal)) { _decimalMeasurementCallback = (MeasurementCallback)(object)measurementCallback; return; } if (typeof(T) == typeof(short)) { _shortMeasurementCallback = (MeasurementCallback)(object)measurementCallback; return; } if (typeof(T) == typeof(long)) { _longMeasurementCallback = (MeasurementCallback)(object)measurementCallback; return; } throw new InvalidOperationException(System.SR.Format(System.SR.UnsupportedType, typeof(T))); } public void Start() { if (!Meter.IsSupported) { return; } List list = null; lock (Instrument.SyncObject) { if (_disposed) { return; } if (!s_allStartedListeners.Contains(this)) { s_allStartedListeners.Add(this); list = Meter.GetPublishedInstruments(); } } if (list == null) { return; } foreach (Instrument item in list) { InstrumentPublished?.Invoke(item, this); } } public void RecordObservableInstruments() { if (!Meter.IsSupported) { return; } List list = null; for (DiagNode diagNode = _enabledMeasurementInstruments.First; diagNode != null; diagNode = diagNode.Next) { if (diagNode.Value.IsObservable) { try { diagNode.Value.Observe(this); } catch (Exception item) { if (list == null) { list = new List(); } list.Add(item); } } } if (list == null) { return; } throw new AggregateException(list); } public void Dispose() { if (!Meter.IsSupported) { return; } Dictionary dictionary = null; Action measurementsCompleted = MeasurementsCompleted; lock (Instrument.SyncObject) { if (_disposed) { return; } _disposed = true; s_allStartedListeners.Remove(this); DiagNode diagNode = _enabledMeasurementInstruments.First; if (diagNode != null) { if (measurementsCompleted != null) { dictionary = new Dictionary(); } do { object value = diagNode.Value.DisableMeasurements(this); dictionary?.Add(diagNode.Value, value); diagNode = diagNode.Next; } while (diagNode != null); _enabledMeasurementInstruments.Clear(); } } if (dictionary == null) { return; } foreach (KeyValuePair item in dictionary) { measurementsCompleted?.Invoke(item.Key, item.Value); } } internal static List GetAllListeners() { if (s_allStartedListeners.Count != 0) { return new List(s_allStartedListeners); } return null; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void NotifyMeasurement(Instrument instrument, T measurement, ReadOnlySpan> tags, object state) where T : struct { if (typeof(T) == typeof(byte)) { _byteMeasurementCallback(instrument, (byte)(object)measurement, tags, state); } if (typeof(T) == typeof(short)) { _shortMeasurementCallback(instrument, (short)(object)measurement, tags, state); } if (typeof(T) == typeof(int)) { _intMeasurementCallback(instrument, (int)(object)measurement, tags, state); } if (typeof(T) == typeof(long)) { _longMeasurementCallback(instrument, (long)(object)measurement, tags, state); } if (typeof(T) == typeof(float)) { _floatMeasurementCallback(instrument, (float)(object)measurement, tags, state); } if (typeof(T) == typeof(double)) { _doubleMeasurementCallback(instrument, (double)(object)measurement, tags, state); } if (typeof(T) == typeof(decimal)) { _decimalMeasurementCallback(instrument, (decimal)(object)measurement, tags, state); } } } internal readonly struct ListenerSubscription { internal MeterListener Listener { get; } internal object State { get; } internal ListenerSubscription(MeterListener listener, object state = null) { Listener = listener; State = state; } } [EventSource(Name = "System.Diagnostics.Metrics")] internal sealed class MetricsEventSource : EventSource { public static class Keywords { public const EventKeywords Messages = (EventKeywords)1L; public const EventKeywords TimeSeriesValues = (EventKeywords)2L; public const EventKeywords InstrumentPublishing = (EventKeywords)4L; } private sealed class CommandHandler { private AggregationManager _aggregationManager; private string _sessionId = ""; private HashSet _sharedSessionClientIds = new HashSet(); private int _sharedSessionRefCount; private bool _disabledRefCount; private static readonly char[] s_instrumentSeparators = new char[4] { '\r', '\n', ',', ';' }; private readonly char[] Base2ExponentialHistogramSpecSeparators = new char[1] { ';' }; private const char HistogramPartSeparator = '='; public MetricsEventSource Parent { get; } public CommandHandler(MetricsEventSource parent) { Parent = parent; } public bool IsSharedSession(string commandSessionId) { if (_sessionId.Equals("SHARED")) { if (!string.IsNullOrEmpty(commandSessionId)) { return commandSessionId.Equals("SHARED"); } return true; } return false; } public void OnEventCommand(EventCommandEventArgs command) { try { string sessionId = GetSessionId(command); if ((command.Command == EventCommand.Update || command.Command == EventCommand.Disable || command.Command == EventCommand.Enable) && _aggregationManager != null) { if (command.Command == EventCommand.Update || command.Command == EventCommand.Enable) { IncrementRefCount(sessionId, command); } if (IsSharedSession(sessionId)) { if (ShouldDisable(command.Command)) { Parent.Message("Previous session with id " + _sessionId + " is stopped"); _aggregationManager.Dispose(); _aggregationManager = null; _sessionId = string.Empty; _sharedSessionClientIds.Clear(); return; } bool flag = true; double refreshIntervalSeconds; lock (_aggregationManager) { flag = SetSharedRefreshIntervalSecs(command.Arguments, _aggregationManager.CollectionPeriod.TotalSeconds, out refreshIntervalSeconds) && flag; } flag = SetSharedMaxHistograms(command.Arguments, _aggregationManager.MaxHistograms, out var maxHistograms) && flag; flag = SetSharedMaxTimeSeries(command.Arguments, _aggregationManager.MaxTimeSeries, out var maxTimeSeries) && flag; if (command.Command != EventCommand.Disable) { string value; if (flag) { if (ParseMetrics(command.Arguments, out var metricsSpecs)) { ParseSpecs(metricsSpecs); _aggregationManager.Update(); } if (ParseBase2ExponentialHistogramSpecs(command.Arguments, out var base2ExponentialHistogramSpec)) { ParseBase2ExponentialHistogram(base2ExponentialHistogramSpec); } } else if (command.Arguments.TryGetValue("ClientId", out value)) { lock (_aggregationManager) { Parent.MultipleSessionsConfiguredIncorrectlyError(value, _aggregationManager.MaxHistograms.ToString(), maxHistograms.ToString(), _aggregationManager.MaxTimeSeries.ToString(), maxTimeSeries.ToString(), _aggregationManager.CollectionPeriod.TotalSeconds.ToString(), refreshIntervalSeconds.ToString()); return; } } return; } } else { if (command.Command == EventCommand.Enable || command.Command == EventCommand.Update) { Parent.MultipleSessionsNotSupportedError(_sessionId); return; } if (ShouldDisable(command.Command)) { Parent.Message("Previous session with id " + _sessionId + " is stopped"); _aggregationManager.Dispose(); _aggregationManager = null; _sessionId = string.Empty; _sharedSessionClientIds.Clear(); return; } } } if ((command.Command == EventCommand.Update || command.Command == EventCommand.Enable) && command.Arguments != null) { IncrementRefCount(sessionId, command); _sessionId = sessionId; double defaultValue = 1.0; SetRefreshIntervalSecs(command.Arguments, 0.1, defaultValue, out var refreshIntervalSeconds2); SetUniqueMaxTimeSeries(command.Arguments, 1000, out var maxTimeSeries2); SetUniqueMaxHistograms(command.Arguments, 20, out var maxHistograms2); string sessionId2 = _sessionId; _aggregationManager = new AggregationManager(maxTimeSeries2, maxHistograms2, delegate(Instrument i, LabeledAggregationStatistics s, InstrumentState state) { TransmitMetricValue(i, s, sessionId2, state); }, delegate(DateTime startIntervalTime, DateTime endIntervalTime) { Parent.CollectionStart(sessionId2, startIntervalTime, endIntervalTime); }, delegate(DateTime startIntervalTime, DateTime endIntervalTime) { Parent.CollectionStop(sessionId2, startIntervalTime, endIntervalTime); }, delegate(Instrument i, InstrumentState state) { Parent.BeginInstrumentReporting(sessionId2, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description, Helpers.FormatTags(i.Tags), Helpers.FormatTags(i.Meter.Tags), Helpers.FormatObjectHash(i.Meter.Scope), state.ID, i.Meter.TelemetrySchemaUrl); }, delegate(Instrument i, InstrumentState state) { Parent.EndInstrumentReporting(sessionId2, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description, Helpers.FormatTags(i.Tags), Helpers.FormatTags(i.Meter.Tags), Helpers.FormatObjectHash(i.Meter.Scope), state.ID, i.Meter.TelemetrySchemaUrl); }, delegate(Instrument i, InstrumentState state) { Parent.InstrumentPublished(sessionId2, i.Meter.Name, i.Meter.Version, i.Name, i.GetType().Name, i.Unit, i.Description, Helpers.FormatTags(i.Tags), Helpers.FormatTags(i.Meter.Tags), Helpers.FormatObjectHash(i.Meter.Scope), state?.ID ?? 0, i.Meter.TelemetrySchemaUrl); }, delegate { Parent.InitialInstrumentEnumerationComplete(sessionId2); }, delegate(Exception ex) { Parent.Error(sessionId2, ex.ToString()); }, delegate { Parent.TimeSeriesLimitReached(sessionId2); }, delegate { Parent.HistogramLimitReached(sessionId2); }, delegate(Exception ex) { Parent.ObservableInstrumentCallbackError(sessionId2, ex.ToString()); }); _aggregationManager.SetCollectionPeriod(TimeSpan.FromSeconds(refreshIntervalSeconds2)); if (ParseMetrics(command.Arguments, out var metricsSpecs2)) { ParseSpecs(metricsSpecs2); } if (ParseBase2ExponentialHistogramSpecs(command.Arguments, out var base2ExponentialHistogramSpec2)) { ParseBase2ExponentialHistogram(base2ExponentialHistogramSpec2); } _aggregationManager.Start(); } } catch (Exception e) when (LogError(e)) { } } private bool ShouldDisable(EventCommand command) { if (command == EventCommand.Disable) { if (_disabledRefCount || Interlocked.Decrement(ref _sharedSessionRefCount) != 0) { return !Parent.IsEnabled(); } return true; } return false; } private bool ParseMetrics(IDictionary arguments, out string metricsSpecs) { if (arguments.TryGetValue("Metrics", out metricsSpecs)) { Parent.Message("Metrics argument received: " + metricsSpecs); return true; } Parent.Message("No Metrics argument received"); return false; } private bool ParseBase2ExponentialHistogramSpecs(IDictionary arguments, out string base2ExponentialHistogramSpec) { if (arguments.TryGetValue("Base2ExponentialHistogram", out base2ExponentialHistogramSpec)) { Parent.Message("Histogram Aggregation argument received: " + base2ExponentialHistogramSpec); return true; } Parent.Message("No Histogram Aggregation argument received"); return false; } private void InvalidateRefCounting() { _disabledRefCount = true; Parent.Message("ClientId not provided; session will remain active indefinitely."); } private void IncrementRefCount(string clientId, EventCommandEventArgs command) { if (clientId.Equals("SHARED")) { if (command.Arguments.TryGetValue("ClientId", out string value) && !string.IsNullOrEmpty(value)) { clientId = value; } else { InvalidateRefCounting(); } } if (_sharedSessionClientIds.Add(clientId)) { Interlocked.Increment(ref _sharedSessionRefCount); } } private bool SetSharedMaxTimeSeries(IDictionary arguments, int sharedValue, out int maxTimeSeries) { return SetMaxValue(arguments, "MaxTimeSeries", "shared value", sharedValue, out maxTimeSeries); } private void SetUniqueMaxTimeSeries(IDictionary arguments, int defaultValue, out int maxTimeSeries) { SetMaxValue(arguments, "MaxTimeSeries", "default", defaultValue, out maxTimeSeries); } private bool SetSharedMaxHistograms(IDictionary arguments, int sharedValue, out int maxHistograms) { return SetMaxValue(arguments, "MaxHistograms", "shared value", sharedValue, out maxHistograms); } private void SetUniqueMaxHistograms(IDictionary arguments, int defaultValue, out int maxHistograms) { SetMaxValue(arguments, "MaxHistograms", "default", defaultValue, out maxHistograms); } private bool SetMaxValue(IDictionary arguments, string argumentsKey, string valueDescriptor, int defaultValue, out int maxValue) { if (arguments.TryGetValue(argumentsKey, out var value)) { Parent.Message(argumentsKey + " argument received: " + value); if (!int.TryParse(value, out maxValue)) { Parent.Message($"Failed to parse {argumentsKey}. Using {valueDescriptor} {defaultValue}"); maxValue = defaultValue; } else if (maxValue != defaultValue) { return false; } } else { Parent.Message($"No {argumentsKey} argument received. Using {valueDescriptor} {defaultValue}"); maxValue = defaultValue; } return true; } private void SetRefreshIntervalSecs(IDictionary arguments, double minValue, double defaultValue, out double refreshIntervalSeconds) { if (GetRefreshIntervalSecs(arguments, "default", defaultValue, out refreshIntervalSeconds) && refreshIntervalSeconds < minValue) { Parent.Message(string.Format("{0} too small. Using minimum interval {1} seconds.", "RefreshInterval", minValue)); refreshIntervalSeconds = minValue; } } private bool SetSharedRefreshIntervalSecs(IDictionary arguments, double sharedValue, out double refreshIntervalSeconds) { if (GetRefreshIntervalSecs(arguments, "shared value", sharedValue, out refreshIntervalSeconds) && refreshIntervalSeconds != sharedValue) { return false; } return true; } private bool GetRefreshIntervalSecs(IDictionary arguments, string valueDescriptor, double defaultValue, out double refreshIntervalSeconds) { if (arguments.TryGetValue("RefreshInterval", out var value)) { Parent.Message("RefreshInterval argument received: " + value); if (!double.TryParse(value, out refreshIntervalSeconds)) { Parent.Message(string.Format("Failed to parse {0}. Using {1} {2}s.", "RefreshInterval", valueDescriptor, defaultValue)); refreshIntervalSeconds = defaultValue; return false; } return true; } Parent.Message(string.Format("No {0} argument received. Using {1} {2}s.", "RefreshInterval", valueDescriptor, defaultValue)); refreshIntervalSeconds = defaultValue; return false; } private string GetSessionId(EventCommandEventArgs command) { if (command.Arguments.TryGetValue("SessionId", out string value)) { Parent.Message("SessionId argument received: " + value); return value; } string text = string.Empty; if (command.Command != EventCommand.Disable) { text = Guid.NewGuid().ToString(); Parent.Message("New session started. SessionId auto-generated: " + text); } return text; } private bool LogError(Exception e) { Parent.Error(_sessionId, e.ToString()); return false; } private void ParseSpecs(string metricsSpecs) { if (metricsSpecs == null) { return; } string[] array = metricsSpecs.Split(s_instrumentSeparators, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { MetricSpec metricSpec = MetricSpec.Parse(array[i]); Parent.Message($"Parsed metric: {metricSpec}"); if (metricSpec.InstrumentName != null) { _aggregationManager.Include(metricSpec.MeterName, metricSpec.InstrumentName); } else if (metricSpec.MeterName.Length > 0 && metricSpec.MeterName[metricSpec.MeterName.Length - 1] == '*') { if (metricSpec.MeterName.Length == 1) { _aggregationManager.IncludeAll(); } else { _aggregationManager.IncludePrefix(metricSpec.MeterName.Substring(0, metricSpec.MeterName.Length - 1)); } } else { _aggregationManager.Include(metricSpec.MeterName); } } } private void ParseBase2ExponentialHistogram(string base2ExponentialHistogramSpec) { if (base2ExponentialHistogramSpec == null) { return; } string[] array = base2ExponentialHistogramSpec.Split(Base2ExponentialHistogramSpecSeparators, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { Parent.Message("No histogram aggregation spec is provided"); return; } int scale = 20; int maxBuckets = 160; bool reportDeltas = false; string[] array2 = array; foreach (string text in array2) { int num = text.IndexOf('='); if (num < 0) { Parent.Message("Invalid histogram aggregation spec: " + text); continue; } ReadOnlySpan span = text.AsSpan(0, num).Trim(); ReadOnlySpan span2 = text.AsSpan(num + 1).Trim(); if (MemoryExtensions.Equals(span, "scale".AsSpan(), StringComparison.OrdinalIgnoreCase)) { if (!int.TryParse(span2.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result < -11 || result > 20) { Parent.Message("Invalid scale value: " + text); } else { scale = result; } } else if (MemoryExtensions.Equals(span, "maxBuckets".AsSpan(), StringComparison.OrdinalIgnoreCase)) { if (!int.TryParse(span2.ToString(), NumberStyles.None, CultureInfo.InvariantCulture, out var result2) || result2 < 2) { Parent.Message("Invalid maxBuckets value: " + text); } else { maxBuckets = result2; } } else if (MemoryExtensions.Equals(span, "reportDeltas".AsSpan(), StringComparison.OrdinalIgnoreCase)) { if (MemoryExtensions.Equals(span2, "true".AsSpan(), StringComparison.OrdinalIgnoreCase)) { reportDeltas = true; } else if (MemoryExtensions.Equals(span2, "false".AsSpan(), StringComparison.OrdinalIgnoreCase)) { reportDeltas = false; } else { Parent.Message("Invalid reportDeltas value: " + text); } } } _aggregationManager.SetHistogramAggregation(() => new Base2ExponentialHistogramAggregator(maxBuckets, scale, reportDeltas)); } private static void TransmitMetricValue(Instrument instrument, LabeledAggregationStatistics stats, string sessionId, InstrumentState instrumentState) { int instrumentId = instrumentState?.ID ?? 0; if (stats.AggregationStatistics is CounterStatistics counterStatistics) { if (counterStatistics.IsMonotonic) { Log.CounterRateValuePublished(sessionId, instrument.Meter.Name, instrument.Meter.Version, instrument.Name, instrument.Unit, Helpers.FormatTags(stats.Labels), counterStatistics.Delta.HasValue ? counterStatistics.Delta.Value.ToString(CultureInfo.InvariantCulture) : "", counterStatistics.Value.ToString(CultureInfo.InvariantCulture), instrumentId); } else { Log.UpDownCounterRateValuePublished(sessionId, instrument.Meter.Name, instrument.Meter.Version, instrument.Name, instrument.Unit, Helpers.FormatTags(stats.Labels), counterStatistics.Delta.HasValue ? counterStatistics.Delta.Value.ToString(CultureInfo.InvariantCulture) : "", counterStatistics.Value.ToString(CultureInfo.InvariantCulture), instrumentId); } } else if (stats.AggregationStatistics is LastValueStatistics lastValueStatistics) { Log.GaugeValuePublished(sessionId, instrument.Meter.Name, instrument.Meter.Version, instrument.Name, instrument.Unit, Helpers.FormatTags(stats.Labels), lastValueStatistics.LastValue.HasValue ? lastValueStatistics.LastValue.Value.ToString(CultureInfo.InvariantCulture) : "", instrumentId); } else if (stats.AggregationStatistics is SynchronousLastValueStatistics synchronousLastValueStatistics) { Log.GaugeValuePublished(sessionId, instrument.Meter.Name, instrument.Meter.Version, instrument.Name, instrument.Unit, Helpers.FormatTags(stats.Labels), synchronousLastValueStatistics.LastValue.ToString(CultureInfo.InvariantCulture), instrumentId); } else if (stats.AggregationStatistics is HistogramStatistics histogramStatistics) { Log.HistogramValuePublished(sessionId, instrument.Meter.Name, instrument.Meter.Version, instrument.Name, instrument.Unit, Helpers.FormatTags(stats.Labels), FormatQuantiles(histogramStatistics.Quantiles), histogramStatistics.Count, histogramStatistics.Sum, instrumentId); } else if (stats.AggregationStatistics is Base2ExponentialHistogramStatistics base2ExponentialHistogramStatistics) { Log.Base2ExponentialHistogramValuePublished(sessionId, instrument.Meter.Name, instrument.Meter.Version, instrument.Name, instrumentId, instrument.Unit, Helpers.FormatTags(stats.Labels), base2ExponentialHistogramStatistics.Scale, base2ExponentialHistogramStatistics.Sum, base2ExponentialHistogramStatistics.Count, base2ExponentialHistogramStatistics.ZeroCount, base2ExponentialHistogramStatistics.Minimum, base2ExponentialHistogramStatistics.Maximum, FormatBuckets(base2ExponentialHistogramStatistics.PositiveBuckets)); } } private static string FormatBuckets(long[] buckets) { Span initialBuffer = stackalloc char[512]; System.Text.ValueStringBuilder valueStringBuilder = new System.Text.ValueStringBuilder(initialBuffer); if (buckets.Length != 0) { valueStringBuilder.Append($"{buckets[0]}"); } for (int i = 1; i < buckets.Length; i++) { valueStringBuilder.Append($", {buckets[i]}"); } return valueStringBuilder.ToString(); } private static string FormatQuantiles(QuantileValue[] quantiles) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < quantiles.Length; i++) { stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}", quantiles[i].Quantile, quantiles[i].Value); if (i != quantiles.Length - 1) { stringBuilder.Append(';'); } } return stringBuilder.ToString(); } } private sealed class MetricSpec { private const char MeterInstrumentSeparator = '\\'; public string MeterName { get; } public string InstrumentName { get; } public MetricSpec(string meterName, string instrumentName) { MeterName = meterName; InstrumentName = instrumentName; } public static MetricSpec Parse(string text) { int num = text.IndexOf('\\'); if (num < 0) { return new MetricSpec(text.Trim(), null); } string meterName = text.AsSpan(0, num).Trim().ToString(); string instrumentName = text.AsSpan(num + 1).Trim().ToString(); return new MetricSpec(meterName, instrumentName); } public override string ToString() { if (InstrumentName == null) { return MeterName; } return MeterName + "\\" + InstrumentName; } } public static readonly MetricsEventSource Log = new MetricsEventSource(); private const string SharedSessionId = "SHARED"; private const string ClientIdKey = "ClientId"; private const string MaxHistogramsKey = "MaxHistograms"; private const string MaxTimeSeriesKey = "MaxTimeSeries"; private const string RefreshIntervalKey = "RefreshInterval"; private const string DefaultValueDescription = "default"; private const string SharedValueDescription = "shared value"; private CommandHandler _handler; private CommandHandler Handler { get { if (_handler == null) { Interlocked.CompareExchange(ref _handler, new CommandHandler(this), null); } return _handler; } } public static MetricsEventSource GetInstance() { return Log; } private MetricsEventSource() { } [Event(1, Keywords = (EventKeywords)1L)] public void Message(string Message) { WriteEvent(1, Message); } [Event(2, Keywords = (EventKeywords)2L)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] public void CollectionStart(string sessionId, DateTime intervalStartTime, DateTime intervalEndTime) { WriteEvent(2, new object[3] { sessionId, intervalStartTime, intervalEndTime }); } [Event(3, Keywords = (EventKeywords)2L)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] public void CollectionStop(string sessionId, DateTime intervalStartTime, DateTime intervalEndTime) { WriteEvent(3, new object[3] { sessionId, intervalStartTime, intervalEndTime }); } [Event(4, Keywords = (EventKeywords)2L, Version = 2)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] public void CounterRateValuePublished(string sessionId, string meterName, string meterVersion, string instrumentName, string unit, string tags, string rate, string value, int instrumentId) { WriteEvent(4, new object[9] { sessionId, meterName, meterVersion ?? "", instrumentName, unit ?? "", tags, rate, value, instrumentId }); } [Event(5, Keywords = (EventKeywords)2L, Version = 2)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] public void GaugeValuePublished(string sessionId, string meterName, string meterVersion, string instrumentName, string unit, string tags, string lastValue, int instrumentId) { WriteEvent(5, new object[8] { sessionId, meterName, meterVersion ?? "", instrumentName, unit ?? "", tags, lastValue, instrumentId }); } [Event(6, Keywords = (EventKeywords)2L, Version = 2)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] public void HistogramValuePublished(string sessionId, string meterName, string meterVersion, string instrumentName, string unit, string tags, string quantiles, int count, double sum, int instrumentId) { WriteEvent(6, new object[10] { sessionId, meterName, meterVersion ?? "", instrumentName, unit ?? "", tags, quantiles, count, sum, instrumentId }); } [Event(7, Keywords = (EventKeywords)2L, Version = 3)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] public void BeginInstrumentReporting(string sessionId, string meterName, string meterVersion, string instrumentName, string instrumentType, string unit, string description, string instrumentTags, string meterTags, string meterScopeHash, int instrumentId, string meterTelemetrySchemaUrl) { WriteEvent(7, new object[12] { sessionId, meterName, meterVersion ?? "", instrumentName, instrumentType, unit ?? "", description ?? "", instrumentTags, meterTags, meterScopeHash, instrumentId, meterTelemetrySchemaUrl ?? "" }); } [Event(8, Keywords = (EventKeywords)2L, Version = 3)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] public void EndInstrumentReporting(string sessionId, string meterName, string meterVersion, string instrumentName, string instrumentType, string unit, string description, string instrumentTags, string meterTags, string meterScopeHash, int instrumentId, string meterTelemetrySchemaUrl) { WriteEvent(8, new object[12] { sessionId, meterName, meterVersion ?? "", instrumentName, instrumentType, unit ?? "", description ?? "", instrumentTags, meterTags, meterScopeHash, instrumentId, meterTelemetrySchemaUrl ?? "" }); } [Event(9, Keywords = (EventKeywords)7L)] public void Error(string sessionId, string errorMessage) { WriteEvent(9, sessionId, errorMessage); } [Event(10, Keywords = (EventKeywords)6L)] public void InitialInstrumentEnumerationComplete(string sessionId) { WriteEvent(10, sessionId); } [Event(11, Keywords = (EventKeywords)4L, Version = 3)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] public void InstrumentPublished(string sessionId, string meterName, string meterVersion, string instrumentName, string instrumentType, string unit, string description, string instrumentTags, string meterTags, string meterScopeHash, int instrumentId, string meterTelemetrySchemaUrl) { WriteEvent(11, new object[12] { sessionId, meterName, meterVersion ?? "", instrumentName, instrumentType, unit ?? "", description ?? "", instrumentTags, meterTags, meterScopeHash, instrumentId, meterTelemetrySchemaUrl ?? "" }); } [Event(12, Keywords = (EventKeywords)2L)] public void TimeSeriesLimitReached(string sessionId) { WriteEvent(12, sessionId); } [Event(13, Keywords = (EventKeywords)2L)] public void HistogramLimitReached(string sessionId) { WriteEvent(13, sessionId); } [Event(14, Keywords = (EventKeywords)2L)] public void ObservableInstrumentCallbackError(string sessionId, string errorMessage) { WriteEvent(14, sessionId, errorMessage); } [Event(15, Keywords = (EventKeywords)7L)] public void MultipleSessionsNotSupportedError(string runningSessionId) { WriteEvent(15, runningSessionId); } [Event(16, Keywords = (EventKeywords)2L, Version = 2)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] public void UpDownCounterRateValuePublished(string sessionId, string meterName, string meterVersion, string instrumentName, string unit, string tags, string rate, string value, int instrumentId) { WriteEvent(16, new object[9] { sessionId, meterName, meterVersion ?? "", instrumentName, unit ?? "", tags, rate, value, instrumentId }); } [Event(17, Keywords = (EventKeywords)2L)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] public void MultipleSessionsConfiguredIncorrectlyError(string clientId, string expectedMaxHistograms, string actualMaxHistograms, string expectedMaxTimeSeries, string actualMaxTimeSeries, string expectedRefreshInterval, string actualRefreshInterval) { WriteEvent(17, new object[7] { clientId, expectedMaxHistograms, actualMaxHistograms, expectedMaxTimeSeries, actualMaxTimeSeries, expectedRefreshInterval, actualRefreshInterval }); } [Event(18, Keywords = (EventKeywords)1L)] public void Version(int Major, int Minor, int Patch) { WriteEvent(18, Major, Minor, Patch); } [Event(19, Keywords = (EventKeywords)2L, Version = 1)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")] public void Base2ExponentialHistogramValuePublished(string sessionId, string meterName, string meterVersion, string instrumentName, int instrumentId, string unit, string tags, int scale, double sum, long count, long zeroCount, double minimum, double maximum, string buckets) { WriteEvent(19, new object[14] { sessionId, meterName, meterVersion ?? "", instrumentName, instrumentId, unit ?? "", tags, scale, sum, count, zeroCount, minimum, maximum, buckets }); } [NonEvent] protected override void OnEventCommand(EventCommandEventArgs command) { if (command.Command == EventCommand.Enable) { Version(ThisAssembly.AssemblyFileVersion.Major, ThisAssembly.AssemblyFileVersion.Minor, ThisAssembly.AssemblyFileVersion.Build); } lock (this) { Handler.OnEventCommand(command); } } } public class MeterOptions { private string _name; public string Name { get { return _name; } set { _name = value ?? throw new ArgumentNullException("value"); } } public string? Version { get; set; } public IEnumerable>? Tags { get; set; } public object? Scope { get; set; } public string? TelemetrySchemaUrl { get; set; } public MeterOptions(string name) { Name = name; } } internal struct ObjectSequence1 : IEquatable, IObjectSequence { public object Value1; public object this[int i] { get { if (i == 0) { return Value1; } throw new IndexOutOfRangeException(); } set { if (i == 0) { Value1 = value; return; } throw new IndexOutOfRangeException(); } } public ObjectSequence1(object value1) { Value1 = value1; } public override int GetHashCode() { return Value1?.GetHashCode() ?? 0; } public bool Equals(ObjectSequence1 other) { if (Value1 != null) { return Value1.Equals(other.Value1); } return other.Value1 == null; } public override bool Equals(object obj) { if (obj is ObjectSequence1 other) { return Equals(other); } return false; } } internal struct ObjectSequence2 : IEquatable, IObjectSequence { public object Value1; public object Value2; public object this[int i] { get { return i switch { 0 => Value1, 1 => Value2, _ => throw new IndexOutOfRangeException(), }; } set { switch (i) { case 0: Value1 = value; break; case 1: Value2 = value; break; default: throw new IndexOutOfRangeException(); } } } public ObjectSequence2(object value1, object value2) { Value1 = value1; Value2 = value2; } public bool Equals(ObjectSequence2 other) { if ((Value1 == null) ? (other.Value1 == null) : Value1.Equals(other.Value1)) { if (Value2 != null) { return Value2.Equals(other.Value2); } return other.Value2 == null; } return false; } public override bool Equals(object obj) { if (obj is ObjectSequence2 other) { return Equals(other); } return false; } public override int GetHashCode() { return (Value1?.GetHashCode() ?? 0) ^ (Value2?.GetHashCode() ?? 0); } } internal struct ObjectSequence3 : IEquatable, IObjectSequence { public object Value1; public object Value2; public object Value3; public object this[int i] { get { return i switch { 0 => Value1, 1 => Value2, 2 => Value3, _ => throw new IndexOutOfRangeException(), }; } set { switch (i) { case 0: Value1 = value; break; case 1: Value2 = value; break; case 2: Value3 = value; break; default: throw new IndexOutOfRangeException(); } } } public ObjectSequence3(object value1, object value2, object value3) { Value1 = value1; Value2 = value2; Value3 = value3; } public bool Equals(ObjectSequence3 other) { if (((Value1 == null) ? (other.Value1 == null) : Value1.Equals(other.Value1)) && ((Value2 == null) ? (other.Value2 == null) : Value2.Equals(other.Value2))) { if (Value3 != null) { return Value3.Equals(other.Value3); } return other.Value3 == null; } return false; } public override bool Equals(object obj) { if (obj is ObjectSequence3 other) { return Equals(other); } return false; } public override int GetHashCode() { return (Value1?.GetHashCode() ?? 0) ^ (Value2?.GetHashCode() ?? 0) ^ (Value3?.GetHashCode() ?? 0); } } internal struct ObjectSequenceMany : IEquatable, IObjectSequence { private readonly object[] _values; public object this[int i] { get { return _values[i]; } set { _values[i] = value; } } public ObjectSequenceMany(object[] values) { _values = values; } public bool Equals(ObjectSequenceMany other) { if (_values.Length != other._values.Length) { return false; } for (int i = 0; i < _values.Length; i++) { object obj = _values[i]; object obj2 = other._values[i]; if (obj == null) { if (obj2 != null) { return false; } } else if (!obj.Equals(obj2)) { return false; } } return true; } public override bool Equals(object obj) { if (obj is ObjectSequenceMany other) { return Equals(other); } return false; } public override int GetHashCode() { int num = 0; for (int i = 0; i < _values.Length; i++) { num <<= 3; object obj = _values[i]; if (obj != null) { num ^= obj.GetHashCode(); } } return num; } } public sealed class ObservableCounter : ObservableInstrument where T : struct { private readonly object _callback; internal ObservableCounter(Meter meter, string name, Func observeValue, string unit, string description) : this(meter, name, observeValue, unit, description, (IEnumerable>)null) { } internal ObservableCounter(Meter meter, string name, Func observeValue, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { _callback = observeValue ?? throw new ArgumentNullException("observeValue"); Publish(); } internal ObservableCounter(Meter meter, string name, Func> observeValue, string unit, string description) : this(meter, name, observeValue, unit, description, (IEnumerable>)null) { } internal ObservableCounter(Meter meter, string name, Func> observeValue, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { _callback = observeValue ?? throw new ArgumentNullException("observeValue"); Publish(); } internal ObservableCounter(Meter meter, string name, Func>> observeValues, string unit, string description) : this(meter, name, observeValues, unit, description, (IEnumerable>)null) { } internal ObservableCounter(Meter meter, string name, Func>> observeValues, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { _callback = observeValues ?? throw new ArgumentNullException("observeValues"); Publish(); } protected override IEnumerable> Observe() { return ObservableInstrument.Observe(_callback); } } public sealed class ObservableGauge : ObservableInstrument where T : struct { private readonly object _callback; internal ObservableGauge(Meter meter, string name, Func observeValue, string unit, string description) : this(meter, name, observeValue, unit, description, (IEnumerable>)null) { } internal ObservableGauge(Meter meter, string name, Func observeValue, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { _callback = observeValue ?? throw new ArgumentNullException("observeValue"); Publish(); } internal ObservableGauge(Meter meter, string name, Func> observeValue, string unit, string description) : this(meter, name, observeValue, unit, description, (IEnumerable>)null) { } internal ObservableGauge(Meter meter, string name, Func> observeValue, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { _callback = observeValue ?? throw new ArgumentNullException("observeValue"); Publish(); } internal ObservableGauge(Meter meter, string name, Func>> observeValues, string unit, string description) : this(meter, name, observeValues, unit, description, (IEnumerable>)null) { } internal ObservableGauge(Meter meter, string name, Func>> observeValues, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { _callback = observeValues ?? throw new ArgumentNullException("observeValues"); Publish(); } protected override IEnumerable> Observe() { return ObservableInstrument.Observe(_callback); } } public abstract class ObservableInstrument : Instrument where T : struct { public override bool IsObservable => true; protected ObservableInstrument(Meter meter, string name, string? unit, string? description) : this(meter, name, unit, description, (IEnumerable>?)null) { } protected ObservableInstrument(Meter meter, string name, string? unit, string? description, IEnumerable>? tags) : base(meter, name, unit, description, tags) { Instrument.ValidateTypeParameter(); } protected abstract IEnumerable> Observe(); internal override void Observe(MeterListener listener) { object subscriptionState = GetSubscriptionState(listener); IEnumerable> enumerable = Observe(); if (enumerable == null) { return; } foreach (Measurement item in enumerable) { listener.NotifyMeasurement(this, item.Value, item.Tags, subscriptionState); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static IEnumerable> Observe(object callback) { if (callback is Func func) { return new Measurement[1] { new Measurement(func()) }; } if (callback is Func> func2) { return new Measurement[1] { func2() }; } if (callback is Func>> func3) { return func3(); } return null; } } public sealed class ObservableUpDownCounter : ObservableInstrument where T : struct { private readonly object _callback; internal ObservableUpDownCounter(Meter meter, string name, Func observeValue, string unit, string description) : this(meter, name, observeValue, unit, description, (IEnumerable>)null) { } internal ObservableUpDownCounter(Meter meter, string name, Func observeValue, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { _callback = observeValue ?? throw new ArgumentNullException("observeValue"); Publish(); } internal ObservableUpDownCounter(Meter meter, string name, Func> observeValue, string unit, string description) : this(meter, name, observeValue, unit, description, (IEnumerable>)null) { } internal ObservableUpDownCounter(Meter meter, string name, Func> observeValue, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { _callback = observeValue ?? throw new ArgumentNullException("observeValue"); Publish(); } internal ObservableUpDownCounter(Meter meter, string name, Func>> observeValues, string unit, string description) : this(meter, name, observeValues, unit, description, (IEnumerable>)null) { } internal ObservableUpDownCounter(Meter meter, string name, Func>> observeValues, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { _callback = observeValues ?? throw new ArgumentNullException("observeValues"); Publish(); } protected override IEnumerable> Observe() { return ObservableInstrument.Observe(_callback); } } internal sealed class CounterAggregator : Aggregator { [StructLayout(LayoutKind.Explicit, Size = 64)] private struct PaddedDouble { [FieldOffset(0)] public double Value; } private readonly bool _isMonotonic; private double _aggregatedValue; private readonly PaddedDouble[] _deltas = new PaddedDouble[Math.Min(Environment.ProcessorCount, 8)]; public CounterAggregator(bool isMonotonic) { _isMonotonic = isMonotonic; } public override void Update(double value) { PaddedDouble[] deltas = _deltas; ref PaddedDouble reference = ref deltas[Environment.CurrentManagedThreadId % deltas.Length]; double value2; do { value2 = reference.Value; } while (Interlocked.CompareExchange(ref reference.Value, value2 + value, value2) != value2); } public override IAggregationStatistics Collect() { double num; double aggregatedValue; lock (this) { num = 0.0; Span span = _deltas.AsSpan(); for (int i = 0; i < span.Length; i++) { num += Interlocked.Exchange(ref span[i].Value, 0.0); } _aggregatedValue += num; aggregatedValue = _aggregatedValue; } return new CounterStatistics(num, _isMonotonic, aggregatedValue); } } internal sealed class ObservableCounterAggregator : Aggregator { private readonly bool _isMonotonic; private double? _prevValue; private double _currValue; public ObservableCounterAggregator(bool isMonotonic) { _isMonotonic = isMonotonic; } public override void Update(double value) { Volatile.Write(ref _currValue, value); } public override IAggregationStatistics Collect() { double? delta = null; double num; lock (this) { num = Volatile.Read(in _currValue); if (_prevValue.HasValue) { delta = num - _prevValue.Value; } _prevValue = num; } return new CounterStatistics(delta, _isMonotonic, num); } } internal sealed class CounterStatistics : IAggregationStatistics { public double? Delta { get; } public bool IsMonotonic { get; } public double Value { get; } public CounterStatistics(double? delta, bool isMonotonic, double value) { Delta = delta; IsMonotonic = isMonotonic; Value = value; } } internal struct StringSequence1 : IEquatable, IStringSequence { public string Value1; public string this[int i] { get { if (i == 0) { return Value1; } throw new IndexOutOfRangeException(); } set { if (i == 0) { Value1 = value; return; } throw new IndexOutOfRangeException(); } } public int Length => 1; public StringSequence1(string value1) { Value1 = value1; } public override int GetHashCode() { return Value1.GetHashCode(); } public bool Equals(StringSequence1 other) { return Value1 == other.Value1; } public override bool Equals(object obj) { if (obj is StringSequence1 other) { return Equals(other); } return false; } } internal struct StringSequence2 : IEquatable, IStringSequence { public string Value1; public string Value2; public string this[int i] { get { return i switch { 0 => Value1, 1 => Value2, _ => throw new IndexOutOfRangeException(), }; } set { switch (i) { case 0: Value1 = value; break; case 1: Value2 = value; break; default: throw new IndexOutOfRangeException(); } } } public int Length => 2; public StringSequence2(string value1, string value2) { Value1 = value1; Value2 = value2; } public bool Equals(StringSequence2 other) { if (Value1 == other.Value1) { return Value2 == other.Value2; } return false; } public override bool Equals(object obj) { if (obj is StringSequence2 other) { return Equals(other); } return false; } public override int GetHashCode() { return (Value1?.GetHashCode() ?? 0) ^ (Value2?.GetHashCode() ?? 0); } } internal struct StringSequence3 : IEquatable, IStringSequence { public string Value1; public string Value2; public string Value3; public string this[int i] { get { return i switch { 0 => Value1, 1 => Value2, 2 => Value3, _ => throw new IndexOutOfRangeException(), }; } set { switch (i) { case 0: Value1 = value; break; case 1: Value2 = value; break; case 2: Value3 = value; break; default: throw new IndexOutOfRangeException(); } } } public int Length => 3; public StringSequence3(string value1, string value2, string value3) { Value1 = value1; Value2 = value2; Value3 = value3; } public bool Equals(StringSequence3 other) { if (Value1 == other.Value1 && Value2 == other.Value2) { return Value3 == other.Value3; } return false; } public override bool Equals(object obj) { if (obj is StringSequence3 other) { return Equals(other); } return false; } public override int GetHashCode() { return (Value1?.GetHashCode() ?? 0) ^ (Value2?.GetHashCode() ?? 0) ^ (Value3?.GetHashCode() ?? 0); } } internal struct StringSequenceMany : IEquatable, IStringSequence { private readonly string[] _values; public string this[int i] { get { return _values[i]; } set { _values[i] = value; } } public int Length => _values.Length; public StringSequenceMany(string[] values) { _values = values; } public Span AsSpan() { return _values.AsSpan(); } public bool Equals(StringSequenceMany other) { return _values.AsSpan().SequenceEqual(other._values.AsSpan()); } public override bool Equals(object obj) { if (obj is StringSequenceMany other) { return Equals(other); } return false; } public override int GetHashCode() { int num = 0; for (int i = 0; i < _values.Length; i++) { num <<= 3; num ^= _values[i].GetHashCode(); } return num; } } public sealed class UpDownCounter : Instrument where T : struct { internal UpDownCounter(Meter meter, string name, string unit, string description) : this(meter, name, unit, description, (IEnumerable>)null) { } internal UpDownCounter(Meter meter, string name, string unit, string description, IEnumerable> tags) : base(meter, name, unit, description, tags) { Publish(); } public void Add(T delta) { RecordMeasurement(delta); } public void Add(T delta, KeyValuePair tag) { RecordMeasurement(delta, tag); } public void Add(T delta, KeyValuePair tag1, KeyValuePair tag2) { RecordMeasurement(delta, tag1, tag2); } public void Add(T delta, KeyValuePair tag1, KeyValuePair tag2, KeyValuePair tag3) { RecordMeasurement(delta, tag1, tag2, tag3); } public void Add(T delta, [ParamCollection] scoped ReadOnlySpan> tags) { RecordMeasurement(delta, tags); } public void Add(T delta, params KeyValuePair[] tags) { RecordMeasurement(delta, tags.AsSpan()); } public void Add(T delta, in TagList tagList) { RecordMeasurement(delta, in tagList); } } internal interface IObjectSequence { object this[int i] { get; set; } } internal interface IStringSequence { string this[int i] { get; set; } int Length { get; } } }