Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,20 @@ public sealed class ActivityListener : IDisposable
public System.Diagnostics.SampleActivity<string>? SampleUsingParentId { get { throw null; } set { throw null; } }
public System.Diagnostics.SampleActivity<ActivityContext>? Sample { get { throw null; } set { throw null; } }
public void Dispose() { throw null; }
}
}
public abstract class TextMapPropagator
{
public delegate void PropagatorGetterCallback(object carrier, string fieldName, out string? fieldValue, out System.Collections.Generic.IEnumerable<string>? fieldValues);
public delegate void PropagatorSetterCallback(object carrier, string fieldName, string fieldValue);
public abstract System.Collections.Generic.IReadOnlyCollection<string> Fields { get; }
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 System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string?>>? ExtractBaggage(object carrier, PropagatorGetterCallback getter);
public static TextMapPropagator Current { get; set; }
public static TextMapPropagator CreateDefaultPropagator() { throw null; }
public static TextMapPropagator CreatePassThroughPropagator() { throw null; }
public static TextMapPropagator CreateNoOutputPropagator() { throw null; }
}
}

namespace System.Diagnostics.Metrics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@
<Compile Include="System\Diagnostics\ActivitySource.cs" />
<Compile Include="System\Diagnostics\DiagnosticSourceActivity.cs" />
<Compile Include="System\Diagnostics\DiagLinkedList.cs" />
<Compile Include="System\Diagnostics\LegacyPropagator.cs" />
<Compile Include="System\Diagnostics\NoOutputPropagator.cs" />
<Compile Include="System\Diagnostics\PassThroughPropagator.cs" />
<Compile Include="System\Diagnostics\RandomNumberGenerator.cs" />
<Compile Include="System\Diagnostics\TextMapPropagator.cs" />
<Compile Include="System\Diagnostics\Metrics\AggregationManager.cs" />
<Compile Include="System\Diagnostics\Metrics\Aggregator.cs" />
<Compile Include="System\Diagnostics\Metrics\AggregatorStore.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Net;
using System.Collections.Generic;

namespace System.Diagnostics
{
internal class LegacyPropagator : TextMapPropagator
{
internal static TextMapPropagator Instance { get; } = new LegacyPropagator();

public override IReadOnlyCollection<string> Fields { get; } = new HashSet<string>() { 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 (activity.TraceStateString is not null)
{
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)
{
IEnumerable<KeyValuePair<string, string?>>? baggage = null;
if (getter is null)
{
return null;
}

getter(carrier, Baggage, out string? theBaggage, out _);
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)
{
if (baggageList is null)
{
baggageList = new();
}

// Insert in reverse order for asp.net compatability.
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;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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;

namespace System.Diagnostics
{
internal class NoOutputPropagator : TextMapPropagator
{
internal static TextMapPropagator Instance { get; } = new NoOutputPropagator();

public override IReadOnlyCollection<string> Fields { get; } = new HashSet<string>() { TraceParent, RequestId, TraceState, Baggage, CorrelationContext };

public override void Inject(Activity activity, object carrier, PropagatorSetterCallback setter)
{
// nothing to do.
}

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<KeyValuePair<string, string?>>? ExtractBaggage(object carrier, PropagatorGetterCallback getter) => LegacyPropagator.Instance.ExtractBaggage(carrier, getter);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// 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;

namespace System.Diagnostics
{
internal class PassThroughPropagator : TextMapPropagator
{
internal static TextMapPropagator Instance { get; } = new PassThroughPropagator();

public override IReadOnlyCollection<string> Fields { get; } = new HashSet<string>() { TraceParent, RequestId, TraceState, Baggage, CorrelationContext };

public override void Inject(Activity activity, object carrier, PropagatorSetterCallback setter)
{
GetRootId(out string? parentId, out string? traceState, out bool isW3c, out IEnumerable<KeyValuePair<string, string?>>? baggage);
if (parentId is null)
{
return;
}

setter(carrier, isW3c ? TraceParent : RequestId, parentId);

if (traceState is not null)
{
setter(carrier, TraceState, traceState);
}

if (baggage is not null)
{
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<KeyValuePair<string, string?>>? ExtractBaggage(object carrier, PropagatorGetterCallback getter) => LegacyPropagator.Instance.ExtractBaggage(carrier, getter);

private static void GetRootId(out string? parentId, out string? traceState, out bool isW3c, out IEnumerable<KeyValuePair<string, string?>>? baggage)
{
Activity? activity = Activity.Current;
if (activity is null)
{
parentId = null;
traceState = null;
isW3c = false;
baggage = null;
return;
}

while (activity is not null && activity.Parent is not null)
{
activity = activity.Parent;
}

traceState = activity?.TraceStateString;
parentId = activity?.ParentId ?? activity?.Id;
isW3c = activity?.IdFormat == ActivityIdFormat.W3C;
baggage = activity?.Baggage;
}
}
}
Loading