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 (AggregateException e)
{
// ignore 'There is no currently active test.'
foreach (var inner in e.InnerExceptions)
{
if (inner.Message.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;
}
}