Skip to content

Commit

Permalink
Make it possible to register a own FuncLayoutRenderer
Browse files Browse the repository at this point in the history
  • Loading branch information
304NotModified committed Feb 27, 2021
1 parent 1a73871 commit 6af6154
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 8 deletions.
27 changes: 22 additions & 5 deletions src/NLog/LayoutRenderers/FuncLayoutRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,24 @@ namespace NLog.LayoutRenderers
/// </summary>
public class FuncLayoutRenderer : LayoutRenderer, IStringValueRenderer
{
private readonly Func<LogEventInfo, LoggingConfiguration, object> _renderMethod;

/// <summary>
/// Initializes a new instance of the <see cref="FuncLayoutRenderer"/> class.
/// </summary>
/// <param name="layoutRendererName">Name without ${}.</param>
protected FuncLayoutRenderer(string layoutRendererName) : this(layoutRendererName, null)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="FuncLayoutRenderer"/> class.
/// </summary>
/// <param name="layoutRendererName">Name without ${}.</param>
/// <param name="renderMethod">Method that renders the layout.</param>
public FuncLayoutRenderer(string layoutRendererName, Func<LogEventInfo, LoggingConfiguration, object> renderMethod)
{
RenderMethod = renderMethod ?? throw new ArgumentNullException(nameof(renderMethod));
_renderMethod = renderMethod ?? throw new ArgumentNullException(nameof(renderMethod));
LayoutRendererName = layoutRendererName;
}

Expand All @@ -60,9 +70,11 @@ public FuncLayoutRenderer(string layoutRendererName, Func<LogEventInfo, LoggingC
public string LayoutRendererName { get; set; }

/// <summary>
/// Method that renders the layout.
/// Method that renders the layout.
///
/// Will be removed in NLog 5!
/// </summary>
public Func<LogEventInfo, LoggingConfiguration, object> RenderMethod { get; }
public Func<LogEventInfo, LoggingConfiguration, object> RenderMethod => _renderMethod;

/// <summary>
/// Format string for conversion from object to string.
Expand Down Expand Up @@ -92,9 +104,14 @@ private string GetStringValue(LogEventInfo logEvent)
return null;
}

private object GetValue(LogEventInfo logEvent)
/// <summary>
/// Get the value for the LogEvent
/// </summary>
/// <param name="logEvent"></param>
/// <returns></returns>
protected virtual object GetValue(LogEventInfo logEvent)
{
return RenderMethod.Invoke(logEvent, LoggingConfiguration);
return _renderMethod?.Invoke(logEvent, LoggingConfiguration);
}
}
}
15 changes: 12 additions & 3 deletions src/NLog/LayoutRenderers/LayoutRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ protected CultureInfo GetCulture(LogEventInfo logEvent, CultureInfo layoutCultur
/// <typeparam name="T"> Type of the layout renderer.</typeparam>
/// <param name="name"> Name of the layout renderer - without ${}.</param>
public static void Register<T>(string name)
where T: LayoutRenderer
where T : LayoutRenderer
{
var layoutRendererType = typeof(T);
Register(name, layoutRendererType);
Expand Down Expand Up @@ -280,8 +280,17 @@ public static void Register(string name, Func<LogEventInfo, object> func)
public static void Register(string name, Func<LogEventInfo, LoggingConfiguration, object> func)
{
var layoutRenderer = new FuncLayoutRenderer(name, func);

ConfigurationItemFactory.Default.GetLayoutRenderers().RegisterFuncLayout(name, layoutRenderer);

Register(layoutRenderer);
}

/// <summary>
/// Register a custom layout renderer with a callback function <paramref name="layoutRenderer"/>. The callback receives the logEvent and the current configuration.
/// </summary>
/// <param name="layoutRenderer">Renderer with callback func</param>
public static void Register(FuncLayoutRenderer layoutRenderer)
{
ConfigurationItemFactory.Default.GetLayoutRenderers().RegisterFuncLayout(layoutRenderer.LayoutRendererName, layoutRenderer);
}
}
}
86 changes: 86 additions & 0 deletions tests/NLog.UnitTests/LayoutRenderers/FuncLayoutRendererTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//
// Copyright (c) 2004-2020 Jaroslaw Kowalski <[email protected]>, Kim Christensen, Julian Verdurmen
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of Jaroslaw Kowalski nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//

using NLog.LayoutRenderers;
using System;
using NLog.Config;
using Xunit;

namespace NLog.UnitTests.LayoutRenderers
{
public class FuncLayoutRendererTests : NLogTestBase
{
[Fact]
public void RegisterCustomFuncLayoutRendererTest()
{
// Arrange
var funcLayoutRenderer = new MyFuncLayoutRenderer("the-answer-new");

// Act
LayoutRenderer.Register(funcLayoutRenderer);

LogManager.Configuration = XmlLoggingConfiguration.CreateFromXmlString(@"<nlog throwExceptions='true'>
<targets>
<target name='debug' type='Debug' layout= 'TheAnswer=${the-answer-new:Format=D3}' /></targets>
<rules>
<logger name='*' minlevel='Debug' writeTo='debug' />
</rules>
</nlog>");

var logger = LogManager.GetCurrentClassLogger();
logger.Debug("test1");

// Assert
AssertDebugLastMessage("debug", "TheAnswer=042");
}


private class MyFuncLayoutRenderer : FuncLayoutRenderer
{
/// <inheritdoc />
public MyFuncLayoutRenderer(string layoutRendererName) : base(layoutRendererName)
{
}

#region Overrides of FuncLayoutRenderer

/// <inheritdoc />
protected override object GetValue(LogEventInfo logEvent)
{
return 42;
}

#endregion
}
}
}

0 comments on commit 6af6154

Please sign in to comment.