Skip to content

Conversation

@snakefoot
Copy link
Contributor

@snakefoot snakefoot commented May 2, 2025

Skip params object[]-allocation when LogLevel is not enabled.

First step for resolving #5537 (Still missing the logic to skip object[]-allocation when message-template with properties like with Microsoft Extension Logging)

Changed NETSTANDARD2.1 to use LangVersion=13 to support params ReadOnlySpan and OverloadResolutionPriority:

Maybe the [OverloadResolutionPriority(-1)] can be a long-game approach for cleaning up the V1 Logger-API with less users affected by the breaking changes (Can cleanup when NET8 has reached end-of-support, some time in 2027)

@snakefoot snakefoot added this to the 6.0 milestone May 2, 2025
@coderabbitai
Copy link

coderabbitai bot commented May 2, 2025

Walkthrough

This update introduces span-based overloads for logging methods throughout the codebase, targeting .NET Standard 2.1 and .NET 9.0 or greater. New overloads for all major logging levels (Trace, Debug, Info, Warn, Error, Fatal) in the Logger, InternalLogger, and LogEventBuilder classes now accept ReadOnlySpan<object> for formatting arguments, reducing allocations. The ILogger and ILoggerBase interfaces receive conditional attributes to control overload resolution priority. An internal OverloadResolutionPriorityAttribute is added for compatibility. The project file and CI configuration are updated for modern platform support, and minor test and formatting changes are included.

Changes

File(s) Change Summary
src/NLog/Common/InternalLogger-generated.cs, src/NLog/Common/InternalLogger.cs, src/NLog/Common/InternalLogger-generated.tt Added span-based overloads for all log level methods in InternalLogger, accepting params ReadOnlySpan<object> arguments; conditional compilation for .NET Standard 2.1+ or .NET 9.0+; no changes to existing logic.
src/NLog/Logger-generated.cs, src/NLog/Logger-generated.tt, src/NLog/Logger.cs Introduced span-based overloads for all log level methods in Logger, accepting params ReadOnlySpan<object>; updated message delegate null check to use Guard.ThrowIfNull; minor formatting cleanup.
src/NLog/Logger-Conditional.cs Added span-based overloads for ConditionalDebug and ConditionalTrace; updated existing overloads to call generic variants; applied [EditorBrowsable] and conditional [OverloadResolutionPriority(-1)] attributes.
src/NLog/LogEventBuilder.cs Added span-based overloads for Properties and Message methods in LogEventBuilder for efficient per-event context and message formatting.
src/NLog/ILogger-V1.cs, src/NLog/ILoggerBase-V1.cs Applied conditional [OverloadResolutionPriority(-1)] attributes to legacy/compatibility method overloads for better overload resolution; imported supporting namespace.
src/NLog/Internal/OverloadResolutionPriorityAttribute.cs Introduced internal sealed OverloadResolutionPriorityAttribute for controlling method overload resolution on older frameworks.
src/NLog/NLog.csproj Updated target frameworks based on Visual Studio version; set C# language version for netstandard2.1; revised supported platforms description.
appveyor.yml Updated build image from Ubuntu 20.04 to 22.04; added MSBUILDTERMINALLOGGER: off to environment variables for Linux builds.
tests/NLog.UnitTests/Fluent/LogEventBuilderTests.cs Clarified overload resolution in test by explicitly casting null to the correct parameter type.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant Logger
    participant InternalLogger
    participant LogEventBuilder

    alt Span-based logging (Logger)
        Caller->>Logger: LogLevel(message, ReadOnlySpan<object> args)
        Logger->>Logger: Convert args to array if not empty
        Logger->>Logger: Create LogEventInfo
        Logger->>Logger: Write LogEventInfo to targets
    end

    alt Span-based logging (InternalLogger)
        Caller->>InternalLogger: LogLevel(message, ReadOnlySpan<object> args)
        InternalLogger->>InternalLogger: Convert args to array if not empty
        InternalLogger->>InternalLogger: Write log entry
    end

    alt Span-based properties (LogEventBuilder)
        Caller->>LogEventBuilder: Properties(ReadOnlySpan<(string, object)>)
        LogEventBuilder->>LogEventBuilder: Set properties from span
    end

    alt Span-based message (LogEventBuilder)
        Caller->>LogEventBuilder: Message(message, ReadOnlySpan<object> args)
        LogEventBuilder->>LogEventBuilder: Set message and parameters
    end
Loading

Poem

🥕
Span-based logs now hop with grace,
Less allocation, a faster race!
New overloads bloom for every need,
With attributes guiding which methods to heed.
From builder to logger, the changes are grand—
This bunny applauds with a twitch of his hand!
🐇


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3cd7f02 and ea3bf73.

📒 Files selected for processing (1)
  • appveyor.yml (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • appveyor.yml

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/NLog/Logger-generated.cs (1)

187-1478: Excellent performance optimization using ReadOnlySpan across all log levels.

The implementation throughout the logger class consistently applies modern C# features to improve performance:

  1. Avoids unnecessary array allocations by using ReadOnlySpan<object> instead of params object[]
  2. Only converts spans to arrays when necessary (when not empty)
  3. Efficiently checks for logger targets directly
  4. Maintains feature parity with existing array-based methods

The conditional compilation ensures these optimizations are only available on platforms that support them (.NET Standard 2.1+ or .NET Core 3.1+).

Consider adding similar span-based overloads for methods that accept both exceptions and arguments in a future update to complete the API surface.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 43e71ed and e27fded.

📒 Files selected for processing (13)
  • src/NLog/Common/InternalLogger-generated.cs (6 hunks)
  • src/NLog/Common/InternalLogger-generated.tt (2 hunks)
  • src/NLog/Common/InternalLogger.cs (1 hunks)
  • src/NLog/ILogger-V1.cs (181 hunks)
  • src/NLog/ILoggerBase-V1.cs (31 hunks)
  • src/NLog/Internal/OverloadResolutionPriorityAttribute.cs (1 hunks)
  • src/NLog/LogEventBuilder.cs (1 hunks)
  • src/NLog/Logger-Conditional.cs (1 hunks)
  • src/NLog/Logger-generated.cs (6 hunks)
  • src/NLog/Logger-generated.tt (3 hunks)
  • src/NLog/Logger.cs (1 hunks)
  • src/NLog/NLog.csproj (2 hunks)
  • tests/NLog.UnitTests/Fluent/LogEventBuilderTests.cs (1 hunks)
🔇 Additional comments (30)
src/NLog/Logger-Conditional.cs (1)

39-39: Adding required namespace for overload resolution attribute.

This adds the System.Runtime.CompilerServices namespace which is needed for the OverloadResolutionPriorityAttribute that will be used to control method overload selection priority in the logging methods.

src/NLog/NLog.csproj (2)

14-14: Updated supported platforms description for accuracy.

The description now clearly specifies .NET Standard 2.0 and 2.1 support instead of the previously more ambiguous ".NET Standard 1.3+ and 2.0+" wording, which better reflects the actual supported platforms.


67-67: Setting C# language version 13 for .NET Standard 2.1 target.

This configuration enables C# 13 language features specifically for the .NET Standard 2.1 target, which is required for the new ReadOnlySpan<object> parameter support in logging methods. This aligns with the PR objectives to leverage C# 13 features for more efficient parameter handling.

tests/NLog.UnitTests/Fluent/LogEventBuilderTests.cs (1)

314-314: Updated test to clarify overload resolution with explicit cast.

The explicit cast to KeyValuePair<string, object>[] ensures the test targets the correct method overload when passing null. This change is necessary because of new ReadOnlySpan-based overloads being added elsewhere in the codebase.

src/NLog/Internal/OverloadResolutionPriorityAttribute.cs (1)

34-60: Well-implemented internal attribute for controlling overload resolution.

This custom implementation of OverloadResolutionPriorityAttribute provides overload resolution control for frameworks that don't include this attribute natively. The implementation follows best practices with:

  1. Proper conditional compilation for compatibility
  2. Appropriate attribute usage targeting (methods, constructors, properties)
  3. Comprehensive XML documentation
  4. Clean implementation with proper parameter validation

This attribute enables the codebase to use [OverloadResolutionPriority(-1)] on legacy method overloads to ensure the new span-based methods are preferred during overload resolution when available.

src/NLog/ILogger-V1.cs (3)

38-38: Addition of System.Runtime.CompilerServices namespace is required for OverloadResolutionPriority attribute

The added namespace import enables the use of the OverloadResolutionPriority attribute which is essential for controlling method overload resolution with the new ReadOnlySpan-based logging methods.


54-57: Strategic use of OverloadResolutionPriority for improved method resolution

The addition of the [OverloadResolutionPriority(-1)] attribute to legacy logging methods ensures correct overload resolution when introducing span-based alternatives. This pattern is applied consistently to all logging method overloads throughout the interface.


77-80: Consistent application of OverloadResolutionPriority to multi-parameter methods

The attribute is correctly applied to multi-parameter logging methods as well, maintaining a consistent approach to overload resolution throughout the interface.

src/NLog/Common/InternalLogger.cs (1)

184-211: Efficient ReadOnlySpan overloads for Log methods

These new overloads using ReadOnlySpan<object> will improve performance by avoiding array allocations. Key implementation points:

  1. Only converts span to array when not empty (args.IsEmpty ? null : args.ToArray())
  2. Guards execution with IsLogLevelEnabled check before parameter processing
  3. Properly compiled for NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
src/NLog/ILoggerBase-V1.cs (3)

38-38: Required namespace import for OverloadResolutionPriority

The System.Runtime.CompilerServices namespace is required for the OverloadResolutionPriority attribute that's used throughout this file to adjust method resolution priority.


54-58: Consistent method resolution approach matches ILogger implementation

The OverloadResolutionPriority approach used here matches that used in ILogger-V1.cs, ensuring a consistent overload resolution strategy across the library's interface hierarchy.


450-453: Comprehensive implementation covers all numeric types

The attribute has been systematically applied to all legacy method overloads, including this one for ulong parameters, ensuring complete coverage across all data types.

src/NLog/Logger.cs (1)

385-421: Well-implemented ReadOnlySpan overloads for improved performance.

These new overloads of the Log method leverage ReadOnlySpan<object> to reduce unnecessary array allocations when passing formatting arguments. The code correctly checks whether targets are available before creating the log event, and only converts the span to an array if it's not empty, which is an excellent optimization.

The conditional compilation (#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER) ensures compatibility with older platforms while enabling the more efficient API on newer frameworks.

src/NLog/Logger-generated.tt (3)

48-48: Added NLog.Internal namespace import for Guard.

The addition of the NLog.Internal namespace import is needed to support the Guard.ThrowIfNull usage in the template.


117-117: Improved null validation using Guard pattern.

Good refactoring to use Guard.ThrowIfNull instead of inline null check, making the code more consistent with the codebase's validation patterns.


163-179: Added span-based logging methods for more efficient parameter passing.

These new conditional overloads for each log level use ReadOnlySpan<object> to reduce unnecessary array allocations. The implementation correctly checks for the log level's enabled status and only converts the span to an array if not empty.

The method signatures and implementation match the pattern used in the main Logger.cs file, maintaining consistency throughout the codebase.

src/NLog/Common/InternalLogger-generated.tt (1)

59-84: Well-designed span-based logging overloads for internal logger.

These new overloads mirror the changes in the public Logger API, enabling more efficient parameter passing without array allocations. The code properly checks if the log level is enabled before proceeding with logging operations, and only converts spans to arrays when necessary.

The conditional compilation ensures backward compatibility while enabling modern API improvements on supported platforms.

src/NLog/Logger-generated.cs (6)

187-203: Well-implemented span-based Trace overload.

This new overload for .NET Standard 2.1+ provides a more efficient way to pass logging arguments without unnecessary array allocations.


442-458: Well-implemented span-based Debug overload.

Follows the same efficient pattern as the Trace method, providing memory allocation benefits on supported platforms.


697-713: Consistent implementation of span-based Info overload.

The Info level implementation maintains the same pattern used throughout the class, ensuring consistent behavior.


952-968: Consistent implementation of span-based Warn overload.

Maintains the pattern established across other log levels, providing efficient argument handling.


1207-1223: Consistent implementation of span-based Error overload.

The Error level implementation follows the established pattern, providing consistent API with performance benefits.


1462-1478: Consistent implementation of span-based Fatal overload.

Completes the set of span-based overloads with consistent implementation across all logging levels.

src/NLog/Common/InternalLogger-generated.cs (7)

73-98: Well-implemented span-based Trace overloads.

These new overloads (with and without exception parameter) provide a more efficient way to pass logging arguments without unnecessary array allocations.


214-239: Well-implemented span-based Debug overloads.

Both overloads follow the same efficient pattern established in the Trace methods, providing memory allocation benefits on supported platforms.


355-380: Consistent implementation of span-based Info overloads.

Both Info level implementations maintain the same pattern used throughout the class, ensuring consistent behavior.


496-521: Consistent implementation of span-based Warn overloads.

Both Warn level implementations follow the established pattern, providing the same efficient API as other log levels.


637-662: Consistent implementation of span-based Error overloads.

The Error level implementations follow the established pattern, maintaining API consistency with other log levels.


778-803: Consistent implementation of span-based Fatal overloads.

Completes the set of span-based overloads with consistent implementation across all logging levels.


73-803: Excellent performance optimization using ReadOnlySpan across all log levels in the InternalLogger.

The implementation consistently applies modern C# features to improve performance:

  1. Avoids unnecessary array allocations by using ReadOnlySpan<object> instead of params object[]
  2. Only converts spans to arrays when necessary (when not empty)
  3. Maintains the same level-checking logic as existing methods
  4. Provides complete API coverage with both exception and non-exception overloads for all log levels

The conditional compilation ensures these optimizations are only available on platforms that support them (.NET Standard 2.1+ or .NET Core 3.1+). This is a well-executed enhancement that maintains backward compatibility while enabling better performance on newer platforms.

@snakefoot snakefoot force-pushed the logger_priority_dev branch 6 times, most recently from 15e72e4 to ccb35d1 Compare May 3, 2025 04:51
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/NLog/Logger-Conditional.cs (3)

39-39: Unconditional using System.Runtime.CompilerServices is safe, but consider conditional inclusion

OverloadResolutionPriorityAttribute is only referenced inside the #if NETSTANDARD2_1_OR_GREATER || NET9_0_OR_GREATER blocks.
To avoid “unused‐using” diagnostics on older target frameworks you could move this using inside the same compilation conditions.

-    using System.Runtime.CompilerServices;
+#if NETSTANDARD2_1_OR_GREATER || NET9_0_OR_GREATER
+    using System.Runtime.CompilerServices;
+#endif

170-182: Minor optimisation: avoid the extra span copy

Debug(message, args) will receive args by value, causing a defensive copy of the ReadOnlySpan<object> struct (16 bytes).
You can forward it by in to prevent that:

-            Debug(message, args);
+            Debug(message, in args);

(This is purely micro-optimisation; feel free to skip if you prefer code consistency.)


283-304: Attribute ordering: place OverloadResolutionPriority first for maximum effect

According to the Roslyn implementation notes, overload-resolution attributes are inspected in declaration order. Placing [OverloadResolutionPriority] before [EditorBrowsable] guarantees it is processed even if another analyser stops walking after the first attribute.

-        [EditorBrowsable(EditorBrowsableState.Never)]
-#if NETSTANDARD2_1_OR_GREATER || NET9_0_OR_GREATER
-        [OverloadResolutionPriority(-1)]
-#endif
+#if NETSTANDARD2_1_OR_GREATER || NET9_0_OR_GREATER
+        [OverloadResolutionPriority(-1)]
+#endif
+        [EditorBrowsable(EditorBrowsableState.Never)]
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1fc5a0e and ccb35d1.

📒 Files selected for processing (13)
  • src/NLog/Common/InternalLogger-generated.cs (7 hunks)
  • src/NLog/Common/InternalLogger-generated.tt (2 hunks)
  • src/NLog/Common/InternalLogger.cs (1 hunks)
  • src/NLog/ILogger-V1.cs (181 hunks)
  • src/NLog/ILoggerBase-V1.cs (31 hunks)
  • src/NLog/Internal/OverloadResolutionPriorityAttribute.cs (1 hunks)
  • src/NLog/LogEventBuilder.cs (2 hunks)
  • src/NLog/Logger-Conditional.cs (53 hunks)
  • src/NLog/Logger-generated.cs (7 hunks)
  • src/NLog/Logger-generated.tt (3 hunks)
  • src/NLog/Logger.cs (1 hunks)
  • src/NLog/NLog.csproj (2 hunks)
  • tests/NLog.UnitTests/Fluent/LogEventBuilderTests.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (12)
  • tests/NLog.UnitTests/Fluent/LogEventBuilderTests.cs
  • src/NLog/NLog.csproj
  • src/NLog/Logger.cs
  • src/NLog/Logger-generated.tt
  • src/NLog/Internal/OverloadResolutionPriorityAttribute.cs
  • src/NLog/Common/InternalLogger.cs
  • src/NLog/Common/InternalLogger-generated.tt
  • src/NLog/LogEventBuilder.cs
  • src/NLog/ILogger-V1.cs
  • src/NLog/ILoggerBase-V1.cs
  • src/NLog/Common/InternalLogger-generated.cs
  • src/NLog/Logger-generated.cs
🔇 Additional comments (1)
src/NLog/Logger-Conditional.cs (1)

106-119: Great to see the new C# 13 params ReadOnlySpan<object> overload

This will eliminate heap allocations for most call-sites.
Two follow-ups to keep in mind:

  1. Unit-tests – make sure there is at least one test that exercises these span-based overloads to guard against accidental regression when LangVersion or TFMs change.
  2. Call-site ambiguity – a call such as ConditionalDebug(ex, "msg", default); can bind both to the object[] and the ReadOnlySpan<object> overload (when default is used). Current Roslyn picks the array version, but please add a unit-test to freeze the behaviour you expect.

@snakefoot snakefoot force-pushed the logger_priority_dev branch from ccb35d1 to 0922493 Compare May 3, 2025 05:10
@snakefoot snakefoot force-pushed the logger_priority_dev branch from c46f03d to 58251fa Compare May 3, 2025 05:38
@snakefoot
Copy link
Contributor Author

snakefoot commented May 3, 2025

LangVersion=13 is only supported with NET9, so had to update AppVeyor from Ubuntu2004 to Ubuntu2204 for NET9-support.

But the console-output from xUnit-tests looks garbled after the change to Ubuntu2204. Seems this is caused by NET9 enabling Terminal Console by default:

And it is fixed by setting environment variable MSBUILDTERMINALLOGGER to off in appyveyor.yml

    environment:
      DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
      MSBUILDTERMINALLOGGER: off

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
tests/NLog.UnitTests/LayoutRenderers/ProcessNameLayoutRendererTests.cs (1)

58-60: Consider making the “allowed process names” list less brittle

Each time the test is executed under a different host (IDE, runner, OS-specific wrapper, etc.) we tend to append another hard-coded string. Over time the list becomes long and still risks missing future hosts.

A more future-proof approach would be:

  • Compare against Process.GetCurrentProcess().ProcessName directly, instead of maintaining a manual allow-list.
  • Or fall back to asserting that the rendered value equals (case-insensitive) the current process name or contains it as a substring.

Example sketch:

var expected = System.Diagnostics.Process.GetCurrentProcess().ProcessName.ToLowerInvariant();
Assert.Contains(expected, lower);

This removes the need to keep this list in sync and avoids false negatives on new runners.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58251fa and c36191f.

📒 Files selected for processing (9)
  • run-tests.ps1 (3 hunks)
  • src/NLog/Internal/XmlHelper.cs (1 hunks)
  • tests/ManuallyLoadedExtension/ManuallyLoadedExtension.csproj (1 hunks)
  • tests/NLog.UnitTests/LayoutRenderers/AssemblyVersionTests.cs (0 hunks)
  • tests/NLog.UnitTests/LayoutRenderers/ProcessNameLayoutRendererTests.cs (1 hunks)
  • tests/NLog.UnitTests/NLog.UnitTests.csproj (3 hunks)
  • tests/NLog.UnitTests/Properties/AssemblyInfo.cs (1 hunks)
  • tests/NLogAutoLoadExtension/NLogAutoLoadExtension.csproj (1 hunks)
  • tests/SampleExtensions/SampleExtensions.csproj (1 hunks)
💤 Files with no reviewable changes (1)
  • tests/NLog.UnitTests/LayoutRenderers/AssemblyVersionTests.cs
✅ Files skipped from review due to trivial changes (4)
  • tests/ManuallyLoadedExtension/ManuallyLoadedExtension.csproj
  • tests/SampleExtensions/SampleExtensions.csproj
  • tests/NLogAutoLoadExtension/NLogAutoLoadExtension.csproj
  • run-tests.ps1
🔇 Additional comments (2)
src/NLog/Internal/XmlHelper.cs (1)

283-283: Excellent improvement for culture-invariant DateTime formatting

This change ensures the DateTime string representation is always formatted using the invariant culture, preventing any potential inconsistencies that could arise from different thread or system culture settings. This is particularly important for XML operations where consistent formatting is critical.

tests/NLog.UnitTests/NLog.UnitTests.csproj (1)

5-6: String comparison on VisualStudioVersion may mis-detect versions

'$(VisualStudioVersion)' < '17.0' performs a lexical comparison, so "9.0" >"17.0" (because '9' >'1').
If someone builds with an older VS (e.g. “9.0” or “10.0”) the condition could yield an unexpected result and select the wrong target framework.

Safer alternatives:

<!-- Convert to integer -->
<PropertyGroup>
  <_VSVersion>$([System.Int32]::Parse('$([System.String]::Copy($(VisualStudioVersion)).Split('.')[0])'))</_VSVersion>
  <TargetFrameworks Condition=" '$(TargetFrameworks)' == '' and $(_VSVersion) &lt; 17 ">net472</TargetFrameworks>
</PropertyGroup>

or consider dropping the VS‐based branching and rely on an explicit TargetFrameworks value.

@snakefoot snakefoot force-pushed the logger_priority_dev branch 4 times, most recently from d31bb98 to be1c73a Compare May 3, 2025 07:22
@snakefoot snakefoot force-pushed the logger_priority_dev branch from be1c73a to cd7e158 Compare May 3, 2025 10:09
@NLog NLog deleted a comment from coderabbitai bot May 3, 2025
@NLog NLog deleted a comment from coderabbitai bot May 3, 2025
@NLog NLog deleted a comment from coderabbitai bot May 3, 2025
@snakefoot snakefoot force-pushed the logger_priority_dev branch from 3cd7f02 to 4a831bb Compare May 3, 2025 11:10
@snakefoot snakefoot force-pushed the logger_priority_dev branch from 4a831bb to ea3bf73 Compare May 3, 2025 11:13
@sonarqubecloud
Copy link

sonarqubecloud bot commented May 3, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@snakefoot snakefoot merged commit 87ed971 into NLog:dev May 3, 2025
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant