using Microsoft.Extensions.Logging; using System; using System.Reactive.Disposables; using Xunit.Abstractions; namespace k8s.Tests.Logging { /// /// An implementation of that writes to the output of the current Xunit test. /// internal sealed class TestOutputLogger : ILogger { /// /// Initializes a new instance of the class. /// Create a new . /// /// /// The output for the current test. /// /// /// The logger's category name. /// /// /// The logger's minimum log level. /// public TestOutputLogger(ITestOutputHelper testOutput, string loggerCategory, LogLevel minLogLevel) { if (testOutput == null) { throw new ArgumentNullException(nameof(testOutput)); } if (string.IsNullOrWhiteSpace(loggerCategory)) { throw new ArgumentException( "Argument cannot be null, empty, or entirely composed of whitespace: 'loggerCategory'.", nameof(loggerCategory)); } TestOutput = testOutput; LoggerCategory = loggerCategory; MinLogLevel = minLogLevel; } /// /// The output for the current test. /// public ITestOutputHelper TestOutput { get; } /// /// The logger's category name. /// public string LoggerCategory { get; } /// /// The logger's minimum log level. /// public LogLevel MinLogLevel { get; } /// /// Emit a log entry. /// /// /// The log entry's level. /// /// /// The log entry's associated event Id. /// /// /// The log entry to be written. Can be also an object. /// /// /// The exception (if any) related to the log entry. /// /// /// A function that creates a string log message from the and . /// public void Log(LogLevel level, EventId eventId, TState state, Exception exception, Func formatter) { if (formatter == null) { throw new ArgumentNullException(nameof(formatter)); } try { TestOutput.WriteLine(string.Format( "[{0}] {1}: {2}", level, LoggerCategory, formatter(state, exception))); if (exception != null) { TestOutput.WriteLine( exception.ToString()); } } catch (Exception e) { // ignore 'There is no currently active test.' if (e.ToString().Contains("There is no currently active test")) { return; } throw; } } /// /// Check if the given is enabled. /// /// /// The level to be checked. /// /// /// true if enabled; otherwise, false. /// public bool IsEnabled(LogLevel logLevel) => logLevel >= MinLogLevel; /// /// Begin a logical operation scope. /// /// /// An identifier for the scope. /// /// /// An that ends the logical operation scope when disposed. /// public IDisposable BeginScope(TState state) => Disposable.Empty; } }