Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify the ${stacktrace} layout renderer in NLog

Tags:

c#

logging

nlog

I started using NLog.Interface so that I can use an ILogger interface instead of the Logger class provided on NLog (mainly for unit testing)

When I use ${stacktrace}, I get something like this:

... => LoginViewModel.LogIn => LoggerAdapter.Info

I'd like to remove the LoggerAdapter.Info part (which is included because NLog.Interface wrapps the Logger class inside LoggerAdapter).

How could I do that?

like image 627
Oscar Mederos Avatar asked Feb 26 '26 13:02

Oscar Mederos


1 Answers

You can create custom LayoutRenderer, which will skip some stack frames:

[LayoutRenderer("stacktrace")]
public class CustomStackTraseLayoutRenderer : StackTraceLayoutRenderer
{
   [DefaultValue(0)]
   public int SkipFrames { get; set; } // configurable

   protected override void Append(StringBuilder builder, LogEventInfo logEvent)
   {
       int startingFrame = logEvent.UserStackFrameNumber + TopFrames - 1;
       if (startingFrame >= logEvent.StackTrace.FrameCount)
           startingFrame = logEvent.StackTrace.FrameCount - 1;

        bool first = true;
        int endingFrame = logEvent.UserStackFrameNumber + SkipFrames;
        for (int i = startingFrame; i >= endingFrame; --i)
        {
            StackFrame f = logEvent.StackTrace.GetFrame(i);

            switch (Format)
            {
                case StackTraceFormat.Raw:
                    builder.Append(f.ToString());
                    break;
                case StackTraceFormat.Flat:
                    if (!first)
                        builder.Append(this.Separator);
                    var type = f.GetMethod().DeclaringType;
                    builder.Append(type == null ? "<no type>" : type.Name);
                    builder.Append(".");
                    builder.Append(f.GetMethod().Name);
                    first = false;
                    break;
                case StackTraceFormat.DetailedFlat:
                    if (!first)
                        builder.Append(this.Separator);
                    builder.Append("[" + f.GetMethod() + "]");
                    first = false;
                    break;
            }
        }
    }
}

Adding custom layout renderer:

<extensions>
  <add prefix="custom" assembly="YourAssemblyName"/>
</extensions>
<targets>
  <target xsi:type="ColoredConsole" name="c"
          layout="${time} ${custom.stacktrace:skipframes=1} ${level} ${message}">
  </target>
</targets>
like image 115
Sergey Berezovskiy Avatar answered Mar 01 '26 01:03

Sergey Berezovskiy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!