Ahmad
Ahmad

Reputation: 13436

Custom log entry string formatting in NLog?

I'm new to NLog and wanted to know if there's a way I write log entries formatted in some custom way ? For example, here are some things I want to do to my log entries:

--> Have nested log entry messages (excluding log entry metadata) to make the depth of the logging call stack easier to follow. This can be done by indenting the log entry string proportionally by how deep you are in the logging call stack

--> Log a "change ID" (basically some sort of ID linked to some request that's being processed) with all relevant log entries

I know NLog has some templates you can use and stuff, but I would prefer having more control, in the form of a custom formatting class or something, which would intercept the logging request every time I do Log.Info(...), and then format my log entry string appropriately according to the behavior I choose.

Is this possible ?

EDIT:

Here's the contents of my current NLog.config file:

<?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" xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd" autoReload="true" throwExceptions="true" internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
   <targets>
      <target name="logfile" xsi:type="File" fileName="logfile.log" />
      <target name="logconsole" xsi:type="Console" />
   </targets>
   <rules>
      <logger name="*" minlevel="Trace" writeTo="logconsole" />
      <logger name="*" minlevel="Trace" writeTo="logfile" />
   </rules>
</nlog>

Upvotes: 0

Views: 4024

Answers (1)

Julian
Julian

Reputation: 36849

One way is create a custom layout renderer.

There are 2 options to do this:

Lambda method

Create a lambda methods and register before loading other NLog things (beware of statics), e.g. in main().

The lambda receives a LogEventInfo, which includes the following properties: Level, Message (unformated), FormattedMessage, Parameters (send to Log.Info), optional Exception and properties (named parameters)

//Create ${message-length}

// NLog 4.7+ syntax
NLog.LogManager.Setup().SetupExtensions(s =>
   s.RegisterLayoutRenderer("message-length", (logevent) => logEvent.FormattedMessage.Length)
);

Class

If you need more control and options, you could also create a class that inherits from NLog.LayoutRenderers.LayoutRenderer

1. Setup

/// <summary>
/// E.g. usage:  ${MyFormatter:MyLayout:${uppercase}} or ${MyFormatter:${uppercase}}
/// </summary>
[LayoutRenderer("MyFormatter")]
public class MyFormatterLayoutRenderer: LayoutRenderer
{
    [RequiredParameter]
    public Layout MyLayout { get; set; }

    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        var text = MyLayout.Render(logEvent);
        builder.Append(text);
    }
}

2. Register

You need to register the layout renderer:

// NLog 4.7+ syntax
NLog.LogManager.Setup().SetupExtensions(s =>
   s.RegisterLayoutRenderer<MyNamespace.MyFormatterLayoutRenderer>("MyFormatter")
);

3. Usage

Use it as follows, set the layout attribute of a target. For example:

<target name="logfile" xsi:type="File" fileName="logfile.log" layout="${message-length} - ${level} - ${message} - ${exception}"  />
<target name="logconsole" xsi:type="Console" layout="${message-length} - ${level} - ${message} - ${exception}" />

Read more here

Upvotes: 1

Related Questions