-
Notifications
You must be signed in to change notification settings - Fork 1.4k
WhenEmpty - Support AppDomainFixedOutput optimization #6057
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdded the Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🧰 Additional context used🧬 Code graph analysis (1)tests/NLog.UnitTests/ApiTests.cs (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (2)
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. Comment |
There was a problem hiding this 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
| /// </summary> | ||
| [LayoutRenderer("whenEmpty")] | ||
| [AmbientProperty(nameof(WhenEmpty))] | ||
| [AppDomainFixedOutput] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find AppDomainFixedOutput attribute definition
echo "=== AppDomainFixedOutput definition ==="
fd -e cs . src/ --exec rg -l "AppDomainFixedOutput" {} \; | head -20
echo -e "\n=== AppDomainFixedOutput attribute definition ==="
rg -A10 "class AppDomainFixedOutputAttribute" --type=csRepository: NLog/NLog
Length of output: 162
🏁 Script executed:
#!/bin/bash
# Check all wrapper classes and their attributes
echo "=== Wrapper classes with attributes ==="
cd src/NLog/LayoutRenderers/Wrappers
for file in *.cs; do
echo "=== $file ==="
head -60 "$file" | rg -B2 "^\s*\[.*\]|class.*Wrapper"
doneRepository: NLog/NLog
Length of output: 162
🏁 Script executed:
#!/bin/bash
# Check WhenEmptyLayoutRendererWrapper in detail
echo "=== WhenEmptyLayoutRendererWrapper class structure ==="
cat -n src/NLog/LayoutRenderers/Wrappers/WhenEmptyLayoutRendererWrapper.cs | head -130Repository: NLog/NLog
Length of output: 162
🌐 Web query:
NLog AppDomainFixedOutput attribute semantics layout renderer
💡 Result:
Short answer — AppDomainFixedOutputAttribute marks a Layout or LayoutRenderer whose rendered value is constant for the lifetime of the current AppDomain (so it never changes between log events). NLog can then evaluate/cache that value once (at init/config time or when capturing state) instead of rendering it per-log-event on the logging thread. Without this attribute NLog will render the layout on the main/logging thread every time. [1]
Notes:
- It’s different from ThreadAgnostic/ThreadAgnosticImmutable (which say the renderer is safe to run on any thread); AppDomainFixedOutput specifically signals the value is fixed for the AppDomain lifetime and may be precomputed/cached. [1]
Source: NLog API docs (AppDomainFixedOutputAttribute description). [1]
References
[1] NLog API documentation — NLog.Config namespace (AppDomainFixedOutputAttribute).
🌐 Web query:
NLog WhenEmptyLayoutRendererWrapper optimization performance
💡 Result:
Short answer: NLog already added a specific optimization for WhenEmptyLayoutRendererWrapper (IStringValueRenderer logic) in recent releases — upgrade to a current NLog 5.x/5.5+ to get that improvement. Also follow general layout-renderer performance guidance (mark thread-agnostic where possible, avoid heavy renderers like callsite/stacktrace, and use Async/Buffering wrappers). [1][2][3]
Sources
- NLog 5.5.0 release notes (calls out "WhenEmptyLayoutRendererWrapper - Optimize IStringValueRenderer Logic"). [1]
- NLog docs: WhenEmptyLayoutRendererWrapper reference. [2]
- NLog performance guidance (layout-renderer optimization, ThreadAgnostic notes). [3]
🌐 Web query:
NLog layout renderer wrapper AppDomainFixedOutput conditional output
💡 Result:
You can conditionally render the AppDomain (or any layout) using NLog's wrapper layout renderers (e.g. ${when}, ${onexception}, ${whenEmpty}). The AppDomain renderer is ${appdomain}. Example — render short AppDomain name only when logger == "MyLogger":
${when:when=logger=='MyLogger':inner=${appdomain:format=Short}}
Notes:
- Use ${onexception:inner=...} to output only on exceptions.
- Use ${whenEmpty:inner=...:else=...} to provide fallback text when inner is empty.
Docs: NLog wrapper renderers list, AppDomain renderer, and When wrapper. [1][2][3]
Sources
[1] NLog.LayoutRenderers.Wrappers (wrapper list).
[2] AppDomainLayoutRenderer documentation.
[3] WhenLayoutRendererWrapper (conditional wrapper).
Remove AppDomainFixedOutput attribute from WhenEmptyLayoutRendererWrapper.
The AppDomainFixedOutput attribute indicates that a layout's rendered value is constant for the AppDomain lifetime and can be cached. However, WhenEmptyLayoutRendererWrapper conditionally outputs either the Inner or WhenEmpty layout based on runtime evaluation of each LogEventInfo. The choice between these two layouts is determined per log event (whether Inner produces empty output), making the output not fixed within the AppDomain. This attribute is semantically incorrect for this wrapper and may cause NLog to incorrectly cache or optimize the output, leading to wrong results.
🤖 Prompt for AI Agents
In src/NLog/LayoutRenderers/Wrappers/WhenEmptyLayoutRendererWrapper.cs around
line 47, remove the AppDomainFixedOutput attribute because the wrapper's output
depends on each LogEventInfo (it conditionally renders Inner or WhenEmpty per
event) and therefore is not constant for the AppDomain; edit the file to delete
the [AppDomainFixedOutput] annotation so the wrapper won't be treated as
cacheable across the AppDomain and will be evaluated per log event.
|



No description provided.