From 699e3abf52735392f355f06c05ee14f25e5b1b4f Mon Sep 17 00:00:00 2001
From: Rolf Kristensen <snakefoot@users.noreply.github.com>
Date: Thu, 28 Nov 2024 20:07:50 +0100
Subject: [PATCH] MicrosoftConsoleJsonLayout - Unit Test TimestampFormat (#776)

---
 .../Layouts/MicrosoftConsoleJsonLayout.cs     | 24 +++++++++----------
 .../MicrosoftConsoleJsonLayoutTests.cs        |  9 +++++++
 2 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/src/NLog.Extensions.Logging/Layouts/MicrosoftConsoleJsonLayout.cs b/src/NLog.Extensions.Logging/Layouts/MicrosoftConsoleJsonLayout.cs
index 1ec1e1b8..2b631940 100644
--- a/src/NLog.Extensions.Logging/Layouts/MicrosoftConsoleJsonLayout.cs
+++ b/src/NLog.Extensions.Logging/Layouts/MicrosoftConsoleJsonLayout.cs
@@ -17,16 +17,16 @@ public class MicrosoftConsoleJsonLayout : JsonLayout
     {
         private static readonly string[] EventIdMapper = Enumerable.Range(0, 50).Select(id => id.ToString(System.Globalization.CultureInfo.InvariantCulture)).ToArray();
 
-        private readonly SimpleLayout _timestampLayout = new SimpleLayout("${date:format=o:universalTime=true}");
+        private readonly SimpleLayout _timestampLayout = new SimpleLayout("\"${date:format=o:universalTime=true}\"");
 
         /// <summary>
         /// Initializes a new instance of the <see cref="MicrosoftConsoleJsonLayout" /> class.
         /// </summary>
         public MicrosoftConsoleJsonLayout()
         {
-            Attributes.Add(new JsonAttribute("Timestamp", _timestampLayout));
+            Attributes.Add(new JsonAttribute("Timestamp", _timestampLayout) { Encode = false });
             Attributes.Add(new JsonAttribute("EventId", Layout.FromMethod(evt => LookupEventId(evt), LayoutRenderOptions.ThreadAgnostic)) { Encode = false });
-            Attributes.Add(new JsonAttribute("LogLevel", Layout.FromMethod(evt => ConvertLogLevel(evt.Level), LayoutRenderOptions.ThreadAgnostic)));
+            Attributes.Add(new JsonAttribute("LogLevel", Layout.FromMethod(evt => ConvertLogLevel(evt.Level), LayoutRenderOptions.ThreadAgnostic)) { Encode = false });
             Attributes.Add(new JsonAttribute("Category", "${logger}"));
             Attributes.Add(new JsonAttribute("Message", "${message}"));
             Attributes.Add(new JsonAttribute("Exception", "${replace-newlines:${exception:format=tostring,data}}"));
@@ -79,7 +79,7 @@ public string TimestampFormat
             get
             {
                 var index = LookupNamedAttributeIndex("Timestamp");
-                return index >= 0 ? ((Attributes[index].Layout as SimpleLayout)?.LayoutRenderers?.FirstOrDefault() as DateLayoutRenderer)?.Format : null;
+                return index >= 0 ? ((Attributes[index].Layout as SimpleLayout)?.LayoutRenderers?.OfType<DateLayoutRenderer>().FirstOrDefault())?.Format : null;
             }
             set
             {
@@ -91,9 +91,9 @@ public string TimestampFormat
                 
                 if (!string.IsNullOrEmpty(value))
                 {
-                    var dateLayoutRenderer = _timestampLayout.LayoutRenderers.First() as DateLayoutRenderer;
+                    var dateLayoutRenderer = _timestampLayout.LayoutRenderers.OfType<DateLayoutRenderer>().First();
                     dateLayoutRenderer.Format = value;
-                    Attributes.Insert(0, new JsonAttribute("Timestamp", _timestampLayout));
+                    Attributes.Insert(0, new JsonAttribute("Timestamp", _timestampLayout) { Encode = false });
                 }
             }
         }
@@ -144,17 +144,17 @@ private static string ConvertEventId(int eventId)
         private static string ConvertLogLevel(LogLevel logLevel)
         {
             if (logLevel == LogLevel.Trace)
-                return nameof(Microsoft.Extensions.Logging.LogLevel.Trace);
+                return "\"" + nameof(Microsoft.Extensions.Logging.LogLevel.Trace) + "\"";
             else if (logLevel == LogLevel.Debug)
-                return nameof(Microsoft.Extensions.Logging.LogLevel.Debug);
+                return "\"" + nameof(Microsoft.Extensions.Logging.LogLevel.Debug) + "\"";
             else if (logLevel == LogLevel.Info)
-                return nameof(Microsoft.Extensions.Logging.LogLevel.Information);
+                return "\"" + nameof(Microsoft.Extensions.Logging.LogLevel.Information) + "\"";
             else if (logLevel == LogLevel.Warn)
-                return nameof(Microsoft.Extensions.Logging.LogLevel.Warning);
+                return "\"" + nameof(Microsoft.Extensions.Logging.LogLevel.Warning) + "\"";
             else if (logLevel == LogLevel.Error)
-                return nameof(Microsoft.Extensions.Logging.LogLevel.Error);
+                return "\"" + nameof(Microsoft.Extensions.Logging.LogLevel.Error) + "\"";
             else
-                return nameof(Microsoft.Extensions.Logging.LogLevel.Critical);
+                return "\"" + nameof(Microsoft.Extensions.Logging.LogLevel.Critical) + "\"";
         }
     }
 }
diff --git a/test/NLog.Extensions.Logging.Tests/MicrosoftConsoleJsonLayoutTests.cs b/test/NLog.Extensions.Logging.Tests/MicrosoftConsoleJsonLayoutTests.cs
index 73c81244..c69e6d99 100644
--- a/test/NLog.Extensions.Logging.Tests/MicrosoftConsoleJsonLayoutTests.cs
+++ b/test/NLog.Extensions.Logging.Tests/MicrosoftConsoleJsonLayoutTests.cs
@@ -17,6 +17,15 @@ public void MicrosoftConsoleJsonLayout_NullEvent()
             Assert.Contains("{ \"EventId\": 0, \"LogLevel\": \"Critical\" }", result);
         }
 
+        [Fact]
+        public void MicrosoftConsoleJsonLayout_TimestampFormat()
+        {
+            var layout = new MicrosoftConsoleJsonLayout() { TimestampFormat = "R" };
+            var logEvent = new LogEventInfo(LogLevel.Error, "MyLogger", "Hello World");
+            var result = layout.Render(logEvent);
+            Assert.Equal($"{{ \"Timestamp\": \"{logEvent.TimeStamp.ToUniversalTime().ToString("R")}\", \"EventId\": {0}, \"LogLevel\": \"Error\", \"Category\": \"MyLogger\", \"Message\": \"Hello World\", \"State\": {{ \"{{OriginalFormat}}\": \"Hello World\" }} }}", result);
+        }
+
         [Fact]
         public void MicrosoftConsoleJsonLayout_ExceptionEvent()
         {