From f9f921246bec594c3420ff07bbad003bd9d3be4f Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 17 May 2022 10:07:07 +0100 Subject: [PATCH 1/5] Bump version to 0.3.0 Bump version to 0.3.0 for the next release. --- Directory.Build.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 6d37cff8..c555de63 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -37,8 +37,8 @@ true snupkg true - 0.2.0.0 - 0.2.2 + 0.3.0.0 + 0.3.0 beta$([System.Convert]::ToInt32(`$(GITHUB_RUN_NUMBER)`).ToString(`0000`)) $(GITHUB_REF.Replace('refs/tags/v', '')) From 79bfb2dd76612daf72d9f1eb0155b0d93f64f369 Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 17 May 2022 10:08:22 +0100 Subject: [PATCH 2/5] Minor refactoring - Tidy up whitespace. - Use expression-bodied property. - Use interpolated string. --- src/Logging.XUnit/XUnitLogger.cs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/Logging.XUnit/XUnitLogger.cs b/src/Logging.XUnit/XUnitLogger.cs index 6a3f1dd1..85b8c079 100644 --- a/src/Logging.XUnit/XUnitLogger.cs +++ b/src/Logging.XUnit/XUnitLogger.cs @@ -63,8 +63,8 @@ private XUnitLogger(string name, XUnitLoggerOptions? options) /// public Func Filter { - get { return _filter; } - set { _filter = value ?? throw new ArgumentNullException(nameof(value)); } + get => _filter; + set => _filter = value ?? throw new ArgumentNullException(nameof(value)); } /// @@ -228,17 +228,11 @@ private static string GetLogLevelString(LogLevel logLevel) return logLevel switch { LogLevel.Critical => "crit", - LogLevel.Debug => "dbug", - LogLevel.Error => "fail", - LogLevel.Information => "info", - LogLevel.Trace => "trce", - LogLevel.Warning => "warn", - _ => throw new ArgumentOutOfRangeException(nameof(logLevel)), }; } @@ -267,10 +261,10 @@ private static void GetScopeInformation(StringBuilder builder) foreach (var property in StringifyScope(elem)) { builder.Append(MessagePadding) - .Append(DepthPadding(depth)) - .Append("=> ") - .Append(property) - .AppendLine(); + .Append(DepthPadding(depth)) + .Append("=> ") + .Append(property) + .AppendLine(); } depth++; @@ -288,7 +282,7 @@ private static IEnumerable StringifyScope(XUnitLogScope scope) { foreach (var pair in pairs) { - yield return pair.Key + ": " + pair.Value; + yield return $"{pair.Key}: {pair.Value}"; } } else if (scope.State is IEnumerable entries) From 2c68de7fb424e1ac45046f8cd649b1f6ebed901b Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 17 May 2022 10:08:53 +0100 Subject: [PATCH 3/5] Make lambdas static Make a number of lambda methods explicitly static. --- src/Logging.XUnit/XUnitLogger.cs | 4 ++-- src/Logging.XUnit/XUnitLoggerExtensions.IMessageSink.cs | 6 +++--- .../XUnitLoggerExtensions.ITestOutputHelper.cs | 8 ++++---- src/Logging.XUnit/XUnitLoggerOptions.cs | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Logging.XUnit/XUnitLogger.cs b/src/Logging.XUnit/XUnitLogger.cs index 85b8c079..8d214d3d 100644 --- a/src/Logging.XUnit/XUnitLogger.cs +++ b/src/Logging.XUnit/XUnitLogger.cs @@ -50,7 +50,7 @@ private XUnitLogger(string name, XUnitLoggerOptions? options) { Name = name ?? throw new ArgumentNullException(nameof(name)); - _filter = options?.Filter ?? ((_, _) => true); + _filter = options?.Filter ?? (static (_, _) => true); _messageSinkMessageFactory = options?.MessageSinkMessageFactory ?? (message => new DiagnosticMessage(message)); IncludeScopes = options?.IncludeScopes ?? false; } @@ -80,7 +80,7 @@ private XUnitLogger(string name, XUnitLoggerOptions? options) /// /// Gets or sets a delegate representing the system clock. /// - internal Func Clock { get; set; } = () => DateTimeOffset.Now; + internal Func Clock { get; set; } = static () => DateTimeOffset.Now; /// public IDisposable BeginScope(TState state) diff --git a/src/Logging.XUnit/XUnitLoggerExtensions.IMessageSink.cs b/src/Logging.XUnit/XUnitLoggerExtensions.IMessageSink.cs index d29df0be..e0ef664a 100644 --- a/src/Logging.XUnit/XUnitLoggerExtensions.IMessageSink.cs +++ b/src/Logging.XUnit/XUnitLoggerExtensions.IMessageSink.cs @@ -36,7 +36,7 @@ public static ILoggingBuilder AddXUnit(this ILoggingBuilder builder, IMessageSin throw new ArgumentNullException(nameof(accessor)); } - return builder.AddXUnit(accessor, (_) => { }); + return builder.AddXUnit(accessor, static (_) => { }); } /// @@ -104,7 +104,7 @@ public static ILoggingBuilder AddXUnit(this ILoggingBuilder builder, IMessageSin throw new ArgumentNullException(nameof(messageSink)); } - return builder.AddXUnit(messageSink, (_) => { }); + return builder.AddXUnit(messageSink, static (_) => { }); } /// @@ -227,7 +227,7 @@ public static ILoggerFactory AddXUnit(this ILoggerFactory factory, IMessageSink throw new ArgumentNullException(nameof(messageSink)); } - return factory.AddXUnit(messageSink, (_) => { }); + return factory.AddXUnit(messageSink, static (_) => { }); } /// diff --git a/src/Logging.XUnit/XUnitLoggerExtensions.ITestOutputHelper.cs b/src/Logging.XUnit/XUnitLoggerExtensions.ITestOutputHelper.cs index 17108734..a95a423c 100644 --- a/src/Logging.XUnit/XUnitLoggerExtensions.ITestOutputHelper.cs +++ b/src/Logging.XUnit/XUnitLoggerExtensions.ITestOutputHelper.cs @@ -31,7 +31,7 @@ public static ILoggingBuilder AddXUnit(this ILoggingBuilder builder) throw new ArgumentNullException(nameof(builder)); } - return builder.AddXUnit(new AmbientTestOutputHelperAccessor(), (_) => { }); + return builder.AddXUnit(new AmbientTestOutputHelperAccessor(), static (_) => { }); } /// @@ -57,7 +57,7 @@ public static ILoggingBuilder AddXUnit(this ILoggingBuilder builder, ITestOutput throw new ArgumentNullException(nameof(accessor)); } - return builder.AddXUnit(accessor, (_) => { }); + return builder.AddXUnit(accessor, static (_) => { }); } /// @@ -125,7 +125,7 @@ public static ILoggingBuilder AddXUnit(this ILoggingBuilder builder, ITestOutput throw new ArgumentNullException(nameof(outputHelper)); } - return builder.AddXUnit(outputHelper, (_) => { }); + return builder.AddXUnit(outputHelper, static (_) => { }); } /// @@ -248,7 +248,7 @@ public static ILoggerFactory AddXUnit(this ILoggerFactory factory, ITestOutputHe throw new ArgumentNullException(nameof(outputHelper)); } - return factory.AddXUnit(outputHelper, (_) => { }); + return factory.AddXUnit(outputHelper, static (_) => { }); } /// diff --git a/src/Logging.XUnit/XUnitLoggerOptions.cs b/src/Logging.XUnit/XUnitLoggerOptions.cs index f4cc85b7..18e7a70a 100644 --- a/src/Logging.XUnit/XUnitLoggerOptions.cs +++ b/src/Logging.XUnit/XUnitLoggerOptions.cs @@ -22,12 +22,12 @@ public XUnitLoggerOptions() /// /// Gets or sets the category filter to apply to logs. /// - public Func Filter { get; set; } = (c, l) => true; // By default log everything + public Func Filter { get; set; } = static (c, l) => true; // By default log everything /// /// Gets or sets the message sink message factory to use when writing to a . /// - public Func MessageSinkMessageFactory { get; set; } = m => new DiagnosticMessage(m); + public Func MessageSinkMessageFactory { get; set; } = static (m) => new DiagnosticMessage(m); /// /// Gets or sets a value indicating whether to include scopes. From 3038ad23a085bf99b138ca5859c3ea8ea541c8ac Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 17 May 2022 10:27:54 +0100 Subject: [PATCH 4/5] Support custom timestamp format Support customising the format of the timestamps. Resolves #311. --- src/Logging.XUnit/XUnitLogger.cs | 21 +++++++++++++++---- src/Logging.XUnit/XUnitLoggerOptions.cs | 8 +++++++ tests/Logging.XUnit.Tests/IntegrationTests.cs | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/Logging.XUnit/XUnitLogger.cs b/src/Logging.XUnit/XUnitLogger.cs index 8d214d3d..17568f0c 100644 --- a/src/Logging.XUnit/XUnitLogger.cs +++ b/src/Logging.XUnit/XUnitLogger.cs @@ -13,7 +13,7 @@ namespace MartinCostello.Logging.XUnit; /// public partial class XUnitLogger : ILogger { - //// Based on https://github.com/aspnet/Logging/blob/master/src/Microsoft.Extensions.Logging.Console/ConsoleLogger.cs + //// Based on https://github.com/dotnet/runtime/blob/65067052e433eda400c5e7cc9f7b21c84640f901/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLogger.cs#L41-L66 /// /// The padding to use for log levels. @@ -36,6 +36,11 @@ public partial class XUnitLogger : ILogger [ThreadStatic] private static StringBuilder? _logBuilder; + /// + /// The format string used to format the timestamp in log messages. + /// + private readonly string _timestampFormat; + /// /// Gets or sets the filter to use. /// @@ -52,6 +57,7 @@ private XUnitLogger(string name, XUnitLoggerOptions? options) _filter = options?.Filter ?? (static (_, _) => true); _messageSinkMessageFactory = options?.MessageSinkMessageFactory ?? (message => new DiagnosticMessage(message)); + _timestampFormat = options?.TimestampFormat ?? "u"; IncludeScopes = options?.IncludeScopes ?? false; } @@ -156,7 +162,8 @@ public virtual void WriteMessage(LogLevel logLevel, int eventId, string? message logBuilder.Append(Name); logBuilder.Append('['); logBuilder.Append(eventId); - logBuilder.AppendLine("]"); + logBuilder.Append(']'); + logBuilder.AppendLine(); if (IncludeScopes) { @@ -184,11 +191,17 @@ public virtual void WriteMessage(LogLevel logLevel, int eventId, string? message logBuilder.Append(exception.ToString()); } - string formatted = logBuilder.ToString(); + // Prefix the formatted message so it renders like this: + // [{timestamp}] {logLevelString}{message} + logBuilder.Insert(0, logLevelString); + logBuilder.Insert(0, "] "); + logBuilder.Insert(0, Clock().ToString(_timestampFormat, CultureInfo.CurrentCulture)); + logBuilder.Insert(0, '['); + + string line = logBuilder.ToString(); try { - var line = $"[{Clock():u}] {logLevelString}{formatted}"; if (outputHelper != null) { outputHelper.WriteLine(line); diff --git a/src/Logging.XUnit/XUnitLoggerOptions.cs b/src/Logging.XUnit/XUnitLoggerOptions.cs index 18e7a70a..06883793 100644 --- a/src/Logging.XUnit/XUnitLoggerOptions.cs +++ b/src/Logging.XUnit/XUnitLoggerOptions.cs @@ -33,4 +33,12 @@ public XUnitLoggerOptions() /// Gets or sets a value indicating whether to include scopes. /// public bool IncludeScopes { get; set; } + + /// + /// Gets or sets format string used to format the timestamp in log messages. Defaults to u. + /// +#if NET7_0_OR_GREATER + [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] +#endif + public string? TimestampFormat { get; set; } } diff --git a/tests/Logging.XUnit.Tests/IntegrationTests.cs b/tests/Logging.XUnit.Tests/IntegrationTests.cs index 98854fd4..b73b6057 100644 --- a/tests/Logging.XUnit.Tests/IntegrationTests.cs +++ b/tests/Logging.XUnit.Tests/IntegrationTests.cs @@ -177,6 +177,7 @@ public static void Can_Configure_xunit_For_ILoggerFactory_With_Options_Factory() var options = new XUnitLoggerOptions() { Filter = (_, level) => level >= LogLevel.Error, + TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff", }; var logger = BootstrapFactory((builder) => builder.AddXUnit(mock.Object, () => options)); From 18a6af803bcdbd8d7b98d3386f2eea36ea1230b2 Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 17 May 2022 11:09:44 +0100 Subject: [PATCH 5/5] Add TODO comment Add TODO comment for [StringSyntax]. --- src/Logging.XUnit/XUnitLoggerOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Logging.XUnit/XUnitLoggerOptions.cs b/src/Logging.XUnit/XUnitLoggerOptions.cs index 06883793..516746d7 100644 --- a/src/Logging.XUnit/XUnitLoggerOptions.cs +++ b/src/Logging.XUnit/XUnitLoggerOptions.cs @@ -38,7 +38,7 @@ public XUnitLoggerOptions() /// Gets or sets format string used to format the timestamp in log messages. Defaults to u. /// #if NET7_0_OR_GREATER - [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] + [StringSyntax(StringSyntaxAttribute.DateTimeFormat)] // TODO Light up after .NET 7 ships https://github.com/martincostello/xunit-logging/issues/315 #endif public string? TimestampFormat { get; set; } }