Search code examples
c#nlog

NLog Pass custom LayoutRenderer to db target parameters


I may be misunderstanding the use of a layout renderer but what I would like to do is pass the layout to the db target parameters. Is this possible? When I try the below code it just renders the Append text to the values.

internal class Program {
    private static NLog.Logger logger = NLog.LogManager.Setup().SetupExtensions(s => s.AutoLoadExtensions().RegisterLayoutRenderer<LogMessage>()).GetCurrentClassLogger();
        static void Main(string[] args) {
            LogMessage message = new LogMessage() { IncomingOrOutgoing = MessageDirection.Incoming, MessageType = MessageType.TestType, MessageKey = "TestKey", Message = "Test Incoming" };
            logger.Info<LogMessage>(message);
}

[LayoutRenderer("LogMessage")]
public class LogMessage : LayoutRenderer {
    public MessageDirection IncomingOrOutgoing { get; set; }
    public string Message { get; set; }

    [DefaultParameter]
    public string MessageKey { get; set; }
        
    protected override void Append(StringBuilder builder, LogEventInfo logEvent) { 
        builder.Append("Test");
     }
}

nlog.config

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Trace"
      internalLogFile="C:\Nlog\logs\internalLog.txt"
      throwConfigExceptions="true">

    <targets async="true">
        <target name="db"
            xsi:type="Database"
            connectionString="..."
            commandType="StoredProcedure"
            commandText="[dbo].[IncomingOutgoingMessageLog]"
            >
            <parameter name="@MessageKey"     layout="${LogMessage:MessageKey}" />
            <parameter name="@Message"        layout="${LogMessage:Message}" />
            <parameter name="@IncomingOutgoing" layout="${LogMessage:IncomingOrOutgoing}" />
            
        </target>
    </targets>

    <rules>
        <logger name="*" minlevel="Info" writeTo="db" />
    </rules>
</nlog>

Solution

  • You should only create your own custom LayoutRenderer, when unable to capture context using the standard ways. Or want to generate output in a new custom format (different from JSON, XML, CSV, etc.)

    Maybe try this instead:

    <parameter name="@MessageKey"     layout="${event-properties:MessageKey}" />
    <parameter name="@Message"        layout="${event-properties:Message}" />
    <parameter name="@IncomingOutgoing" layout="${event-properties:IncomingOrOutgoing}" />
    
    var message = new NLog.LogEventInfo();
    message.Properties["IncomingOrOutgoing"] = MessageDirection.Incoming;
    message.Properties["MessageType"] = MessageType.TestType;
    message.Properties["MessageKey"] = "TestKey";
    message.Properties["Message"] = "Test Incoming";
    logger.Info(message);
    

    See also: https://github.com/NLog/NLog/wiki/Context