@@ -13,7 +13,7 @@ namespace MartinCostello.Logging.XUnit;
1313/// </summary>
1414public partial class XUnitLogger : ILogger
1515{
16- //// Based on https://github.com/aspnet/Logging /blob/master /src/Microsoft.Extensions.Logging.Console/ConsoleLogger.cs
16+ //// Based on https://github.com/dotnet/runtime /blob/65067052e433eda400c5e7cc9f7b21c84640f901 /src/libraries/ Microsoft.Extensions.Logging.Console/src/ ConsoleLogger.cs#L41-L66
1717
1818 /// <summary>
1919 /// The padding to use for log levels.
@@ -36,6 +36,11 @@ public partial class XUnitLogger : ILogger
3636 [ ThreadStatic ]
3737 private static StringBuilder ? _logBuilder ;
3838
39+ /// <summary>
40+ /// The format string used to format the timestamp in log messages.
41+ /// </summary>
42+ private readonly string _timestampFormat ;
43+
3944 /// <summary>
4045 /// Gets or sets the filter to use.
4146 /// </summary>
@@ -50,8 +55,9 @@ private XUnitLogger(string name, XUnitLoggerOptions? options)
5055 {
5156 Name = name ?? throw new ArgumentNullException ( nameof ( name ) ) ;
5257
53- _filter = options ? . Filter ?? ( ( _ , _ ) => true ) ;
58+ _filter = options ? . Filter ?? ( static ( _ , _ ) => true ) ;
5459 _messageSinkMessageFactory = options ? . MessageSinkMessageFactory ?? ( message => new DiagnosticMessage ( message ) ) ;
60+ _timestampFormat = options ? . TimestampFormat ?? "u" ;
5561 IncludeScopes = options ? . IncludeScopes ?? false ;
5662 }
5763
@@ -63,8 +69,8 @@ private XUnitLogger(string name, XUnitLoggerOptions? options)
6369 /// </exception>
6470 public Func < string ? , LogLevel , bool > Filter
6571 {
66- get { return _filter ; }
67- set { _filter = value ?? throw new ArgumentNullException ( nameof ( value ) ) ; }
72+ get => _filter ;
73+ set => _filter = value ?? throw new ArgumentNullException ( nameof ( value ) ) ;
6874 }
6975
7076 /// <summary>
@@ -80,7 +86,7 @@ private XUnitLogger(string name, XUnitLoggerOptions? options)
8086 /// <summary>
8187 /// Gets or sets a delegate representing the system clock.
8288 /// </summary>
83- internal Func < DateTimeOffset > Clock { get ; set ; } = ( ) => DateTimeOffset . Now ;
89+ internal Func < DateTimeOffset > Clock { get ; set ; } = static ( ) => DateTimeOffset . Now ;
8490
8591 /// <inheritdoc />
8692 public IDisposable BeginScope < TState > ( TState state )
@@ -156,7 +162,8 @@ public virtual void WriteMessage(LogLevel logLevel, int eventId, string? message
156162 logBuilder . Append ( Name ) ;
157163 logBuilder . Append ( '[' ) ;
158164 logBuilder . Append ( eventId ) ;
159- logBuilder . AppendLine ( "]" ) ;
165+ logBuilder . Append ( ']' ) ;
166+ logBuilder . AppendLine ( ) ;
160167
161168 if ( IncludeScopes )
162169 {
@@ -184,11 +191,17 @@ public virtual void WriteMessage(LogLevel logLevel, int eventId, string? message
184191 logBuilder . Append ( exception . ToString ( ) ) ;
185192 }
186193
187- string formatted = logBuilder . ToString ( ) ;
194+ // Prefix the formatted message so it renders like this:
195+ // [{timestamp}] {logLevelString}{message}
196+ logBuilder . Insert ( 0 , logLevelString ) ;
197+ logBuilder . Insert ( 0 , "] " ) ;
198+ logBuilder . Insert ( 0 , Clock ( ) . ToString ( _timestampFormat , CultureInfo . CurrentCulture ) ) ;
199+ logBuilder . Insert ( 0 , '[' ) ;
200+
201+ string line = logBuilder . ToString ( ) ;
188202
189203 try
190204 {
191- var line = $ "[{ Clock ( ) : u} ] { logLevelString } { formatted } ";
192205 if ( outputHelper != null )
193206 {
194207 outputHelper . WriteLine ( line ) ;
@@ -228,17 +241,11 @@ private static string GetLogLevelString(LogLevel logLevel)
228241 return logLevel switch
229242 {
230243 LogLevel . Critical => "crit" ,
231-
232244 LogLevel . Debug => "dbug" ,
233-
234245 LogLevel . Error => "fail" ,
235-
236246 LogLevel . Information => "info" ,
237-
238247 LogLevel . Trace => "trce" ,
239-
240248 LogLevel . Warning => "warn" ,
241-
242249 _ => throw new ArgumentOutOfRangeException ( nameof ( logLevel ) ) ,
243250 } ;
244251 }
@@ -267,10 +274,10 @@ private static void GetScopeInformation(StringBuilder builder)
267274 foreach ( var property in StringifyScope ( elem ) )
268275 {
269276 builder . Append ( MessagePadding )
270- . Append ( DepthPadding ( depth ) )
271- . Append ( "=> " )
272- . Append ( property )
273- . AppendLine ( ) ;
277+ . Append ( DepthPadding ( depth ) )
278+ . Append ( "=> " )
279+ . Append ( property )
280+ . AppendLine ( ) ;
274281 }
275282
276283 depth ++ ;
@@ -288,7 +295,7 @@ private static IEnumerable<string> StringifyScope(XUnitLogScope scope)
288295 {
289296 foreach ( var pair in pairs )
290297 {
291- yield return pair . Key + ": " + pair . Value ;
298+ yield return $ " { pair . Key } : { pair . Value } " ;
292299 }
293300 }
294301 else if ( scope . State is IEnumerable < string > entries )
0 commit comments