Skip to content
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

${whenEmpty} implemented IRawValue and IStringValueRenderer #3398

Merged
merged 3 commits into from May 14, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -36,17 +36,17 @@ namespace NLog.LayoutRenderers.Wrappers
using System;
using System.Text;
using NLog.Config;
using NLog.Internal;
using NLog.Layouts;

/// <summary>
/// Outputs alternative layout when the inner layout produces empty result.
/// </summary>
[LayoutRenderer("whenEmpty")]
[AmbientProperty("WhenEmpty")]
[AppDomainFixedOutput]
[ThreadAgnostic]
[ThreadSafe]
public sealed class WhenEmptyLayoutRendererWrapper : WrapperLayoutRendererBuilderBase
public sealed class WhenEmptyLayoutRendererWrapper : WrapperLayoutRendererBuilderBase, IRawValue, IStringValueRenderer
{
/// <summary>
/// Gets or sets the layout to be rendered when original layout produced empty result.
Expand All @@ -55,11 +55,14 @@ public sealed class WhenEmptyLayoutRendererWrapper : WrapperLayoutRendererBuilde
[RequiredParameter]
public Layout WhenEmpty { get; set; }

private bool _skipStringValueRenderer;

/// <inheritdoc/>
protected override void InitializeLayoutRenderer()
{
base.InitializeLayoutRenderer();
WhenEmpty?.Initialize(LoggingConfiguration);
_skipStringValueRenderer = !TryGetStringValue(out var _, out var _);
Copy link
Member

Choose a reason for hiding this comment

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

I think you don't want var here ;) (the _ is also a keyword)

I have updated it

}

/// <inheritdoc/>
Expand All @@ -73,6 +76,65 @@ protected override void RenderInnerAndTransform(LogEventInfo logEvent, StringBui
WhenEmpty.RenderAppendBuilder(logEvent, builder);
}

string IStringValueRenderer.GetFormattedString(LogEventInfo logEvent)
{
if (!_skipStringValueRenderer)
{
if (TryGetStringValue(out var innerLayout, out var whenEmptyLayout))
{
var innerValue = innerLayout.Render(logEvent);
if (!string.IsNullOrEmpty(innerValue))
{
return innerValue;
}

// render WhenEmpty when the inner layout was empty
return whenEmptyLayout.Render(logEvent);
}

_skipStringValueRenderer = true;
}
return null;
}

bool TryGetStringValue(out SimpleLayout innerLayout, out SimpleLayout whenEmptyLayout)
{
innerLayout = Inner as SimpleLayout;
whenEmptyLayout = WhenEmpty as SimpleLayout;

if (innerLayout == null || (!innerLayout.IsFixedText && !innerLayout.IsSimpleStringText))
return false;

if (whenEmptyLayout == null || (!whenEmptyLayout.IsFixedText && !whenEmptyLayout.IsSimpleStringText))
return false;

return true;
}

bool IRawValue.TryGetRawValue(LogEventInfo logEvent, out object value)
{
if (Inner.TryGetRawValue(logEvent, out var innerValue))
{
if (innerValue != null && !innerValue.Equals(string.Empty))
{
value = innerValue;
return true;
}
}
else
{
var innerResult = Inner.Render(logEvent); // Beware this can be very expensive call!
if (!string.IsNullOrEmpty(innerResult))
{
value = null;
return false;
}
}

// render WhenEmpty when the inner layout was empty
return WhenEmpty.TryGetRawValue(logEvent, out value);
}

/// <inheritdoc/>
[Obsolete("Inherit from WrapperLayoutRendererBase and override RenderInnerAndTransform() instead. Marked obsolete in NLog 4.6")]
protected override void TransformFormattedMesssage(StringBuilder target)
Expand Down
22 changes: 22 additions & 0 deletions tests/NLog.UnitTests/LayoutRenderers/Wrappers/WhenEmptyTests.cs
Expand Up @@ -33,6 +33,7 @@

namespace NLog.UnitTests.LayoutRenderers.Wrappers
{
using System;
using NLog;
using NLog.Layouts;
using Xunit;
Expand Down Expand Up @@ -73,5 +74,26 @@ public void WhenEmpty_MissingInner_ShouldNotThrow()
var le = LogEventInfo.Create(LogLevel.Info, "logger", "message");
Assert.Equal("api.log", l.Render(le));
}

[Fact]
public void WhenDbNullRawValueShouldWork()
{
SimpleLayout l = @"${event-properties:prop1:whenEmpty=${db-null}}";
{
var le = LogEventInfo.Create(LogLevel.Info, "logger", "message");
le.Properties["prop1"] = 1;
var success = l.TryGetRawValue(le, out var rawValue);
Assert.True(success);
Assert.Equal(1, rawValue);
}
// empty log message
{
var le = LogEventInfo.Create(LogLevel.Info, "logger", "message");
var success = l.TryGetRawValue(le, out var rawValue);
Assert.True(success);
Assert.Equal(DBNull.Value, rawValue);
}

}
}
}