diff --git a/src/NLog/LayoutRenderers/Wrappers/WhenLayoutRendererWrapper.cs b/src/NLog/LayoutRenderers/Wrappers/WhenLayoutRendererWrapper.cs index b63e6864c4..651283b163 100644 --- a/src/NLog/LayoutRenderers/Wrappers/WhenLayoutRendererWrapper.cs +++ b/src/NLog/LayoutRenderers/Wrappers/WhenLayoutRendererWrapper.cs @@ -38,6 +38,7 @@ namespace NLog.LayoutRenderers.Wrappers using NLog.Conditions; using NLog.Config; using NLog.Layouts; + using NLog.Internal; /// /// Only outputs the inner layout when the specified condition has been met. @@ -46,7 +47,7 @@ namespace NLog.LayoutRenderers.Wrappers [AmbientProperty("When")] [ThreadAgnostic] [ThreadSafe] - public sealed class WhenLayoutRendererWrapper : WrapperLayoutRendererBuilderBase + public sealed class WhenLayoutRendererWrapper : WrapperLayoutRendererBuilderBase, IRawValue { /// /// Gets or sets the condition that must be met for the layout to be printed. @@ -67,13 +68,13 @@ protected override void Append(StringBuilder builder, LogEventInfo logEvent) int orgLength = builder.Length; try { - if (When == null || true.Equals(When.Evaluate(logEvent))) + if (ShouldRenderInner(logEvent)) { Inner?.RenderAppendBuilder(logEvent, builder); } - else if (Else != null) + else { - Else.RenderAppendBuilder(logEvent, builder); + Else?.RenderAppendBuilder(logEvent, builder); } } catch @@ -83,10 +84,37 @@ protected override void Append(StringBuilder builder, LogEventInfo logEvent) } } + private bool ShouldRenderInner(LogEventInfo logEvent) + { + return When == null || true.Equals(When.Evaluate(logEvent)); + } + /// [Obsolete("Inherit from WrapperLayoutRendererBase and override RenderInnerAndTransform() instead. Marked obsolete in NLog 4.6")] protected override void TransformFormattedMesssage(StringBuilder target) { } + + /// + public bool TryGetRawValue(LogEventInfo logEvent, out object value) + { + if (ShouldRenderInner(logEvent)) + { + return TryGetRawValueFromLayout(logEvent, Inner, out value); + } + + return TryGetRawValueFromLayout(logEvent, Else, out value); + } + + private static bool TryGetRawValueFromLayout(LogEventInfo logEvent, Layout layout, out object value) + { + if (layout == null) + { + value = null; + return false; + } + + return layout.TryGetRawValue(logEvent, out value); + } } } diff --git a/tests/NLog.UnitTests/LayoutRenderers/Wrappers/WhenTests.cs b/tests/NLog.UnitTests/LayoutRenderers/Wrappers/WhenTests.cs index c74e937285..bb4630f926 100644 --- a/tests/NLog.UnitTests/LayoutRenderers/Wrappers/WhenTests.cs +++ b/tests/NLog.UnitTests/LayoutRenderers/Wrappers/WhenTests.cs @@ -31,6 +31,7 @@ // THE POSSIBILITY OF SUCH DAMAGE. // +using System; using NLog.Config; namespace NLog.UnitTests.LayoutRenderers.Wrappers @@ -203,5 +204,49 @@ private static void WhenNumericAndPropertyConditionTest_inner(SimpleLayout l, ob le.Properties["Elapsed"] = time; Assert.Equal(fast ? "Fast" : "Slow", l.Render(le)); } + + [Theory] + [InlineData("logger", "DBNullValue", true)] + [InlineData("logger1", null, false)] + public void WhenDbNullRawValueShouldWork(string loggername, object expectedValue, bool expectedSuccess) + { + expectedValue = OptionalConvert(expectedValue); + + //else cannot be invoked ambiently. First param is inner + SimpleLayout l = @"${when:${db-null}:when=logger=='logger':else=better}"; + + var le = LogEventInfo.Create(LogLevel.Info, loggername, "message"); + var success = l.TryGetRawValue(le, out var result); + + Assert.Equal(expectedValue, result); + Assert.Equal(expectedSuccess, success); + } + [Theory] + [InlineData("logger1", "DBNullValue", true)] + [InlineData("logger", null, false)] + public void WhenDbNullRawValueShouldWorkElse(string loggername, object expectedValue, bool expectedSuccess) + { + + expectedValue = OptionalConvert(expectedValue); + + //else cannot be invoked ambiently. First param is inner + SimpleLayout l = @"${when:something:when=logger=='logger':else=${db-null}}"; + + var le = LogEventInfo.Create(LogLevel.Info, loggername, "message"); + var success = l.TryGetRawValue(le, out var result); + + Assert.Equal(expectedValue, result); + Assert.Equal(expectedSuccess, success); + } + + private static object OptionalConvert(object expectedValue) + { + if (expectedValue is string s && s == "DBNullValue") + { + expectedValue = DBNull.Value; + } + + return expectedValue; + } } } \ No newline at end of file