Created
March 11, 2019 18:40
-
-
Save jeremydmiller/6fb736ca75b0b0f7b3ed6b8d5ec62f69 to your computer and use it in GitHub Desktop.
A strategy to plug ASP.Net Core logging into Storyteller test results
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; | |
using System.Collections.Generic; | |
using Baseline; | |
using Microsoft.Extensions.Logging; | |
using StoryTeller.Results; | |
using StoryTeller.Util; | |
namespace Jasper.TestSupport.Storyteller.Logging | |
{ | |
/// <summary> | |
/// Used to pipe output from the standard ASP.Net Core ILogger interface | |
/// in your application to the Storyteller test results | |
/// </summary> | |
public class StorytellerAspNetCoreLogger : Report, ILoggerProvider | |
{ | |
public StorytellerAspNetCoreLogger(string title = "Logging") | |
{ | |
Title = title; | |
} | |
void IDisposable.Dispose() | |
{ | |
} | |
ILogger ILoggerProvider.CreateLogger(string categoryName) | |
{ | |
return new CategoryLogger(categoryName, this); | |
} | |
// These 3 properties are for Storytller | |
public string Title { get; } | |
string Report.ShortTitle => Title; | |
int Report.Count => Records.Count; | |
// This is the hook that lets you generate raw HTML | |
// that will show up as a tab within the results for a spec | |
string Report.ToHtml() | |
{ | |
var table = new TableTag(); | |
table.AddClass("table").AddClass("table-striped"); | |
table.AddHeaderRow(row => | |
{ | |
row.Header("Category"); | |
row.Header("Level"); | |
row.Header("Message"); | |
}); | |
foreach (var record in Records) | |
{ | |
table.AddBodyRow(row => | |
{ | |
row.Cell(record.Category); | |
row.Cell(record.Level); | |
row.Cell(record.Message); | |
}); | |
// Write out the full stack trace if there's an exception | |
if (record.ExceptionText.IsNotEmpty()) | |
{ | |
table.AddBodyRow(row => | |
{ | |
row.Cell().Attr("colspan", "3").AddClass("bg-warning").Add("pre").AddClass("bg-warning").Text(record.ExceptionText); | |
}); | |
} | |
} | |
return table.ToString(); | |
} | |
internal class LogRecord | |
{ | |
public string Level { get; set; } | |
public string Message { get; set; } | |
public string ExceptionText { get; set; } | |
public string Category { get; set; } | |
} | |
internal class CategoryLogger : ILogger | |
{ | |
private readonly string _categoryName; | |
private readonly StorytellerAspNetCoreLogger _parent; | |
public CategoryLogger(string categoryName, StorytellerAspNetCoreLogger parent) | |
{ | |
_categoryName = categoryName; | |
_parent = parent; | |
} | |
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) | |
{ | |
var logRecord = new LogRecord | |
{ | |
Category = _categoryName, | |
Level = logLevel.ToString(), | |
Message = formatter(state, exception), | |
ExceptionText = exception?.ToString() | |
}; | |
_parent.Records.Add(logRecord); | |
} | |
public bool IsEnabled(LogLevel logLevel) | |
{ | |
return true; | |
} | |
public IDisposable BeginScope<TState>(TState state) | |
{ | |
return new Disposable(); | |
} | |
internal class Disposable : IDisposable | |
{ | |
public void Dispose() | |
{ | |
} | |
} | |
} | |
internal IList<LogRecord> Records { get; private set; } = new List<LogRecord>(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment