| File: System\Diagnostics\LegacyPropagator.cs | Web Access |
| Project: src\runtime\src\libraries\System.Diagnostics.DiagnosticSource\src\System.Diagnostics.DiagnosticSource.csproj (System.Diagnostics.DiagnosticSource) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Collections.ObjectModel; using System.Net; namespace System.Diagnostics { internal sealed class LegacyPropagator : DistributedContextPropagator { internal static DistributedContextPropagator Instance { get; } = new LegacyPropagator(); public override IReadOnlyCollection<string> Fields { get; } = new ReadOnlyCollection<string>(new[] { TraceParent, RequestId, TraceState, Baggage, CorrelationContext }); public override void Inject(Activity? activity, object? carrier, PropagatorSetterCallback? setter) { if (activity is null || setter is null) { return; } string? id = activity.Id; if (id is null) { return; } if (activity.IdFormat == ActivityIdFormat.W3C) { setter(carrier, TraceParent, id); if (!string.IsNullOrEmpty(activity.TraceStateString)) { setter(carrier, TraceState, activity.TraceStateString); } } else { setter(carrier, RequestId, id); } InjectBaggage(carrier, activity.Baggage, setter); } public override void ExtractTraceIdAndState(object? carrier, PropagatorGetterCallback? getter, out string? traceId, out string? traceState) { if (getter is null) { traceId = null; traceState = null; return; } getter(carrier, TraceParent, out traceId, out _); if (traceId is null) { getter(carrier, RequestId, out traceId, out _); } getter(carrier, TraceState, out traceState, out _); } public override IEnumerable<KeyValuePair<string, string?>>? ExtractBaggage(object? carrier, PropagatorGetterCallback? getter) { if (getter is null) { return null; } getter(carrier, Baggage, out string? theBaggage, out _); IEnumerable<KeyValuePair<string, string?>>? baggage = null; if (theBaggage is null || !TryExtractBaggage(theBaggage, out baggage)) { getter(carrier, CorrelationContext, out theBaggage, out _); if (theBaggage is not null) { TryExtractBaggage(theBaggage, out baggage); } } return baggage; } internal static bool TryExtractBaggage(string baggageString, out IEnumerable<KeyValuePair<string, string?>>? baggage) { baggage = null; List<KeyValuePair<string, string?>>? baggageList = null; if (string.IsNullOrEmpty(baggageString)) { return true; } int currentIndex = 0; do { // Skip spaces while (currentIndex < baggageString.Length && (baggageString[currentIndex] == Space || baggageString[currentIndex] == Tab)) { currentIndex++; } if (currentIndex >= baggageString.Length) { break; // No Key exist } int keyStart = currentIndex; // Search end of the key while (currentIndex < baggageString.Length && baggageString[currentIndex] != Space && baggageString[currentIndex] != Tab && baggageString[currentIndex] != '=') { currentIndex++; } if (currentIndex >= baggageString.Length) { break; } int keyEnd = currentIndex; if (baggageString[currentIndex] != '=') { // Skip Spaces while (currentIndex < baggageString.Length && (baggageString[currentIndex] == Space || baggageString[currentIndex] == Tab)) { currentIndex++; } if (currentIndex >= baggageString.Length) { break; // Wrong key format } if (baggageString[currentIndex] != '=') { break; // wrong key format. } } currentIndex++; // Skip spaces while (currentIndex < baggageString.Length && (baggageString[currentIndex] == Space || baggageString[currentIndex] == Tab)) { currentIndex++; } if (currentIndex >= baggageString.Length) { break; // Wrong value format } int valueStart = currentIndex; // Search end of the value while (currentIndex < baggageString.Length && baggageString[currentIndex] != Space && baggageString[currentIndex] != Tab && baggageString[currentIndex] != Comma && baggageString[currentIndex] != Semicolon) { currentIndex++; } if (keyStart < keyEnd && valueStart < currentIndex) { baggageList ??= new List<KeyValuePair<string, string?>>(); // Insert in reverse order for asp.net compatibility. baggageList.Insert(0, new KeyValuePair<string, string?>( WebUtility.UrlDecode(baggageString.Substring(keyStart, keyEnd - keyStart)).Trim(s_trimmingSpaceCharacters), WebUtility.UrlDecode(baggageString.Substring(valueStart, currentIndex - valueStart)).Trim(s_trimmingSpaceCharacters))); } // Skip to end of values while (currentIndex < baggageString.Length && baggageString[currentIndex] != Comma) { currentIndex++; } currentIndex++; // Move to next key-value entry } while (currentIndex < baggageString.Length); baggage = baggageList; return baggageList != null; } } }