Last active
March 11, 2018 06:20
-
-
Save dennisroche/530234f16a94c8c1ee1a41bd94c1ba88 to your computer and use it in GitHub Desktop.
xUnit2 and BDDfy logging with Serilog
This file contains hidden or 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
internal static class LogHelper | |
{ | |
private static readonly AsyncLocal<Guid> TestCorrelationId = new AsyncLocal<Guid>(); | |
private static readonly ConcurrentDictionary<Guid, XUnitBddfyTextReporter> BddfyTextReporterLookup = new ConcurrentDictionary<Guid, XUnitBddfyTextReporter>(); | |
private static readonly ConcurrentDictionary<Guid, ITestOutputHelper> LoggerLookup = new ConcurrentDictionary<Guid, ITestOutputHelper>(); | |
private static readonly ConcurrentDictionary<Guid, ILogger> SerilogLookup = new ConcurrentDictionary<Guid, ILogger>(); | |
public static IDisposable Capture(ITestOutputHelper outputHelper) | |
{ | |
if (outputHelper == null) | |
throw new ArgumentNullException(nameof(outputHelper)); | |
var correlationId = Guid.NewGuid(); | |
LoggerLookup.TryAdd(correlationId, outputHelper); | |
BddfyTextReporterLookup.TryAdd(correlationId, new XUnitBddfyTextReporter()); | |
SerilogLookup.TryAdd(correlationId, CreateLogger()); | |
TestCorrelationId.Value = correlationId; | |
return new DelegateDisposable(() => | |
{ | |
LoggerLookup.TryRemove(correlationId, out ITestOutputHelper removedHelper); | |
BddfyTextReporterLookup.TryRemove(correlationId, out XUnitBddfyTextReporter removedBddfyTextReporter); | |
SerilogLookup.TryRemove(correlationId, out ILogger removedLogger); | |
}); | |
} | |
public static bool TryGetTestOutputHelper(out ITestOutputHelper testOutputHelper) | |
{ | |
return LoggerLookup.TryGetValue(TestCorrelationId.Value, out testOutputHelper); | |
} | |
public static bool TryBddfyReporter(out XUnitBddfyTextReporter reporter) | |
{ | |
return BddfyTextReporterLookup.TryGetValue(TestCorrelationId.Value, out reporter); | |
} | |
public static bool TryGetLogger(out ILogger logger) | |
{ | |
return SerilogLookup.TryGetValue(TestCorrelationId.Value, out logger); | |
} | |
static LogHelper() | |
{ | |
Configurator.Processors.Add(() => | |
{ | |
TryBddfyReporter(out XUnitBddfyTextReporter reporter); | |
return reporter; | |
}); | |
} | |
private static ILogger CreateLogger() | |
{ | |
return new LoggerConfiguration() | |
.MinimumLevel.Debug() | |
.MinimumLevel.Override("IdentityServer", LogEventLevel.Warning) | |
.MinimumLevel.Override("Microsoft", LogEventLevel.Fatal) | |
.MinimumLevel.Override("System", LogEventLevel.Warning) | |
.Enrich.WithDemystifiedStackTraces() | |
.WriteTo.Sink<XUnitLogContextSink>() | |
.WriteTo.LiterateConsole() | |
.CreateLogger(); | |
} | |
private class DelegateDisposable : IDisposable | |
{ | |
public DelegateDisposable(Action action) | |
{ | |
_action = action; | |
} | |
public void Dispose() | |
{ | |
_action(); | |
} | |
private readonly Action _action; | |
} | |
} |
This file contains hidden or 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
public class SerilogTestBase : IDisposable | |
{ | |
protected SerilogTestBase(ITestOutputHelper outputHelper) | |
{ | |
_logger = LogHelper.Capture(outputHelper); | |
} | |
public static ILogger Log | |
{ | |
get | |
{ | |
LogHelper.TryGetLogger(out ILogger log); | |
return log; | |
} | |
} | |
public virtual void Dispose() | |
{ | |
_logger.Dispose(); | |
} | |
private readonly IDisposable _logger; | |
} |
This file contains hidden or 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
internal class XUnitBddfyTextReporter : IProcessor | |
{ | |
public void Process(Story story) | |
{ | |
if (!LogHelper.TryGetTestOutputHelper(out ITestOutputHelper logger)) | |
return; | |
var reporter = new TextReporter(); | |
reporter.Process(story); | |
logger.WriteLine(reporter.ToString()); | |
} | |
public ProcessType ProcessType => ProcessType.Report; | |
} |
This file contains hidden or 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
public class XUnitLogContextSink : ILogEventSink | |
{ | |
public void Emit(LogEvent logEvent) | |
{ | |
if (!LogHelper.TryGetTestOutputHelper(out ITestOutputHelper logger)) | |
return; | |
var buffer = new StringBuilder(); | |
using (var writer = new StringWriter(buffer)) | |
logEvent.RenderMessage(writer, null); | |
logger.WriteLine(buffer.ToString()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment