Skip to content

NLogConfigurationItem - ToString returns Name and Value#6132

Merged
snakefoot merged 1 commit intoNLog:devfrom
snakefoot:attrib_tostring
Mar 29, 2026
Merged

NLogConfigurationItem - ToString returns Name and Value#6132
snakefoot merged 1 commit intoNLog:devfrom
snakefoot:attrib_tostring

Conversation

@snakefoot
Copy link
Copy Markdown
Contributor

No description provided.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 29, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Refactors InternalLogger environment-variable expansion to only run when % is present and guards token replacements; adds several ToString() overrides to layout/target classes to produce consistent {Name}={Layout} (with conditional encoding text for JSON/XML attributes).

Changes

Cohort / File(s) Summary
Environment Variable Expansion
src/NLog/Common/InternalLogger.cs
ExpandFilePathVariables now calls Environment.ExpandEnvironmentVariables only if the input contains '%'; removed unconditional % expansion after NLog token replacement; each ${...} token replacement is guarded with token != null; simplified ContainsSubStringIgnoreCase out-parameter annotation.
Simple ToString() Overrides
src/NLog/Layouts/CSV/CsvColumn.cs, src/NLog/Targets/MethodCallParameter.cs, src/NLog/Targets/TargetPropertyWithContext.cs
Added public override string ToString() returning "{Name}={Layout}".
Conditional ToString() Overrides
src/NLog/Layouts/JSON/JsonAttribute.cs, src/NLog/Layouts/XML/XmlAttribute.cs
Added public override string ToString() that returns "{Name}={Layout}" when Encode is true or Layout is a SimpleLayout; otherwise returns "{Name} (Encode=false)".

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hop through paths and clear the view,
Percent signs expand only when due.
Tokens checked, no surprises left behind,
Names and layouts neatly combined.
I twitch my whiskers and bound on through.

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to evaluate whether a description relates to the changeset. Add a description explaining the purpose of the ToString() overrides and their intended use in logging configuration.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: adding ToString() overrides to NLogConfigurationItem and related configuration classes throughout the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (2)
src/NLog/Common/InternalLogger.cs (1)

477-478: Optional: align token variable naming for readability.

localapplicationdatadir breaks the naming pattern used by nearby locals. Consider localApplicationDataDirToken for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Common/InternalLogger.cs` around lines 477 - 478, The local variable
name localapplicationdatadir used in the ContainsSubStringIgnoreCase call and
subsequent Replace should be renamed to follow the surrounding naming style
(e.g., localApplicationDataDirToken) for readability and consistency; update all
references in the block where internalLogFile is processed (the
ContainsSubStringIgnoreCase call, the out variable declaration, and the Replace
call) so the symbol names remain correct and compile.
src/NLog/Layouts/JSON/JsonAttribute.cs (1)

221-228: Consider keeping Layout visible when Encode=false.

Current output drops layout details in that branch, which makes diagnostics less informative.

♻️ Suggested adjustment
 public override string ToString()
 {
-    if (Encode)
-        return $"{Name}={Layout}";
-    else
-        return $"{Name} (Encode=false)";
+    if (Encode)
+        return $"{Name}={Layout}";
+    else
+        return $"{Name}={Layout} (Encode=false)";
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Layouts/JSON/JsonAttribute.cs` around lines 221 - 228, The
ToString() implementation of JsonAttribute hides Layout when Encode is false;
update JsonAttribute.ToString() so both branches include the Layout for
diagnostics (keep the existing Encode=true behavior but change the Encode=false
branch to also include Layout, e.g. include Name, Encode=false and the Layout
value), referencing the JsonAttribute class and its Encode, Name and Layout
properties so the layout remains visible in logs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/NLog/Common/InternalLogger.cs`:
- Around line 477-478: The local variable name localapplicationdatadir used in
the ContainsSubStringIgnoreCase call and subsequent Replace should be renamed to
follow the surrounding naming style (e.g., localApplicationDataDirToken) for
readability and consistency; update all references in the block where
internalLogFile is processed (the ContainsSubStringIgnoreCase call, the out
variable declaration, and the Replace call) so the symbol names remain correct
and compile.

In `@src/NLog/Layouts/JSON/JsonAttribute.cs`:
- Around line 221-228: The ToString() implementation of JsonAttribute hides
Layout when Encode is false; update JsonAttribute.ToString() so both branches
include the Layout for diagnostics (keep the existing Encode=true behavior but
change the Encode=false branch to also include Layout, e.g. include Name,
Encode=false and the Layout value), referencing the JsonAttribute class and its
Encode, Name and Layout properties so the layout remains visible in logs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c06daf4d-bf63-4344-b97f-017116f533ad

📥 Commits

Reviewing files that changed from the base of the PR and between a56df90 and 534dbe7.

📒 Files selected for processing (6)
  • src/NLog/Common/InternalLogger.cs
  • src/NLog/Layouts/CSV/CsvColumn.cs
  • src/NLog/Layouts/JSON/JsonAttribute.cs
  • src/NLog/Layouts/XML/XmlAttribute.cs
  • src/NLog/Targets/MethodCallParameter.cs
  • src/NLog/Targets/TargetPropertyWithContext.cs

@snakefoot snakefoot force-pushed the attrib_tostring branch 2 times, most recently from b14f673 to 7fd05b8 Compare March 29, 2026 06:57
Copy link
Copy Markdown

@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.

🧹 Nitpick comments (2)
src/NLog/Common/InternalLogger.cs (1)

465-478: Consider consolidating token replacement to reduce drift risk.

The repeated ContainsSubStringIgnoreCase(..., out var token) && token != null blocks are now fairly repetitive. A tiny helper would make future token additions safer and easier to maintain.

Refactor sketch
+        private static string ReplacePathToken(string path, string tokenName, string replacement)
+        {
+            if (ContainsSubStringIgnoreCase(path, tokenName, out var token) && token != null)
+                return path.Replace(token, replacement);
+            return path;
+        }
+
         private static string ExpandFilePathVariables(string internalLogFile)
         {
             try
             {
                 if (internalLogFile.IndexOf('%') >= 0)
                     internalLogFile = Environment.ExpandEnvironmentVariables(internalLogFile);
-                if (ContainsSubStringIgnoreCase(internalLogFile, "${currentdir}", out var currentDirToken) && currentDirToken != null)
-                    internalLogFile = internalLogFile.Replace(currentDirToken, System.IO.Directory.GetCurrentDirectory() + System.IO.Path.DirectorySeparatorChar.ToString());
+                internalLogFile = ReplacePathToken(internalLogFile, "${currentdir}", System.IO.Directory.GetCurrentDirectory() + System.IO.Path.DirectorySeparatorChar);
                 // ...same pattern for remaining tokens...
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Common/InternalLogger.cs` around lines 465 - 478, Replace the
repeated token-replacement blocks in InternalLogger.cs with a small helper that
centralizes the ContainsSubStringIgnoreCase check and replacement to avoid
drift; create a method (e.g., ReplaceTokenIfPresent) that accepts the token name
(like "${currentdir}"), the out-token capture logic (uses
ContainsSubStringIgnoreCase) and a replacement string/provider, and call it for
each token instead of duplicating the pattern around internalLogFile and
ContainsSubStringIgnoreCase; reference the existing ContainsSubStringIgnoreCase
function and the internalLogFile variable so callers like
ReplaceTokenIfPresent("${basedir}", () =>
LogManager.LogFactory.CurrentAppEnvironment.AppDomainBaseDirectory +
Path.DirectorySeparatorChar.ToString()) perform the same replacement behavior.
src/NLog/Layouts/XML/XmlAttribute.cs (1)

200-208: Consider including Layout in all cases for fuller diagnostic output.

When Encode=false and Layout is not a SimpleLayout, the current implementation omits the Layout value entirely. This could reduce diagnostic utility when debugging configuration issues.

💡 Optional: Include Layout value in all branches
 public override string ToString()
 {
     if (Encode || Layout is SimpleLayout)
         return $"{Name}={Layout}";
     else
-        return $"{Name} (Encode=false)";
+        return $"{Name}={Layout} (Encode=false)";
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Layouts/XML/XmlAttribute.cs` around lines 200 - 208, The ToString
override in XmlAttribute omits the Layout when Encode is false and Layout is not
a SimpleLayout; update XmlAttribute.ToString to always include the Layout value
for fuller diagnostics (e.g., include Layout.ToString() or Layout?.ToString()
regardless of Encode) while still indicating the Encode flag and Name so the
output contains Name, Encode state, and the Layout representation; refer to the
XmlAttribute class, its ToString method, the Encode and Layout properties, and
Name to implement this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/NLog/Common/InternalLogger.cs`:
- Around line 465-478: Replace the repeated token-replacement blocks in
InternalLogger.cs with a small helper that centralizes the
ContainsSubStringIgnoreCase check and replacement to avoid drift; create a
method (e.g., ReplaceTokenIfPresent) that accepts the token name (like
"${currentdir}"), the out-token capture logic (uses ContainsSubStringIgnoreCase)
and a replacement string/provider, and call it for each token instead of
duplicating the pattern around internalLogFile and ContainsSubStringIgnoreCase;
reference the existing ContainsSubStringIgnoreCase function and the
internalLogFile variable so callers like ReplaceTokenIfPresent("${basedir}", ()
=> LogManager.LogFactory.CurrentAppEnvironment.AppDomainBaseDirectory +
Path.DirectorySeparatorChar.ToString()) perform the same replacement behavior.

In `@src/NLog/Layouts/XML/XmlAttribute.cs`:
- Around line 200-208: The ToString override in XmlAttribute omits the Layout
when Encode is false and Layout is not a SimpleLayout; update
XmlAttribute.ToString to always include the Layout value for fuller diagnostics
(e.g., include Layout.ToString() or Layout?.ToString() regardless of Encode)
while still indicating the Encode flag and Name so the output contains Name,
Encode state, and the Layout representation; refer to the XmlAttribute class,
its ToString method, the Encode and Layout properties, and Name to implement
this change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4f79e7b0-51a6-4177-937b-484398de6b5d

📥 Commits

Reviewing files that changed from the base of the PR and between 534dbe7 and 7fd05b8.

📒 Files selected for processing (6)
  • src/NLog/Common/InternalLogger.cs
  • src/NLog/Layouts/CSV/CsvColumn.cs
  • src/NLog/Layouts/JSON/JsonAttribute.cs
  • src/NLog/Layouts/XML/XmlAttribute.cs
  • src/NLog/Targets/MethodCallParameter.cs
  • src/NLog/Targets/TargetPropertyWithContext.cs
✅ Files skipped from review due to trivial changes (2)
  • src/NLog/Layouts/CSV/CsvColumn.cs
  • src/NLog/Layouts/JSON/JsonAttribute.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/NLog/Targets/MethodCallParameter.cs

@snakefoot snakefoot force-pushed the attrib_tostring branch 2 times, most recently from 2ed21a1 to ab4407a Compare March 29, 2026 07:04
Copy link
Copy Markdown

@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/Common/InternalLogger.cs (1)

467-480: Consider using [NotNullWhen(true)] to eliminate redundant null guards.

The && token != null checks are logically redundant since ContainsSubStringIgnoreCase returns true only when result is non-null. Adding the [NotNullWhen(true)] attribute to the method's out parameter would let the compiler infer this, allowing removal of the redundant checks.

♻️ Proposed refactor

Update the method signature at line 492:

-private static bool ContainsSubStringIgnoreCase(string haystack, string needle, out string? result)
+private static bool ContainsSubStringIgnoreCase(string haystack, string needle, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out string? result)

Then simplify the null guards:

-if (ContainsSubStringIgnoreCase(internalLogFile, "${currentdir}", out var currentDirToken) && currentDirToken != null)
+if (ContainsSubStringIgnoreCase(internalLogFile, "${currentdir}", out var currentDirToken))
     internalLogFile = internalLogFile.Replace(currentDirToken, System.IO.Directory.GetCurrentDirectory() + System.IO.Path.DirectorySeparatorChar.ToString());

(Apply similar simplification to all other token replacement lines)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Common/InternalLogger.cs` around lines 467 - 480, The repeated "&&
token != null" guards are redundant because ContainsSubStringIgnoreCase only
returns true when the out token is non-null; update the
ContainsSubStringIgnoreCase method signature to annotate the out parameter with
[NotNullWhen(true)] so the compiler knows the token is non-null on true, then
remove the redundant "&& ... != null" checks from each replacement line (e.g.,
currentDirToken, baseDirToken, tempDirToken, processDirToken,
commonAppDataDirToken, appDataDirToken, localapplicationdataToken) so the if
statements simply check the boolean result and perform Replace when true.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/NLog/Layouts/CSV/CsvColumn.cs`:
- Line 128: Replace the misspelled XML doc tag "<inhertitdoc />" with the
correct "<inheritdoc/>" in the CsvColumn class documentation so XML doc
inheritance works; search for the CsvColumn type (or the CsvColumn
constructor/property/method around the existing XML comment) and update the
incorrect tag to "<inheritdoc/>" wherever it appears.

---

Nitpick comments:
In `@src/NLog/Common/InternalLogger.cs`:
- Around line 467-480: The repeated "&& token != null" guards are redundant
because ContainsSubStringIgnoreCase only returns true when the out token is
non-null; update the ContainsSubStringIgnoreCase method signature to annotate
the out parameter with [NotNullWhen(true)] so the compiler knows the token is
non-null on true, then remove the redundant "&& ... != null" checks from each
replacement line (e.g., currentDirToken, baseDirToken, tempDirToken,
processDirToken, commonAppDataDirToken, appDataDirToken,
localapplicationdataToken) so the if statements simply check the boolean result
and perform Replace when true.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0be795cc-a032-46be-80af-ffa0ba05dba1

📥 Commits

Reviewing files that changed from the base of the PR and between 7fd05b8 and ab4407a.

📒 Files selected for processing (6)
  • src/NLog/Common/InternalLogger.cs
  • src/NLog/Layouts/CSV/CsvColumn.cs
  • src/NLog/Layouts/JSON/JsonAttribute.cs
  • src/NLog/Layouts/XML/XmlAttribute.cs
  • src/NLog/Targets/MethodCallParameter.cs
  • src/NLog/Targets/TargetPropertyWithContext.cs
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/NLog/Targets/MethodCallParameter.cs
  • src/NLog/Layouts/JSON/JsonAttribute.cs
  • src/NLog/Targets/TargetPropertyWithContext.cs

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (1)
src/NLog/Common/InternalLogger.cs (1)

465-480: The && token != null checks are redundant.

ContainsSubStringIgnoreCase returns true only when the out parameter is non-null (line 496: return result != null). The additional null checks are unnecessary.

However, this is a minor verbosity issue and the code is functionally correct. The checks do satisfy the nullable analyzer and provide defensive clarity, so keeping them is acceptable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Common/InternalLogger.cs` around lines 465 - 480, The if-conditions
in InternalLogger.cs redundantly check both ContainsSubStringIgnoreCase(...) and
the out-token for null (e.g., currentDirToken, baseDirToken, tempDirToken,
processDirToken, commonAppDataDirToken, appDataDirToken,
localapplicationdataToken); remove the unnecessary "&& <token> != null"
fragments because ContainsSubStringIgnoreCase already guarantees a non-null out
value when it returns true—update the conditions around internalLogFile
replacements (the blocks that call ContainsSubStringIgnoreCase and then Replace)
to rely solely on the ContainsSubStringIgnoreCase(...) result while leaving the
replacement logic unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/NLog/Common/InternalLogger.cs`:
- Around line 465-480: The if-conditions in InternalLogger.cs redundantly check
both ContainsSubStringIgnoreCase(...) and the out-token for null (e.g.,
currentDirToken, baseDirToken, tempDirToken, processDirToken,
commonAppDataDirToken, appDataDirToken, localapplicationdataToken); remove the
unnecessary "&& <token> != null" fragments because ContainsSubStringIgnoreCase
already guarantees a non-null out value when it returns true—update the
conditions around internalLogFile replacements (the blocks that call
ContainsSubStringIgnoreCase and then Replace) to rely solely on the
ContainsSubStringIgnoreCase(...) result while leaving the replacement logic
unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 42992819-3ad2-4cd9-afba-f2365d3c1bd8

📥 Commits

Reviewing files that changed from the base of the PR and between ab4407a and db0283f.

📒 Files selected for processing (6)
  • src/NLog/Common/InternalLogger.cs
  • src/NLog/Layouts/CSV/CsvColumn.cs
  • src/NLog/Layouts/JSON/JsonAttribute.cs
  • src/NLog/Layouts/XML/XmlAttribute.cs
  • src/NLog/Targets/MethodCallParameter.cs
  • src/NLog/Targets/TargetPropertyWithContext.cs
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/NLog/Targets/MethodCallParameter.cs
  • src/NLog/Targets/TargetPropertyWithContext.cs

@sonarqubecloud
Copy link
Copy Markdown

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

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

See analysis details on SonarQube Cloud

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (1)
src/NLog/Common/InternalLogger.cs (1)

467-480: Consider extracting token replacement into a helper to reduce repetition.

The logic is correct, but this block is repetitive and harder to maintain as token count grows.

♻️ Proposed refactor
-                if (ContainsSubStringIgnoreCase(internalLogFile, "${currentdir}", out var currentDirToken) && currentDirToken != null)
-                    internalLogFile = internalLogFile.Replace(currentDirToken, System.IO.Directory.GetCurrentDirectory() + System.IO.Path.DirectorySeparatorChar.ToString());
-                if (ContainsSubStringIgnoreCase(internalLogFile, "${basedir}", out var baseDirToken) && baseDirToken != null)
-                    internalLogFile = internalLogFile.Replace(baseDirToken, LogManager.LogFactory.CurrentAppEnvironment.AppDomainBaseDirectory + System.IO.Path.DirectorySeparatorChar.ToString());
-                if (ContainsSubStringIgnoreCase(internalLogFile, "${tempdir}", out var tempDirToken) && tempDirToken != null)
-                    internalLogFile = internalLogFile.Replace(tempDirToken, LogManager.LogFactory.CurrentAppEnvironment.UserTempFilePath + System.IO.Path.DirectorySeparatorChar.ToString());
-                if (ContainsSubStringIgnoreCase(internalLogFile, "${processdir}", out var processDirToken) && processDirToken != null)
-                    internalLogFile = internalLogFile.Replace(processDirToken, System.IO.Path.GetDirectoryName(LogManager.LogFactory.CurrentAppEnvironment.CurrentProcessFilePath) + System.IO.Path.DirectorySeparatorChar.ToString());
-                if (ContainsSubStringIgnoreCase(internalLogFile, "${commonApplicationDataDir}", out var commonAppDataDirToken) && commonAppDataDirToken != null)
-                    internalLogFile = internalLogFile.Replace(commonAppDataDirToken, NLog.LayoutRenderers.SpecialFolderLayoutRenderer.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + System.IO.Path.DirectorySeparatorChar.ToString());
-                if (ContainsSubStringIgnoreCase(internalLogFile, "${userApplicationDataDir}", out var appDataDirToken) && appDataDirToken != null)
-                    internalLogFile = internalLogFile.Replace(appDataDirToken, NLog.LayoutRenderers.SpecialFolderLayoutRenderer.GetFolderPath(Environment.SpecialFolder.ApplicationData) + System.IO.Path.DirectorySeparatorChar.ToString());
-                if (ContainsSubStringIgnoreCase(internalLogFile, "${userLocalApplicationDataDir}", out var localapplicationdataToken) && localapplicationdataToken != null)
-                    internalLogFile = internalLogFile.Replace(localapplicationdataToken, NLog.LayoutRenderers.SpecialFolderLayoutRenderer.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + System.IO.Path.DirectorySeparatorChar.ToString());
+                internalLogFile = ReplaceTokenIfFoundIgnoreCase(internalLogFile, "${currentdir}", System.IO.Directory.GetCurrentDirectory() + System.IO.Path.DirectorySeparatorChar);
+                internalLogFile = ReplaceTokenIfFoundIgnoreCase(internalLogFile, "${basedir}", LogManager.LogFactory.CurrentAppEnvironment.AppDomainBaseDirectory + System.IO.Path.DirectorySeparatorChar);
+                internalLogFile = ReplaceTokenIfFoundIgnoreCase(internalLogFile, "${tempdir}", LogManager.LogFactory.CurrentAppEnvironment.UserTempFilePath + System.IO.Path.DirectorySeparatorChar);
+                internalLogFile = ReplaceTokenIfFoundIgnoreCase(internalLogFile, "${processdir}", System.IO.Path.GetDirectoryName(LogManager.LogFactory.CurrentAppEnvironment.CurrentProcessFilePath) + System.IO.Path.DirectorySeparatorChar);
+                internalLogFile = ReplaceTokenIfFoundIgnoreCase(internalLogFile, "${commonApplicationDataDir}", NLog.LayoutRenderers.SpecialFolderLayoutRenderer.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + System.IO.Path.DirectorySeparatorChar);
+                internalLogFile = ReplaceTokenIfFoundIgnoreCase(internalLogFile, "${userApplicationDataDir}", NLog.LayoutRenderers.SpecialFolderLayoutRenderer.GetFolderPath(Environment.SpecialFolder.ApplicationData) + System.IO.Path.DirectorySeparatorChar);
+                internalLogFile = ReplaceTokenIfFoundIgnoreCase(internalLogFile, "${userLocalApplicationDataDir}", NLog.LayoutRenderers.SpecialFolderLayoutRenderer.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + System.IO.Path.DirectorySeparatorChar);
private static string ReplaceTokenIfFoundIgnoreCase(string value, string needle, string replacement)
{
    if (ContainsSubStringIgnoreCase(value, needle, out var token) && token != null)
        return value.Replace(token, replacement);

    return value;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Common/InternalLogger.cs` around lines 467 - 480, The repeated
token-replacement blocks in InternalLogger.cs make maintenance hard; create a
helper like ReplaceTokenIfFoundIgnoreCase(value, needle, replacement) that uses
ContainsSubStringIgnoreCase and returns the replaced string or original, then
replace each in the method that computes internalLogFile (the blocks handling
"${currentdir}", "${basedir}", "${tempdir}", "${processdir}",
"${commonApplicationDataDir}", "${userApplicationDataDir}",
"${userLocalApplicationDataDir}") by calling this helper with the appropriate
replacement expressions (e.g., System.IO.Directory.GetCurrentDirectory() +
Path.DirectorySeparatorChar,
LogManager.LogFactory.CurrentAppEnvironment.AppDomainBaseDirectory +
Path.DirectorySeparatorChar, etc.), keeping existing symbol names
ContainsSubStringIgnoreCase and LogManager.LogFactory.CurrentAppEnvironment
referenced exactly as they are.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/NLog/Common/InternalLogger.cs`:
- Around line 467-480: The repeated token-replacement blocks in
InternalLogger.cs make maintenance hard; create a helper like
ReplaceTokenIfFoundIgnoreCase(value, needle, replacement) that uses
ContainsSubStringIgnoreCase and returns the replaced string or original, then
replace each in the method that computes internalLogFile (the blocks handling
"${currentdir}", "${basedir}", "${tempdir}", "${processdir}",
"${commonApplicationDataDir}", "${userApplicationDataDir}",
"${userLocalApplicationDataDir}") by calling this helper with the appropriate
replacement expressions (e.g., System.IO.Directory.GetCurrentDirectory() +
Path.DirectorySeparatorChar,
LogManager.LogFactory.CurrentAppEnvironment.AppDomainBaseDirectory +
Path.DirectorySeparatorChar, etc.), keeping existing symbol names
ContainsSubStringIgnoreCase and LogManager.LogFactory.CurrentAppEnvironment
referenced exactly as they are.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7ba6139f-b17a-4e0d-85ac-96d497858d08

📥 Commits

Reviewing files that changed from the base of the PR and between db0283f and 3218a9f.

📒 Files selected for processing (6)
  • src/NLog/Common/InternalLogger.cs
  • src/NLog/Layouts/CSV/CsvColumn.cs
  • src/NLog/Layouts/JSON/JsonAttribute.cs
  • src/NLog/Layouts/XML/XmlAttribute.cs
  • src/NLog/Targets/MethodCallParameter.cs
  • src/NLog/Targets/TargetPropertyWithContext.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/NLog/Layouts/CSV/CsvColumn.cs

@snakefoot snakefoot merged commit 260fee5 into NLog:dev Mar 29, 2026
5 of 7 checks passed
@snakefoot snakefoot added this to the 6.1.2 milestone Mar 29, 2026
@snakefoot snakefoot changed the title NLogConfigurationItem - ToString NLogConfigurationItem - ToString returns Name and Value Apr 1, 2026
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