Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Baggage and Tags for activity tracking options (#46571) #48722

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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 @@ -109,11 +109,11 @@ private void WriteScopeInformation(Utf8JsonWriter writer, IExternalScopeProvider
writer.WriteStartArray("Scopes");
scopeProvider.ForEachScope((scope, state) =>
{
if (scope is IEnumerable<KeyValuePair<string, object>> scopes)
if (scope is IEnumerable<KeyValuePair<string, object>> scopeItems)
msallin marked this conversation as resolved.
Show resolved Hide resolved
{
state.WriteStartObject();
state.WriteString("Message", scope.ToString());
foreach (KeyValuePair<string, object> item in scopes)
foreach (KeyValuePair<string, object> item in scopeItems)
{
WriteItem(state, item);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public enum ActivityTrackingOptions
ParentId = 4,
TraceState = 8,
TraceFlags = 16,
Tags = 32,
Baggage = 64
}
public static partial class FilterLoggingBuilderExtensions
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,38 @@ public enum ActivityTrackingOptions
None = 0x0000,

/// <summary>
/// Span Id wil be included in the logging.
/// Span Id will be included in the logging.
/// </summary>
SpanId = 0x0001,

/// <summary>
/// Trace Id wil be included in the logging.
/// Trace Id will be included in the logging.
/// </summary>
TraceId = 0x0002,

/// <summary>
/// Parent Id wil be included in the logging.
/// Parent Id will be included in the logging.
/// </summary>
ParentId = 0x0004,

/// <summary>
/// Trace State wil be included in the logging.
/// Trace State will be included in the logging.
/// </summary>
TraceState = 0x0008,

/// <summary>
/// Trace flags wil be included in the logging.
/// Trace flags will be included in the logging.
/// </summary>
TraceFlags = 0x0010
TraceFlags = 0x0010,

/// <summary>
/// Tags will be included in the logging.
/// </summary>
Tags = 0x0020,

/// <summary>
/// Items of baggage will be included in the logging.
/// </summary>
Baggage = 0x0040
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ public LoggerFactory(IEnumerable<ILoggerProvider> providers, IOptionsMonitor<Log
_factoryOptions = options == null || options.Value == null ? new LoggerFactoryOptions() : options.Value;

const ActivityTrackingOptions ActivityTrackingOptionsMask = ~(ActivityTrackingOptions.SpanId | ActivityTrackingOptions.TraceId | ActivityTrackingOptions.ParentId |
ActivityTrackingOptions.TraceFlags | ActivityTrackingOptions.TraceState);
ActivityTrackingOptions.TraceFlags | ActivityTrackingOptions.TraceState | ActivityTrackingOptions.Tags
| ActivityTrackingOptions.Baggage);


if ((_factoryOptions.ActivityTrackingOptions & ActivityTrackingOptionsMask) != 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System;
using System.Text;
using System.Globalization;
using System.Threading;
using System.Collections;
using System.Diagnostics;
Expand Down Expand Up @@ -48,12 +47,47 @@ void Report(Scope current)
}

callback(activityLogScope, state);

// Tags and baggage are opt-in and thus we assume that most of the time it will not be used.
if ((_activityTrackingOption & ActivityTrackingOptions.Tags) != 0
&& activity.TagObjects.GetEnumerator().MoveNext())
{
// As TagObjects is a IEnumerable<KeyValuePair<string, object?>> this can be used directly as a scope.
// We do this to safe the allocation of a wrapper object.
callback(activity.TagObjects, state);
}

if ((_activityTrackingOption & ActivityTrackingOptions.Baggage) != 0)
{
// Only access activity.Baggage as every call leads to an allocation
IEnumerable<KeyValuePair<string, string?>> baggage = activity.Baggage;
if (baggage.GetEnumerator().MoveNext())
{
// For the baggage a wrapper object is necessary because we need to be able to overwrite ToString().
// In contrast to the TagsObject, Baggage doesn't have one underlining type where we can do this overwrite.
ActivityBaggageLogScopeWrapper scope = GetOrCreateActivityBaggageLogScopeWrapper(activity, baggage);
callback(scope, state);
}
}
}
}

Report(_currentScope.Value);
}

private static ActivityBaggageLogScopeWrapper GetOrCreateActivityBaggageLogScopeWrapper(Activity activity, IEnumerable<KeyValuePair<string, string?>> items)
{
const string additionalItemsBaggagePropertyKey = "__ActivityBaggageItemsLogScope__";
var activityBaggageLogScopeWrapper = activity.GetCustomProperty(additionalItemsBaggagePropertyKey) as ActivityBaggageLogScopeWrapper;
if (activityBaggageLogScopeWrapper == null)
{
activityBaggageLogScopeWrapper = new ActivityBaggageLogScopeWrapper(items);
activity.SetCustomProperty(additionalItemsBaggagePropertyKey, activityBaggageLogScopeWrapper);
}

return activityBaggageLogScopeWrapper;
}

public IDisposable Push(object state)
{
Scope parent = _currentScope.Value;
Expand Down Expand Up @@ -185,7 +219,59 @@ IEnumerator IEnumerable.GetEnumerator()
return GetEnumerator();
}
}

private class ActivityBaggageLogScopeWrapper : IEnumerable<KeyValuePair<string, string?>>
{
private readonly IEnumerable<KeyValuePair<string, string?>> _items;

private StringBuilder? _stringBuilder;

public ActivityBaggageLogScopeWrapper (IEnumerable<KeyValuePair<string, string?>> items)
{
_items = items;
}

public IEnumerator<KeyValuePair<string, string?>> GetEnumerator()
{
return _items.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return _items.GetEnumerator();
}

public override string ToString()
{
lock (this)
{
IEnumerator<KeyValuePair<string, string?>> enumerator = _items.GetEnumerator();
if (!enumerator.MoveNext())
{
return string.Empty;
}

_stringBuilder ??= new StringBuilder();
_stringBuilder.Append(enumerator.Current.Key);
_stringBuilder.Append(':');
_stringBuilder.Append(enumerator.Current.Value);

while (enumerator.MoveNext())
{
_stringBuilder.Append(", ");
_stringBuilder.Append(enumerator.Current.Key);
_stringBuilder.Append(':');
_stringBuilder.Append(enumerator.Current.Value);
}

string result = _stringBuilder.ToString();
_stringBuilder.Clear();
return result;
}
}
}
}

internal static class ActivityExtensions
{
public static string GetSpanId(this Activity activity)
Expand Down
Loading