Skip to content
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
361 changes: 190 additions & 171 deletions src/OpenTelemetry/Logs/ILogger/OpenTelemetryLogger.cs

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace OpenTelemetry.Logs
public class OpenTelemetryLoggerOptions
{
internal readonly List<BaseProcessor<LogRecord>> Processors = new();
internal ResourceBuilder ResourceBuilder = ResourceBuilder.CreateDefault();
internal ResourceBuilder? ResourceBuilder;

/// <summary>
/// Gets or sets a value indicating whether or not formatted log message
Expand Down Expand Up @@ -111,5 +111,17 @@ public OpenTelemetryLoggerOptions SetResourceBuilder(ResourceBuilder resourceBui
this.ResourceBuilder = resourceBuilder;
return this;
}

internal OpenTelemetryLoggerOptions Copy()
{
return new()
{
IncludeFormattedMessage = this.IncludeFormattedMessage,
IncludeScopes = this.IncludeScopes,
ParseStateValues = this.ParseStateValues,
IncludeAttributes = this.IncludeAttributes,
IncludeTraceState = this.IncludeTraceState,
};
}
}
}
227 changes: 51 additions & 176 deletions src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@
#nullable enable

using System.Collections;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;

namespace OpenTelemetry.Logs
{
Expand All @@ -32,15 +31,9 @@ namespace OpenTelemetry.Logs
[ProviderAlias("OpenTelemetry")]
public class OpenTelemetryLoggerProvider : BaseProvider, ILoggerProvider, ISupportExternalScope
{
internal readonly bool IncludeAttributes;
internal readonly bool IncludeFormattedMessage;
internal readonly bool IncludeScopes;
internal readonly bool IncludeTraceState;
internal readonly bool ParseStateValues;
internal BaseProcessor<LogRecord>? Processor;
internal Resource Resource;
internal readonly LoggerProvider Provider;
private readonly bool ownsProvider;
private readonly Hashtable loggers = new();
private ILogRecordPool? threadStaticPool = LogRecordThreadStaticPool.Instance;
private bool disposed;

static OpenTelemetryLoggerProvider()
Expand All @@ -54,60 +47,50 @@ static OpenTelemetryLoggerProvider()
/// Initializes a new instance of the <see cref="OpenTelemetryLoggerProvider"/> class.
/// </summary>
/// <param name="options"><see cref="OpenTelemetryLoggerOptions"/>.</param>
// todo: [Obsolete("Use the Sdk.CreateLoggerProviderBuilder method instead this ctor will be removed in a future version.")]
public OpenTelemetryLoggerProvider(IOptionsMonitor<OpenTelemetryLoggerOptions> options)
: this(options?.CurrentValue ?? throw new ArgumentNullException(nameof(options)))
{
}
Guard.ThrowIfNull(options);

internal OpenTelemetryLoggerProvider(IServiceProvider serviceProvider)
: this(
serviceProvider: serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)),
options: serviceProvider?.GetRequiredService<IOptionsMonitor<OpenTelemetryLoggerOptions>>().CurrentValue!)
{
}
var optionsInstance = options.CurrentValue;

internal OpenTelemetryLoggerProvider()
: this(new OpenTelemetryLoggerOptions())
{
}
this.Provider = Sdk
.CreateLoggerProviderBuilder()
.ConfigureBuilder((sp, builder) =>
{
if (optionsInstance.ResourceBuilder != null)
{
builder.SetResourceBuilder(optionsInstance.ResourceBuilder);
}

internal OpenTelemetryLoggerProvider(Action<OpenTelemetryLoggerOptions> configure)
: this(BuildOptions(configure))
{
foreach (var processor in optionsInstance.Processors)
{
builder.AddProcessor(processor);
}
})
.Build();

this.Options = optionsInstance.Copy();
this.ownsProvider = true;
}

internal OpenTelemetryLoggerProvider(OpenTelemetryLoggerOptions options, IServiceProvider? serviceProvider = null)
internal OpenTelemetryLoggerProvider(
LoggerProvider loggerProvider,
OpenTelemetryLoggerOptions options,
bool disposeProvider)
{
OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent("Building OpenTelemetryLoggerProvider.");

Guard.ThrowIfNull(options);

this.ServiceProvider = serviceProvider;

this.IncludeAttributes = options.IncludeAttributes;
this.IncludeFormattedMessage = options.IncludeFormattedMessage;
this.IncludeScopes = options.IncludeScopes;
this.IncludeTraceState = options.IncludeTraceState;
this.ParseStateValues = options.ParseStateValues;

var resourceBuilder = options.ResourceBuilder;
resourceBuilder.ServiceProvider = serviceProvider;
this.Resource = resourceBuilder.Build();
Debug.Assert(loggerProvider != null, "loggerProvider was null");
Debug.Assert(options != null, "options was null");

foreach (var processor in options.Processors)
{
this.AddProcessor(processor);
}

OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent("OpenTelemetryLoggerProvider built successfully.");
this.Provider = loggerProvider!;
this.Options = options!.Copy();
this.ownsProvider = disposeProvider;
}

internal IServiceProvider? ServiceProvider { get; }
internal OpenTelemetryLoggerOptions Options { get; }

internal IExternalScopeProvider? ScopeProvider { get; private set; }

internal ILogRecordPool LogRecordPool => this.threadStaticPool ?? LogRecordSharedPool.Current;

/// <inheritdoc/>
void ISupportExternalScope.SetScopeProvider(IExternalScopeProvider scopeProvider)
{
Expand All @@ -128,17 +111,25 @@ void ISupportExternalScope.SetScopeProvider(IExternalScopeProvider scopeProvider
/// <inheritdoc/>
public ILogger CreateLogger(string categoryName)
{
if (this.loggers[categoryName] is not OpenTelemetryLogger logger)
if (this.loggers[categoryName] is not ILogger logger)
{
lock (this.loggers)
{
logger = (this.loggers[categoryName] as OpenTelemetryLogger)!;
logger = (this.loggers[categoryName] as ILogger)!;
if (logger == null)
{
logger = new OpenTelemetryLogger(categoryName, this)
var loggerProviderSdk = this.Provider as LoggerProviderSdk;
if (loggerProviderSdk == null)
{
logger = NullLogger.Instance;
}
else
{
ScopeProvider = this.ScopeProvider,
};
logger = new OpenTelemetryLogger(loggerProviderSdk, this.Options, categoryName)
{
ScopeProvider = this.ScopeProvider,
};
}

this.loggers[categoryName] = logger;
}
Expand All @@ -148,126 +139,17 @@ public ILogger CreateLogger(string categoryName)
return logger;
}

/// <summary>
/// Flushes all the processors registered under <see
/// cref="OpenTelemetryLoggerProvider"/>, blocks the current thread
/// until flush completed, shutdown signaled or timed out.
/// </summary>
/// <param name="timeoutMilliseconds">
/// The number (non-negative) of milliseconds to wait, or
/// <c>Timeout.Infinite</c> to wait indefinitely.
/// </param>
/// <returns>
/// Returns <c>true</c> when force flush succeeded; otherwise, <c>false</c>.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown when the <c>timeoutMilliseconds</c> is smaller than -1.
/// </exception>
/// <remarks>
/// This function guarantees thread-safety.
/// </remarks>
internal bool ForceFlush(int timeoutMilliseconds = Timeout.Infinite)
{
OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderForceFlushInvoked(timeoutMilliseconds);
return this.Processor?.ForceFlush(timeoutMilliseconds) ?? true;
}

/// <summary>
/// Add a processor to the <see cref="OpenTelemetryLoggerProvider"/>.
/// </summary>
/// <remarks>
/// Note: The supplied <paramref name="processor"/> will be
/// automatically disposed when then the <see
/// cref="OpenTelemetryLoggerProvider"/> is disposed.
/// </remarks>
/// <param name="processor">Log processor to add.</param>
/// <returns>The supplied <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
internal OpenTelemetryLoggerProvider AddProcessor(BaseProcessor<LogRecord> processor)
{
OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent("Started adding processor.");

Guard.ThrowIfNull(processor);

processor.SetParentProvider(this);

StringBuilder processorAdded = new StringBuilder();

if (this.threadStaticPool != null && this.ContainsBatchProcessor(processor))
{
OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent("Using shared thread pool.");

this.threadStaticPool = null;
}

if (this.Processor == null)
{
processorAdded.Append("Setting processor to ");
processorAdded.Append(processor);

this.Processor = processor;
}
else if (this.Processor is CompositeProcessor<LogRecord> compositeProcessor)
{
processorAdded.Append("Adding processor ");
processorAdded.Append(processor);
processorAdded.Append(" to composite processor");

compositeProcessor.AddProcessor(processor);
}
else
{
processorAdded.Append("Creating new composite processor with processor ");
processorAdded.Append(this.Processor);
processorAdded.Append(" and adding new processor ");
processorAdded.Append(processor);

var newCompositeProcessor = new CompositeProcessor<LogRecord>(new[]
{
this.Processor,
});
newCompositeProcessor.SetParentProvider(this);
newCompositeProcessor.AddProcessor(processor);
this.Processor = newCompositeProcessor;
}

OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent($"Completed adding processor = \"{processorAdded}\".");

return this;
}

internal bool ContainsBatchProcessor(BaseProcessor<LogRecord> processor)
{
if (processor is BatchExportProcessor<LogRecord>)
{
return true;
}
else if (processor is CompositeProcessor<LogRecord> compositeProcessor)
{
var current = compositeProcessor.Head;
while (current != null)
{
if (this.ContainsBatchProcessor(current.Value))
{
return true;
}

current = current.Next;
}
}

return false;
}

/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
// Wait for up to 5 seconds grace period
this.Processor?.Shutdown(5000);
this.Processor?.Dispose();
if (this.ownsProvider)
{
this.Provider.Dispose();
}
}

this.disposed = true;
Expand All @@ -276,12 +158,5 @@ protected override void Dispose(bool disposing)

base.Dispose(disposing);
}

private static OpenTelemetryLoggerOptions BuildOptions(Action<OpenTelemetryLoggerOptions> configure)
{
var options = new OpenTelemetryLoggerOptions();
configure?.Invoke(options);
return options;
}
}
}
Loading