<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="9.0.0-preview.7.24405.7" />

ActivityTraceId

Represents a TraceId whose format is based on a W3C standard.
using System.Buffers.Binary; using System.Buffers.Text; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace System.Diagnostics { public readonly struct ActivityTraceId : IEquatable<ActivityTraceId> { private readonly string _hexString; internal ActivityTraceId(string hexString) { _hexString = hexString; } public unsafe static ActivityTraceId CreateRandom() { Span<byte> span = new Span<byte>(stackalloc byte[16], 16); SetToRandomBytes(span); return CreateFromBytes(span); } public static ActivityTraceId CreateFromBytes(ReadOnlySpan<byte> 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<byte> idData) { return new ActivityTraceId(idData); } public static ActivityTraceId CreateFromString(ReadOnlySpan<char> idData) { if (idData.Length != 32 || !IsLowerCaseHexAndNotAllZeros(idData)) throw new ArgumentOutOfRangeException("idData"); return new ActivityTraceId(idData.ToString()); } [System.Runtime.CompilerServices.NullableContext(1)] public string ToHexString() { return _hexString ?? "00000000000000000000000000000000"; } [System.Runtime.CompilerServices.NullableContext(1)] 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; } [System.Runtime.CompilerServices.NullableContext(2)] public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] object obj) { if (obj is ActivityTraceId) { ActivityTraceId activityTraceId = (ActivityTraceId)obj; return _hexString == activityTraceId._hexString; } return false; } public override int GetHashCode() { return ToHexString().GetHashCode(); } private unsafe ActivityTraceId(ReadOnlySpan<byte> idData) { if (idData.Length != 32) throw new ArgumentOutOfRangeException("idData"); Span<ulong> span = new Span<ulong>(stackalloc byte[16], 2); if (!Utf8Parser.TryParse(idData.Slice(0, 16), out span[0], out int bytesConsumed, 'x')) _hexString = CreateRandom()._hexString; else if (!Utf8Parser.TryParse(idData.Slice(16, 16), out span[1], out bytesConsumed, 'x')) { _hexString = CreateRandom()._hexString; } else { 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<byte> destination) { SetSpanFromHexChars(ToHexString().AsSpan(), destination); } internal static void SetToRandomBytes(Span<byte> 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<char> charData, Span<byte> 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<char> idData) { bool result = false; foreach (char c in idData) { if (!System.HexConverter.IsHexLowerChar(c)) return false; if (c != '0') result = true; } return result; } } }