Skip to content
Open
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 @@ -41,11 +41,6 @@ public partial interface IExternalScopeProvider
void ForEachScope<TState>(System.Action<object?, TState> callback, TState state);
System.IDisposable Push(object? state);
}
public partial interface ILogEntryPipelineFactory
{
Microsoft.Extensions.Logging.LogEntryPipeline<TState>? GetLoggingPipeline<TState>(Microsoft.Extensions.Logging.ILogMetadata<TState>? metadata, object? userState);
Microsoft.Extensions.Logging.ScopePipeline<TState>? GetScopePipeline<TState>(Microsoft.Extensions.Logging.ILogMetadata<TState>? metadata, object? userState) where TState : notnull;
}
public partial interface ILogEntryProcessor
{
Microsoft.Extensions.Logging.LogEntryHandler<TState> GetLogEntryHandler<TState>(Microsoft.Extensions.Logging.ILogMetadata<TState>? metadata, out bool enabled, out bool dynamicEnabledCheckRequired);
Expand Down Expand Up @@ -111,12 +106,6 @@ protected LogEntryHandler() { }
public abstract void HandleLogEntry(ref Microsoft.Extensions.Logging.Abstractions.LogEntry<TState> logEntry);
public abstract bool IsEnabled(Microsoft.Extensions.Logging.LogLevel level);
}
public partial class LogEntryPipeline<TState> : Microsoft.Extensions.Logging.Pipeline
{
public LogEntryPipeline(Microsoft.Extensions.Logging.LogEntryHandler<TState> handler, object? userState, bool isEnabled, bool isDynamicLevelCheckRequired) : base (default(object), default(bool), default(bool)) { }
public void HandleLogEntry(ref Microsoft.Extensions.Logging.Abstractions.LogEntry<TState> logEntry) { }
public bool IsEnabledDynamic(Microsoft.Extensions.Logging.LogLevel level) { throw null; }
}
public static partial class LoggerExtensions
{
public static System.IDisposable? BeginScope(this Microsoft.Extensions.Logging.ILogger logger, string messageFormat, params object?[] args) { throw null; }
Expand Down Expand Up @@ -197,11 +186,10 @@ public LoggerMessageAttribute(int eventId, Microsoft.Extensions.Logging.LogLevel
public string Message { get { throw null; } set { } }
public bool SkipEnabledCheck { get { throw null; } set { } }
}
public partial class Logger<T> : Microsoft.Extensions.Logging.ILogEntryPipelineFactory, Microsoft.Extensions.Logging.ILogger, Microsoft.Extensions.Logging.ILogger<T>
public partial class Logger<T> : Microsoft.Extensions.Logging.ILogger, Microsoft.Extensions.Logging.ILogger<T>, Microsoft.Extensions.Logging.ILogEntryProcessorFactory
{
public Logger(Microsoft.Extensions.Logging.ILoggerFactory factory) { }
Microsoft.Extensions.Logging.LogEntryPipeline<TState> Microsoft.Extensions.Logging.ILogEntryPipelineFactory.GetLoggingPipeline<TState>(Microsoft.Extensions.Logging.ILogMetadata<TState>? metadata, object? userState) { throw null; }
Microsoft.Extensions.Logging.ScopePipeline<TState> Microsoft.Extensions.Logging.ILogEntryPipelineFactory.GetScopePipeline<TState>(Microsoft.Extensions.Logging.ILogMetadata<TState>? metadata, object? userState) { throw null; }
public ProcessorContext GetProcessor() { throw null; }
System.IDisposable Microsoft.Extensions.Logging.ILogger.BeginScope<TState>(TState state) { throw null; }
bool Microsoft.Extensions.Logging.ILogger.IsEnabled(Microsoft.Extensions.Logging.LogLevel logLevel) { throw null; }
void Microsoft.Extensions.Logging.ILogger.Log<TState>(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, TState state, System.Exception? exception, System.Func<TState, System.Exception?, string> formatter) { }
Expand All @@ -224,14 +212,6 @@ public partial struct LogPropertyInfo
public readonly object[]? Metadata { get { throw null; } }
public readonly string Name { get { throw null; } }
}
public partial class Pipeline
{
public Pipeline(object? userState, bool isEnabled, bool isDynamicLevelCheckRequired) { }
public bool IsDynamicLevelCheckRequired { get { throw null; } }
public bool IsEnabled { get { throw null; } }
public bool IsUpToDate { get { throw null; } set { } }
public object? UserState { get { throw null; } }
}
public readonly partial struct ProcessorContext
{
private readonly object _dummy;
Expand Down Expand Up @@ -259,11 +239,6 @@ protected ScopeHandler() { }
public abstract System.IDisposable? HandleBeginScope(ref TState state);
public abstract bool IsEnabled(Microsoft.Extensions.Logging.LogLevel level);
}
public partial class ScopePipeline<TState> : Microsoft.Extensions.Logging.Pipeline where TState : notnull
{
public ScopePipeline(Microsoft.Extensions.Logging.ScopeHandler<TState> handler, object? userState, bool isEnabled) : base (default(object), default(bool), default(bool)) { }
public System.IDisposable? HandleScope(ref TState scope) { throw null; }
}
}
namespace Microsoft.Extensions.Logging.Abstractions
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,33 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Threading;
using Microsoft.Extensions.Logging.Abstractions;

namespace Microsoft.Extensions.Logging
{
public interface ILogEntryPipelineFactory
//TODO: Pipeline isn't the best name for this, but leaving it as-is to make the refactor clearer.
//Really it is a single entry in a cache that maps ILogger -> Handler
internal class Pipeline
{
public LogEntryPipeline<TState>? GetLoggingPipeline<TState>(ILogMetadata<TState>? metadata, object? userState);
public ScopePipeline<TState>? GetScopePipeline<TState>(ILogMetadata<TState>? metadata, object? userState) where TState : notnull;
}

public class Pipeline
{
public Pipeline(object? userState, bool isEnabled, bool isDynamicLevelCheckRequired)
public Pipeline(object? userState, bool isEnabled, bool isDynamicLevelCheckRequired, CancellationToken cancelToken)
{
UserState = userState;
IsEnabled = isEnabled;
IsDynamicLevelCheckRequired = isDynamicLevelCheckRequired;
IsUpToDate = true;
CancelToken = cancelToken;
}

public object? UserState { get; }
public bool IsEnabled { get; }
public bool IsDynamicLevelCheckRequired { get; }
public bool IsUpToDate { get; set; }
public CancellationToken CancelToken { get; }
}

public class LogEntryPipeline<TState> : Pipeline
internal class LogEntryPipeline<TState> : Pipeline
{
public LogEntryPipeline(LogEntryHandler<TState> handler, object? userState, bool isEnabled, bool isDynamicLevelCheckRequired) :
base(userState, isEnabled, isDynamicLevelCheckRequired)
public LogEntryPipeline(LogEntryHandler<TState> handler, object? userState, bool isEnabled, bool isDynamicLevelCheckRequired, CancellationToken cancelToken) :
base(userState, isEnabled, isDynamicLevelCheckRequired, cancelToken)
{
_firstHandler = handler;
}
Expand All @@ -42,10 +39,10 @@ public LogEntryPipeline(LogEntryHandler<TState> handler, object? userState, bool
public void HandleLogEntry(ref LogEntry<TState> logEntry) => _firstHandler.HandleLogEntry(ref logEntry);
}

public class ScopePipeline<TState> : Pipeline where TState : notnull
internal class ScopePipeline<TState> : Pipeline where TState : notnull
{
public ScopePipeline(ScopeHandler<TState> handler, object? userState, bool isEnabled) :
base(userState, isEnabled, isDynamicLevelCheckRequired: false)
public ScopePipeline(ScopeHandler<TState> handler, object? userState, bool isEnabled, CancellationToken cancelToken) :
base(userState, isEnabled, isDynamicLevelCheckRequired: false, cancelToken)
{
_firstHandler = handler;
}
Expand All @@ -54,4 +51,27 @@ public ScopePipeline(ScopeHandler<TState> handler, object? userState, bool isEna

public IDisposable? HandleScope(ref TState scope) => _firstHandler.HandleBeginScope(ref scope);
}


internal class InvokeLoggerLogHandler<TState> : LogEntryHandler<TState>
{
private ILogger _logger;
public InvokeLoggerLogHandler(ILogger logger)
{
_logger = logger;
}
public override void HandleLogEntry(ref LogEntry<TState> logEntry) => _logger.Log(logEntry.LogLevel, logEntry.EventId, logEntry.State, logEntry.Exception, logEntry.Formatter);
public override bool IsEnabled(LogLevel level) => _logger.IsEnabled(level);
}

internal class InvokeLoggerScopeHandler<TState> : ScopeHandler<TState> where TState : notnull
{
private ILogger _logger;
public InvokeLoggerScopeHandler(ILogger logger)
{
_logger = logger;
}
public override IDisposable? HandleBeginScope(ref TState state) => _logger.BeginScope(state);
public override bool IsEnabled(LogLevel level) => true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using Microsoft.Extensions.Logging.Abstractions;
using static Microsoft.Extensions.Logging.LoggerMessage;

Expand Down Expand Up @@ -219,43 +220,38 @@ public static Log<TState> Define<TState>(ILogMetadata<TState> metadata, LogDefin

void Log(ILogger logger, ref TState state, Exception? exception)
{
LogEntryPipeline<TState>? pipelineSnapshot = pipeline;
if (pipelineSnapshot != null && pipelineSnapshot.UserState == logger && pipelineSnapshot.IsUpToDate)
{
if (!pipelineSnapshot.IsEnabled ||
(pipelineSnapshot.IsDynamicLevelCheckRequired && needFullEnabledCheck && !pipelineSnapshot.IsEnabledDynamic(metadata.LogLevel)))
return;
LogEntry<TState> entry = new LogEntry<TState>(metadata.LogLevel, category: null!, metadata.EventId, state, exception, null!);
pipelineSnapshot.HandleLogEntry(ref entry);
}
else
{
LogSlowPath(logger, ref state, exception);
}
LogEntry<TState> entry = new LogEntry<TState>(metadata.LogLevel, category: null!, metadata.EventId, state, exception, null!);
LogCore(ref pipeline, logger, metadata, ref entry, needFullEnabledCheck);
}
}

void LogSlowPath(ILogger logger, ref TState state, Exception? exception)
private static void LogCore<TState>(ref LogEntryPipeline<TState>? cachedPipeline, ILogger logger, ILogMetadata<TState>? metadata, ref LogEntry<TState> entry, bool needFullEnabledCheck)
{
if (cachedPipeline == null || cachedPipeline.UserState != logger || cachedPipeline.CancelToken.IsCancellationRequested)
{
LogEntryPipeline<TState>? pipelineSnapshot = null;
LogEntry<TState> entry = new LogEntry<TState>(metadata.LogLevel, category: null!, metadata.EventId, state, exception, null!);
if (logger is ILogEntryPipelineFactory)
{
pipelineSnapshot = ((ILogEntryPipelineFactory)logger).GetLoggingPipeline(metadata, logger);
pipeline = pipelineSnapshot;
}
if (pipelineSnapshot != null)
{
if (!pipelineSnapshot.IsEnabled ||
(pipelineSnapshot.IsDynamicLevelCheckRequired && needFullEnabledCheck && !pipelineSnapshot.IsEnabledDynamic(metadata.LogLevel)))
return;
pipelineSnapshot.HandleLogEntry(ref entry);
}
else
{
if (needFullEnabledCheck && logger.IsEnabled(metadata.LogLevel))
return;
logger.Log(entry.LogLevel, entry.EventId, entry.State, entry.Exception, metadata.GetStringMessageFormatter());
}
cachedPipeline = GetLogEntryPipeline(metadata, logger);
}

if (!cachedPipeline.IsEnabled ||
(cachedPipeline.IsDynamicLevelCheckRequired && needFullEnabledCheck && !cachedPipeline.IsEnabledDynamic(entry.LogLevel)))
{
return;
}

cachedPipeline.HandleLogEntry(ref entry);
}

private static LogEntryPipeline<TState> GetLogEntryPipeline<TState>(ILogMetadata<TState>? metadata, ILogger logger)
{
if (logger is ILogEntryProcessorFactory)
{
ProcessorContext context = ((ILogEntryProcessorFactory)logger).GetProcessor();
LogEntryHandler<TState> handler = context.Processor.GetLogEntryHandler(metadata, out bool enabled, out bool dynamicEnableCheckRequired);
return new LogEntryPipeline<TState>(handler, logger, enabled, dynamicEnableCheckRequired, context.CancellationToken);
}
else
{
return new LogEntryPipeline<TState>(new InvokeLoggerLogHandler<TState>(logger), logger, true, true, CancellationToken.None);
}
}

Expand Down Expand Up @@ -290,46 +286,9 @@ void LogSlowPath(ILogger logger, ref TState state, Exception? exception)

void Log(ILogger logger, T1 arg1, T2 arg2, Exception? exception)
{
LogEntryPipeline<LogValues<T1, T2>>? pipelineSnapshot = pipeline;
if (pipelineSnapshot != null && pipelineSnapshot.UserState == logger && pipelineSnapshot.IsUpToDate)
{
if (!pipelineSnapshot.IsEnabled ||
(pipelineSnapshot.IsDynamicLevelCheckRequired && needFullEnabledCheck && !pipelineSnapshot.IsEnabledDynamic(logLevel)))
return;
LogValues<T1, T2> state = new LogValues<T1, T2>(metadata, arg1, arg2);
LogEntry<LogValues<T1, T2>> entry = new LogEntry<LogValues<T1, T2>>(logLevel, category: null!, eventId, state, exception, LogValues<T1, T2>.Callback);
pipelineSnapshot.HandleLogEntry(ref entry);
}
else
{
LogSlowPath(logger, arg1, arg2, exception);
}
}

void LogSlowPath(ILogger logger, T1 arg1, T2 arg2, Exception? exception)
{
LogEntryPipeline<LogValues<T1, T2>>? pipelineSnapshot = null;
if (logger is ILogEntryPipelineFactory)
{
pipelineSnapshot = ((ILogEntryPipelineFactory)logger).GetLoggingPipeline(metadata, logger);
pipeline = pipelineSnapshot;
}
if (pipelineSnapshot != null)
{
if (!pipelineSnapshot.IsEnabled ||
(pipelineSnapshot.IsDynamicLevelCheckRequired && needFullEnabledCheck && !pipelineSnapshot.IsEnabledDynamic(logLevel)))
return;
LogValues<T1, T2> state = new LogValues<T1, T2>(metadata, arg1, arg2);
LogEntry<LogValues<T1, T2>> entry = new LogEntry<LogValues<T1, T2>>(logLevel, category: null!, eventId, state, exception, LogValues<T1, T2>.Callback);
pipelineSnapshot.HandleLogEntry(ref entry);
}
else
{
if (needFullEnabledCheck && !logger.IsEnabled(logLevel))
return;
LogValues<T1, T2> state = new LogValues<T1, T2>(metadata, arg1, arg2);
logger.Log(logLevel, eventId, state, exception, LogValues<T1, T2>.Callback);
}
LogValues<T1, T2> state = new LogValues<T1, T2>(metadata, arg1, arg2);
LogEntry<LogValues<T1, T2>> entry = new LogEntry<LogValues<T1, T2>>(logLevel, category: null!, eventId, state, exception, LogValues<T1, T2>.Callback);
LogCore(ref pipeline, logger, metadata, ref entry, needFullEnabledCheck);
}
}

Expand Down
Loading