Skip to content

Commit

Permalink
Baggage and Tags for activity tracking options (#46571) (#48722)
Browse files Browse the repository at this point in the history
Co-authored-by: Sallin Marc, I212 <marc.sallin@post.ch>
  • Loading branch information
msallin and Sallin Marc, I212 committed Mar 12, 2021
1 parent d84e331 commit dacf02b
Show file tree
Hide file tree
Showing 7 changed files with 351 additions and 14 deletions.
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)
{
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

0 comments on commit dacf02b

Please sign in to comment.