Print a multi-line message with NLog

点点圈 提交于 2020-05-11 07:21:41

问题


Is it possible with NLog to emit a multi-line message such that each line is formatted according to the current layout? E.g.

2015-12-17 11:37:38.0845 | 64 | INFO | -----------------------------------
2015-12-17 11:37:38.0845 | 64 | INFO | Statistics:
2015-12-17 11:37:38.0845 | 64 | INFO |   Crawling Requests   46887 /min
2015-12-17 11:37:38.0845 | 64 | INFO |   Stored Documents    9910 /min
2015-12-17 11:37:38.0845 | 64 | INFO | -----------------------------------

Alternatively, is it possible with NLog to emit multiple messages as a single, non-interrupted block in a multithreaded environment?


回答1:


You can do all this from your config.

<variable name="statData" value="${longdate} | 64 | ${level} | "/>
<variable name="line" value="-----------------------------------"/>
<targets>
    <target xsi:type="Console"
        name="Console"
        layout="
        ${statData}${line}${newline}
        ${statData}Statistics:${newline}
        ${statData}  Crawling Requests   46887 /min ${newline}
        ${statData}  Stored Documents    9910 /min ${newline}
        ${statData}${line}${newline}"/>

Wasn't exactly sure what your 64 was or where you were getting your per minute data. Probably a variable or something your inserting.This should also work if you are logging to a file not the console.

As for your second question, if you are wanting a single log message from multiple threads I think you would have to do that on the code side. You would have to collect your threads, get your log data you want and send it 1 time to nLog. I might be misunderstanding though




回答2:


There does not appear to be existing functionally to do this yet (as of NLog 4.2.3). A potential solution is to create your own wrapper layout renderer to improve the functionality of the replace-newlines renderer.

So replace-newlines and replace wrappers will not take layout renderers in their replacement strings. Looking at the NLog source for other wrappers, renderers, and targets, a Layout type property can be used to accept a string with (or without) layout renderers. The built in replace wrappers fail when provided a layout renderer because their Replacement property type is string. The xml parser is only looking for plain text but the } of a provided layout renderer prematurely ends the replace-newline wrapper.

The following custom wrapper changes the replacement type from string to Layout. The replacement layout then needs to be rendered by calling its Render method with some context (LogEventInfo). This can be done in the overridden Append method where LogEventInfo is available. The rendered output can be saved off for later usage in the Transform method.

using System;
using System.Text;
using NLog.Config;
using NLog.LayoutRenderers;
using NLog.LayoutRenderers.Wrappers;
using NLog.Layouts;

namespace My.Namespace
{
    [LayoutRenderer("replace-newlines-withlayout")]
    [ThreadAgnostic]
    public class ReplaceNewLinesFormatLayoutRendererWrapper : WrapperLayoutRendererBase
    {
        private string m_replacementString = " ";

        public ReplaceNewLinesFormatLayoutRendererWrapper()
        {
            // Changed from
            // Replacement = " ";
            Replacement = Layout.FromString(" ");
        }

        // Changed from
        // public string Replacement { get; set; }
        public Layout Replacement { get; set; }

        // Override Append in order to render the replacement.
        protected override void  Append(StringBuilder builder, NLog.LogEventInfo logEvent)
        {
            // Render...
            m_replacementString = Replacement.Render(logEvent);

            // The base functionality of append is fine.
            base.Append(builder, logEvent);
        }   

        // Called from base.Append()
        protected override string Transform(string text)
        {
            // Changed from 
            // return text.Replace(Environment.NewLine, Replacement);

            // Now just put in the rendered replacement string.
            return text.Replace(Environment.NewLine, m_replacementString);
        }
    }
}

And then, for example, use it as

<target
    ...
    layout=${replace-newlines-withlayout:replacement=${newline}${time}:${message}}
    ... 
    />

In this simplified case, assuming ${message} has line breaks, each new line will be prefixed with a time stamp. Just replace ${time} with the desired prefix layout.



来源:https://stackoverflow.com/questions/34333794/print-a-multi-line-message-with-nlog

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!