<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="5.0.0-preview.1.20120.5" />

ActivityTraceId

Represents a TraceId whose format is based on a W3C standard.
using System.Buffers.Binary; using System.Buffers.Text; 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); Span<byte> span2 = span; SetToRandomBytes(span2); return CreateFromBytes(span2); } 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(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); Span<ulong> span2 = span; if (!Utf8Parser.TryParse(idData.Slice(0, 16), out span2[0], out int bytesConsumed, 'x')) _hexString = CreateRandom()._hexString; else if (!Utf8Parser.TryParse(idData.Slice(16, 16), out span2[1], out bytesConsumed, 'x')) { _hexString = CreateRandom()._hexString; } else { if (BitConverter.IsLittleEndian) { span2[0] = BinaryPrimitives.ReverseEndianness(span2[0]); span2[1] = BinaryPrimitives.ReverseEndianness(span2[1]); } _hexString = System.HexConverter.ToString(MemoryMarshal.AsBytes(span2), System.HexConverter.Casing.Lower); } } public void CopyTo(Span<byte> destination) { SetSpanFromHexChars(ToHexString().AsSpan(), destination); } internal unsafe static void SetToRandomBytes(Span<byte> outBytes) { Guid guid = Guid.NewGuid(); new ReadOnlySpan<byte>(&guid, sizeof(Guid)).Slice(0, outBytes.Length).CopyTo(outBytes); } 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) { return (byte)(HexDigitToBinary(char1) * 16 + HexDigitToBinary(char2)); } private static byte HexDigitToBinary(char c) { if ('0' <= c && c <= '9') return (byte)(c - 48); if ('a' <= c && c <= 'f') return (byte)(c - 87); throw new ArgumentOutOfRangeException("idData"); } internal static bool IsLowerCaseHexAndNotAllZeros(ReadOnlySpan<char> idData) { bool result = false; foreach (char c in idData) { if (!IsHexadecimalLowercaseChar(c)) return false; if (c != '0') result = true; } return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool IsHexadecimalLowercaseChar(char c) { if ((uint)(c - 48) > 9) return (uint)(c - 97) <= 5; return true; } } }