Skip to content

Commit 907c412

Browse files
committed
- Push contexts to stack so they can be read in reverse so that the display makes sense
- Supports multiple scopes each with keyvaluepairs displayed correctly
1 parent 39e53da commit 907c412

File tree

2 files changed

+79
-21
lines changed

2 files changed

+79
-21
lines changed

src/Logging.XUnit/XUnitLogger.cs

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections;
66
using System.Collections.Generic;
7+
using System.Linq;
78
using System.Text;
89
using Microsoft.Extensions.Logging;
910
using Xunit.Abstractions;
@@ -266,32 +267,26 @@ private static string GetLogLevelString(LogLevel logLevel)
266267
private static void GetScopeInformation(StringBuilder builder)
267268
{
268269
var current = XUnitLogScope.Current;
269-
string scopeLog;
270-
int length = builder.Length;
271270

271+
var stack = new Stack<XUnitLogScope>();
272272
while (current != null)
273273
{
274-
foreach (var property in StringifyScope(current))
275-
{
276-
if (length == builder.Length)
277-
{
278-
scopeLog = $"=> {property}";
279-
}
280-
else
281-
{
282-
scopeLog = $"=> {property} ";
283-
}
284-
285-
builder.Insert(length, scopeLog);
286-
}
287-
274+
stack.Push(current);
288275
current = current.Parent;
289276
}
290277

291-
if (builder.Length > length)
278+
var depth = 0;
279+
string DepthPadding(int depth) => new string(' ', depth * 2);
280+
281+
while (stack.Any())
292282
{
293-
builder.Insert(length, MessagePadding);
294-
builder.AppendLine();
283+
var elem = stack.Pop();
284+
foreach (var property in StringifyScope(elem))
285+
{
286+
builder.AppendLine($"{MessagePadding}{DepthPadding(depth)}=> {property}");
287+
}
288+
289+
depth++;
295290
}
296291
}
297292

tests/Logging.XUnit.Tests/XUnitLoggerTests.cs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,12 @@ public static void XUnitLogger_Log_Logs_Message_If_Scopes_Included_And_There_Are
453453

454454
string expected = string.Join(
455455
Environment.NewLine,
456-
new[] { "[2018-08-19 16:12:16Z] info: MyName[0]", " => _ => __ => ___ => [null]", " Message|False|False" });
456+
"[2018-08-19 16:12:16Z] info: MyName[0]",
457+
" => _",
458+
" => __",
459+
" => ___",
460+
" => {OriginalFormat}: [null]",
461+
" Message|False|False");
457462

458463
// Act
459464
using (logger.BeginScope("_"))
@@ -533,7 +538,11 @@ public static void XUnitLogger_Log_Logs_Message_If_Scopes_Included_And_There_Is_
533538

534539
string expected = string.Join(
535540
Environment.NewLine,
536-
new[] { "[2018-08-19 16:12:16Z] info: MyName[0]", " => ScopeKeyThree: ScopeValueThree => ScopeKeyTwo: ScopeValueTwo => ScopeKeyOne: ScopeValueOne", " Message|False|False" });
541+
"[2018-08-19 16:12:16Z] info: MyName[0]",
542+
" => ScopeKeyOne: ScopeValueOne",
543+
" => ScopeKeyTwo: ScopeValueTwo",
544+
" => ScopeKeyThree: ScopeValueThree",
545+
" Message|False|False");
537546

538547
// Act
539548
using (logger.BeginScope(new[]
@@ -550,6 +559,60 @@ public static void XUnitLogger_Log_Logs_Message_If_Scopes_Included_And_There_Is_
550559
mock.Verify((p) => p.WriteLine(expected), Times.Once());
551560
}
552561

562+
[Fact]
563+
public static void XUnitLogger_Log_Logs_Message_If_Scopes_Included_And_There_Are_Scopes_Of_KeyValuePairs()
564+
{
565+
// Arrange
566+
var mock = new Mock<ITestOutputHelper>();
567+
568+
string name = "MyName";
569+
var outputHelper = mock.Object;
570+
571+
var options = new XUnitLoggerOptions()
572+
{
573+
Filter = FilterTrue,
574+
IncludeScopes = true,
575+
};
576+
577+
var logger = new XUnitLogger(name, outputHelper, options)
578+
{
579+
Clock = StaticClock,
580+
};
581+
582+
string expected = string.Join(
583+
Environment.NewLine,
584+
"[2018-08-19 16:12:16Z] info: MyName[0]",
585+
" => ScopeKeyOne: ScopeValueOne",
586+
" => ScopeKeyTwo: ScopeValueTwo",
587+
" => ScopeKeyThree: ScopeValueThree",
588+
" => ScopeKeyFour: ScopeValueFour",
589+
" => ScopeKeyFive: ScopeValueFive",
590+
" => ScopeKeySix: ScopeValueSix",
591+
" Message|False|False");
592+
593+
// Act
594+
using (logger.BeginScope(new[]
595+
{
596+
new KeyValuePair<string, object>("ScopeKeyOne", "ScopeValueOne"),
597+
new KeyValuePair<string, object>("ScopeKeyTwo", "ScopeValueTwo"),
598+
new KeyValuePair<string, object>("ScopeKeyThree", "ScopeValueThree"),
599+
}))
600+
{
601+
using (logger.BeginScope(new[]
602+
{
603+
new KeyValuePair<string, object>("ScopeKeyFour", "ScopeValueFour"),
604+
new KeyValuePair<string, object>("ScopeKeyFive", "ScopeValueFive"),
605+
new KeyValuePair<string, object>("ScopeKeySix", "ScopeValueSix"),
606+
}))
607+
{
608+
logger.Log<string>(LogLevel.Information, 0, null, null, Formatter);
609+
}
610+
}
611+
612+
// Assert
613+
mock.Verify((p) => p.WriteLine(expected), Times.Once());
614+
}
615+
553616
private static DateTimeOffset StaticClock() => new DateTimeOffset(2018, 08, 19, 17, 12, 16, TimeSpan.FromHours(1));
554617

555618
private static bool FilterTrue(string categoryName, LogLevel level) => true;

0 commit comments

Comments
 (0)