简体   繁体   中英

How do i manipulate the stack level of NLog?

I've got an extension method to support additional log levels like this:

    public static void Duration(this ILogger source, string message)
    {
        var logEventInfo = new LogEventInfo(LogLevel.Warn, source.Name, message);
        logEventInfo.Properties.Add("specialLevel", "Duration");
        source.Log(logEventInfo);
    }

There is one problem with this.

My ${callsite} now always reports Duration. Is there any way to increase the call stack level by one, to get the method which calls Duration, or do i need a custom renderer for this?

What i tried so far:

logEventInfo.Properties.Add("skipFrames", 1);

and

layout="${formattedDate} ${callsite:skipFrames=${event-properties:item=skipFrames}} ${message}"

Ugly workaround:

[LayoutRenderer("customCallSite")]
public class CustomCallSiteLayoutRenderer : CallSiteLayoutRenderer
{
    private readonly CallSiteLayoutRenderer DefaultRenderer = new CallSiteLayoutRenderer();

    /// <inheritdoc />
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        if (!logEvent.HasProperties)
        {
            builder.Append(DefaultRenderer.Render(logEvent));
            return;
        }

        if (logEvent.Properties["skipFrames"] is int skipFrames)
        {
            builder.Append(GetRenderer(skipFrames).Render(logEvent));
        }
        else
        {
            builder.Append(logEvent.Level);
        }
    }

    private static readonly ConcurrentDictionary<int, CallSiteLayoutRenderer> Renderers = new ConcurrentDictionary<int, CallSiteLayoutRenderer>();

    private CallSiteLayoutRenderer GetRenderer(int skipFrames)
    {
        return Renderers.GetOrAdd(skipFrames, f => new CallSiteLayoutRenderer() {SkipFrames = skipFrames});
    }
}

There is another approach you can follow

  1. Move the "Duration" method to a new assembly
  2. Hide that assembly in the stacktraces, by calling AddHiddenAssembly

     LogManager.AddHiddenAssembly(yourAssemblyWithDurationMethod) 

No need for custom layout renderers then :)

PS: Your "Duration" method should be named "LogDuration". ;) From an API-viewpoint it's a bit odd method in my opinion.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM