Created
March 1, 2023 19:20
-
-
Save benbrandt22/2ac71eeed151388ef606820bc7606fe7 to your computer and use it in GitHub Desktop.
ILogger / ILoggerFactory implementation to use in XUnit tests for pushing log messages into the test output
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Text; | |
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.Logging; | |
using Xunit.Abstractions; | |
namespace MyGists; | |
public class TestOutputLoggerFactory : ILoggerFactory | |
{ | |
private readonly ITestOutputHelper _testOutputHelper; | |
public TestOutputLoggerFactory(ITestOutputHelper testOutputHelper) | |
{ | |
_testOutputHelper = testOutputHelper; | |
} | |
/// <summary> | |
/// Registers a logger that outputs to the unit test output, to easily display logging messages in unit test results. | |
/// </summary> | |
public static void Register(IServiceCollection serviceCollection, ITestOutputHelper testOutputHelper) | |
=> serviceCollection.AddTransient<ILoggerFactory>(provider => new TestOutputLoggerFactory(testOutputHelper)); | |
public void Dispose() { } | |
public ILogger CreateLogger(string categoryName) => TestOutputLogger.CreateLogger(_testOutputHelper, categoryName); | |
public void AddProvider(ILoggerProvider provider) | |
{ | |
throw new NotImplementedException(); | |
} | |
} | |
public class TestOutputLogger : ILogger | |
{ | |
private readonly ITestOutputHelper _testOutputHelper; | |
private readonly LoggerExternalScopeProvider _scopeProvider; | |
private readonly string _categoryName; | |
public TestOutputLogger(ITestOutputHelper testOutputHelper, LoggerExternalScopeProvider scopeProvider, string categoryName) | |
{ | |
_testOutputHelper = testOutputHelper; | |
_scopeProvider = scopeProvider; | |
_categoryName = categoryName; | |
} | |
public static ILogger CreateLogger(ITestOutputHelper testOutputHelper, string categoryName) => new TestOutputLogger(testOutputHelper, new LoggerExternalScopeProvider(), categoryName); | |
public bool IsEnabled(LogLevel logLevel) => true; | |
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) | |
{ | |
var sb = new StringBuilder(); | |
sb.Append(GetLogLevelString(logLevel)) | |
.Append(" [").Append(_categoryName).Append("] ") | |
.Append(formatter(state, exception)); | |
if (exception != null) | |
{ | |
sb.Append('\n').Append(exception); | |
} | |
_scopeProvider.ForEachScope((scope, s) => | |
{ | |
s.Append("\n => "); | |
s.Append(scope); | |
}, sb); | |
_testOutputHelper.WriteLine(sb.ToString()); | |
} | |
private static string GetLogLevelString(LogLevel logLevel) => | |
logLevel switch | |
{ | |
LogLevel.Trace => "TRACE", | |
LogLevel.Debug => "DEBUG", | |
LogLevel.Information => "INFO ", | |
LogLevel.Warning => "WARN ", | |
LogLevel.Error => "ERROR", | |
LogLevel.Critical => "CRIT ", | |
_ => throw new ArgumentOutOfRangeException(nameof(logLevel)) | |
}; | |
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => _scopeProvider.Push(state); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment