diff --git a/test/TestBuildingBlocks/LogOutputFields.cs b/test/TestBuildingBlocks/LogOutputFields.cs index 02ea580eff..c6a1475579 100644 --- a/test/TestBuildingBlocks/LogOutputFields.cs +++ b/test/TestBuildingBlocks/LogOutputFields.cs @@ -8,10 +8,12 @@ public enum LogOutputFields { None = 0, Level = 1, - Category = 1 << 1, - Message = 1 << 2, - Exception = 1 << 3, - Scopes = 1 << 4, + CategoryName = 1 << 1, + CategoryNamespace = 1 << 2, + Message = 1 << 3, + Exception = 1 << 4, + Scopes = 1 << 5, + Category = CategoryName | CategoryNamespace, All = Level | Category | Message | Exception | Scopes } diff --git a/test/TestBuildingBlocks/XUnitLoggerProvider.cs b/test/TestBuildingBlocks/XUnitLoggerProvider.cs index a6214032af..26c15d575b 100644 --- a/test/TestBuildingBlocks/XUnitLoggerProvider.cs +++ b/test/TestBuildingBlocks/XUnitLoggerProvider.cs @@ -8,11 +8,12 @@ namespace TestBuildingBlocks; // Based on https://www.meziantou.net/how-to-get-asp-net-core-logs-in-the-output-of-xunit-tests.htm. public sealed class XUnitLoggerProvider : ILoggerProvider { + private const LogOutputFields DefaultLogOutputFields = LogOutputFields.All & ~LogOutputFields.CategoryNamespace; private readonly ITestOutputHelper _testOutputHelper; private readonly LogOutputFields _outputFields; private readonly string? _categoryPrefixFilter; - public XUnitLoggerProvider(ITestOutputHelper testOutputHelper, string? categoryPrefixFilter, LogOutputFields outputFields = LogOutputFields.All) + public XUnitLoggerProvider(ITestOutputHelper testOutputHelper, string? categoryPrefixFilter, LogOutputFields outputFields = DefaultLogOutputFields) { ArgumentNullException.ThrowIfNull(testOutputHelper); @@ -41,7 +42,34 @@ private sealed class XUnitLogger(ITestOutputHelper testOutputHelper, LogOutputFi { private readonly ITestOutputHelper _testOutputHelper = testOutputHelper; private readonly LogOutputFields _outputFields = outputFields; - private readonly string _categoryName = categoryName; + private readonly string? _categoryText = GetCategoryText(categoryName, outputFields); + + private static string? GetCategoryText(string categoryName, LogOutputFields outputFields) + { + if (outputFields.HasFlag(LogOutputFields.Category)) + { + return categoryName; + } + + bool hasName = outputFields.HasFlag(LogOutputFields.CategoryName); + bool hasNamespace = outputFields.HasFlag(LogOutputFields.CategoryNamespace); + + if (hasName || hasNamespace) + { + // Microsoft.Extensions.Logging.LoggerFactory.CreateLogger(Type) removes generic type parameters + // and replaces '+' (nested class) with '.'. + int lastDotIndex = categoryName.LastIndexOf('.'); + + if (lastDotIndex == -1) + { + return hasName ? categoryName : string.Empty; + } + + return hasName ? categoryName[(lastDotIndex + 1)..] : categoryName[..lastDotIndex]; + } + + return null; + } public bool IsEnabled(LogLevel logLevel) { @@ -68,7 +96,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except builder.Append(logLevelString); } - if (_outputFields.HasFlag(LogOutputFields.Category)) + if (_categoryText != null) { if (builder.Length > 0) { @@ -76,7 +104,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except } builder.Append('['); - builder.Append(_categoryName); + builder.Append(_categoryText); builder.Append(']'); }