Skip to content

Commit

Permalink
[OpenTelemetry.Extensions] Use file scoped namespace #276 (#560)
Browse files Browse the repository at this point in the history
  • Loading branch information
tony21921 authored Aug 3, 2022
1 parent 3dbb571 commit 5b47fd8
Show file tree
Hide file tree
Showing 9 changed files with 409 additions and 418 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,94 +20,93 @@
using OpenTelemetry.Internal;
using OpenTelemetry.Trace;

namespace OpenTelemetry.Logs
namespace OpenTelemetry.Logs;

internal sealed class ActivityEventAttachingLogProcessor : BaseProcessor<LogRecord>
{
internal sealed class ActivityEventAttachingLogProcessor : BaseProcessor<LogRecord>
private static readonly Action<LogRecordScope, State> ProcessScope = (LogRecordScope scope, State state) =>
{
private static readonly Action<LogRecordScope, State> ProcessScope = (LogRecordScope scope, State state) =>
try
{
try
{
state.Processor.options.ScopeConverter?.Invoke(state.Tags, state.Depth++, scope);
}
catch (Exception ex)
{
OpenTelemetryExtensionsEventSource.Log.LogProcessorException($"Processing scope of type [{scope.GetType().FullName}]", ex);
}
};
state.Processor.options.ScopeConverter?.Invoke(state.Tags, state.Depth++, scope);
}
catch (Exception ex)
{
OpenTelemetryExtensionsEventSource.Log.LogProcessorException($"Processing scope of type [{scope.GetType().FullName}]", ex);
}
};

private readonly LogToActivityEventConversionOptions options;
private readonly LogToActivityEventConversionOptions options;

public ActivityEventAttachingLogProcessor(LogToActivityEventConversionOptions options)
{
Guard.ThrowIfNull(options);
public ActivityEventAttachingLogProcessor(LogToActivityEventConversionOptions options)
{
Guard.ThrowIfNull(options);

this.options = options;
}
this.options = options;
}

public override void OnEnd(LogRecord data)
{
Activity? activity = Activity.Current;
public override void OnEnd(LogRecord data)
{
Activity? activity = Activity.Current;

if (activity?.IsAllDataRequested == true)
if (activity?.IsAllDataRequested == true)
{
var tags = new ActivityTagsCollection
{
var tags = new ActivityTagsCollection
{
{ nameof(data.CategoryName), data.CategoryName },
{ nameof(data.LogLevel), data.LogLevel },
};
{ nameof(data.CategoryName), data.CategoryName },
{ nameof(data.LogLevel), data.LogLevel },
};

if (data.EventId != 0)
{
tags[nameof(data.EventId)] = data.EventId;
}
if (data.EventId != 0)
{
tags[nameof(data.EventId)] = data.EventId;
}

var activityEvent = new ActivityEvent("log", data.Timestamp, tags);
var activityEvent = new ActivityEvent("log", data.Timestamp, tags);

data.ForEachScope(ProcessScope, new State(tags, this));
data.ForEachScope(ProcessScope, new State(tags, this));

if (data.StateValues != null)
if (data.StateValues != null)
{
try
{
try
{
this.options.StateConverter?.Invoke(tags, data.StateValues);
}
this.options.StateConverter?.Invoke(tags, data.StateValues);
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
OpenTelemetryExtensionsEventSource.Log.LogProcessorException($"Processing state of type [{data.State.GetType().FullName}]", ex);
}
}

if (!string.IsNullOrEmpty(data.FormattedMessage))
{
tags[nameof(data.FormattedMessage)] = data.FormattedMessage;
OpenTelemetryExtensionsEventSource.Log.LogProcessorException($"Processing state of type [{data.State.GetType().FullName}]", ex);
}
}

activity.AddEvent(activityEvent);
if (!string.IsNullOrEmpty(data.FormattedMessage))
{
tags[nameof(data.FormattedMessage)] = data.FormattedMessage;
}

if (data.Exception != null)
{
activity.RecordException(data.Exception);
}
activity.AddEvent(activityEvent);

if (data.Exception != null)
{
activity.RecordException(data.Exception);
}
}
}

private class State
private class State
{
public State(ActivityTagsCollection tags, ActivityEventAttachingLogProcessor processor)
{
public State(ActivityTagsCollection tags, ActivityEventAttachingLogProcessor processor)
{
this.Tags = tags;
this.Processor = processor;
}
this.Tags = tags;
this.Processor = processor;
}

public ActivityTagsCollection Tags { get; }
public ActivityTagsCollection Tags { get; }

public ActivityEventAttachingLogProcessor Processor { get; }
public ActivityEventAttachingLogProcessor Processor { get; }

public int Depth { get; set; }
}
public int Depth { get; set; }
}
}
#endif
59 changes: 29 additions & 30 deletions src/OpenTelemetry.Extensions/Internal/DefaultLogStateConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,48 +18,47 @@
using System.Collections.Generic;
using System.Diagnostics;

namespace OpenTelemetry.Logs
namespace OpenTelemetry.Logs;

internal static class DefaultLogStateConverter
{
internal static class DefaultLogStateConverter
public static void ConvertState(ActivityTagsCollection tags, IReadOnlyList<KeyValuePair<string, object>> state)
{
public static void ConvertState(ActivityTagsCollection tags, IReadOnlyList<KeyValuePair<string, object>> state)
for (int i = 0; i < state.Count; i++)
{
for (int i = 0; i < state.Count; i++)
{
KeyValuePair<string, object> stateItem = state[i];
KeyValuePair<string, object> stateItem = state[i];

object value = stateItem.Value;
if (value != null)
object value = stateItem.Value;
if (value != null)
{
if (string.IsNullOrEmpty(stateItem.Key))
{
if (string.IsNullOrEmpty(stateItem.Key))
{
tags["state"] = value;
}
else
{
tags[$"state.{stateItem.Key}"] = value;
}
tags["state"] = value;
}
else
{
tags[$"state.{stateItem.Key}"] = value;
}
}
}
}

public static void ConvertScope(ActivityTagsCollection tags, int depth, LogRecordScope scope)
{
string prefix = $"scope[{depth}]";
public static void ConvertScope(ActivityTagsCollection tags, int depth, LogRecordScope scope)
{
string prefix = $"scope[{depth}]";

foreach (KeyValuePair<string, object> scopeItem in scope)
foreach (KeyValuePair<string, object> scopeItem in scope)
{
object value = scopeItem.Value;
if (value != null)
{
object value = scopeItem.Value;
if (value != null)
if (string.IsNullOrEmpty(scopeItem.Key))
{
tags[prefix] = value;
}
else
{
if (string.IsNullOrEmpty(scopeItem.Key))
{
tags[prefix] = value;
}
else
{
tags[$"{prefix}.{scopeItem.Key}"] = value;
}
tags[$"{prefix}.{scopeItem.Key}"] = value;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,28 @@
using System.Diagnostics.Tracing;
using OpenTelemetry.Internal;

namespace OpenTelemetry
namespace OpenTelemetry;

/// <summary>
/// EventSource implementation for OpenTelemetry SDK extensions implementation.
/// </summary>
[EventSource(Name = "OpenTelemetry-Extensions")]
internal class OpenTelemetryExtensionsEventSource : EventSource
{
/// <summary>
/// EventSource implementation for OpenTelemetry SDK extensions implementation.
/// </summary>
[EventSource(Name = "OpenTelemetry-Extensions")]
internal class OpenTelemetryExtensionsEventSource : EventSource
{
public static OpenTelemetryExtensionsEventSource Log = new OpenTelemetryExtensionsEventSource();
public static OpenTelemetryExtensionsEventSource Log = new OpenTelemetryExtensionsEventSource();

[NonEvent]
public void LogProcessorException(string @event, Exception ex)
[NonEvent]
public void LogProcessorException(string @event, Exception ex)
{
if (this.IsEnabled(EventLevel.Error, (EventKeywords)(-1)))
{
if (this.IsEnabled(EventLevel.Error, (EventKeywords)(-1)))
{
this.LogProcessorException(@event, ex.ToInvariantString());
}
this.LogProcessorException(@event, ex.ToInvariantString());
}
}

[Event(1, Message = "Unknown error in LogProcessor event '{0}': '{1}'.", Level = EventLevel.Error)]
public void LogProcessorException(string @event, string exception)
{
this.WriteEvent(1, @event, exception);
}
[Event(1, Message = "Unknown error in LogProcessor event '{0}': '{1}'.", Level = EventLevel.Error)]
public void LogProcessorException(string @event, string exception)
{
this.WriteEvent(1, @event, exception);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,21 @@
using System.Collections.Generic;
using System.Diagnostics;

namespace OpenTelemetry.Logs
namespace OpenTelemetry.Logs;

/// <summary>
/// Stores options used to convert log messages into <see cref="ActivityEvent"/>s.
/// </summary>
public class LogToActivityEventConversionOptions
{
/// <summary>
/// Stores options used to convert log messages into <see cref="ActivityEvent"/>s.
/// Gets or sets the callback action used to convert log state into <see cref="ActivityEvent"/> tags.
/// </summary>
public class LogToActivityEventConversionOptions
{
/// <summary>
/// Gets or sets the callback action used to convert log state into <see cref="ActivityEvent"/> tags.
/// </summary>
public Action<ActivityTagsCollection, IReadOnlyList<KeyValuePair<string, object>>> StateConverter { get; set; } = DefaultLogStateConverter.ConvertState;
public Action<ActivityTagsCollection, IReadOnlyList<KeyValuePair<string, object>>> StateConverter { get; set; } = DefaultLogStateConverter.ConvertState;

/// <summary>
/// Gets or sets the callback action used to convert log scopes into <see cref="ActivityEvent"/> tags.
/// </summary>
public Action<ActivityTagsCollection, int, LogRecordScope> ScopeConverter { get; set; } = DefaultLogStateConverter.ConvertScope;
}
/// <summary>
/// Gets or sets the callback action used to convert log scopes into <see cref="ActivityEvent"/> tags.
/// </summary>
public Action<ActivityTagsCollection, int, LogRecordScope> ScopeConverter { get; set; } = DefaultLogStateConverter.ConvertScope;
}
#endif
43 changes: 21 additions & 22 deletions src/OpenTelemetry.Extensions/Logs/OpenTelemetryLoggingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,34 @@
using OpenTelemetry.Internal;
using OpenTelemetry.Logs;

namespace Microsoft.Extensions.Logging
namespace Microsoft.Extensions.Logging;

/// <summary>
/// Contains OpenTelemetry logging SDK extensions.
/// </summary>
public static class OpenTelemetryLoggingExtensions
{
/// <summary>
/// Contains OpenTelemetry logging SDK extensions.
/// Adds a <see cref="LogRecord"/> processor to the OpenTelemetry <see
/// cref="OpenTelemetryLoggerOptions"/> which will convert log messages
/// into <see cref="ActivityEvent"/>s attached to the active <see
/// cref="Activity"/> when the message is written.
/// </summary>
public static class OpenTelemetryLoggingExtensions
/// <param name="loggerOptions"><see cref="OpenTelemetryLoggerOptions"/> options to use.</param>
/// <param name="configure"><see cref="LogToActivityEventConversionOptions"/>.</param>
/// <returns>The instance of <see cref="OpenTelemetryLoggerOptions"/> to chain the calls.</returns>
/// <exception cref="ArgumentNullException"><paramref name="loggerOptions"/> is <c>null</c>.</exception>
public static OpenTelemetryLoggerOptions AttachLogsToActivityEvent(
this OpenTelemetryLoggerOptions loggerOptions,
Action<LogToActivityEventConversionOptions>? configure = null)
{
/// <summary>
/// Adds a <see cref="LogRecord"/> processor to the OpenTelemetry <see
/// cref="OpenTelemetryLoggerOptions"/> which will convert log messages
/// into <see cref="ActivityEvent"/>s attached to the active <see
/// cref="Activity"/> when the message is written.
/// </summary>
/// <param name="loggerOptions"><see cref="OpenTelemetryLoggerOptions"/> options to use.</param>
/// <param name="configure"><see cref="LogToActivityEventConversionOptions"/>.</param>
/// <returns>The instance of <see cref="OpenTelemetryLoggerOptions"/> to chain the calls.</returns>
/// <exception cref="ArgumentNullException"><paramref name="loggerOptions"/> is <c>null</c>.</exception>
public static OpenTelemetryLoggerOptions AttachLogsToActivityEvent(
this OpenTelemetryLoggerOptions loggerOptions,
Action<LogToActivityEventConversionOptions>? configure = null)
{
Guard.ThrowIfNull(loggerOptions);
Guard.ThrowIfNull(loggerOptions);

var options = new LogToActivityEventConversionOptions();
configure?.Invoke(options);
var options = new LogToActivityEventConversionOptions();
configure?.Invoke(options);
#pragma warning disable CA2000 // Dispose objects before losing scope
return loggerOptions.AddProcessor(new ActivityEventAttachingLogProcessor(options));
return loggerOptions.AddProcessor(new ActivityEventAttachingLogProcessor(options));
#pragma warning restore CA2000 // Dispose objects before losing scope
}
}
}
#endif
Loading

0 comments on commit 5b47fd8

Please sign in to comment.