NLog feature question: can the stack depth be taken into account while writing logs?
Asked Answered
S

1

1

I'm quite new at working with NLog., but I have earlier experience working with logfiles/trace files, but previously the logs looked as follows:

<timestamp> ... | main function logging
<timestamp> ... |   sub function logging.1
<timestamp> ... |     subsub function logging.1.1
<timestamp> ... |     subsub function logging.1.2
<timestamp> ... |   sub function logging.2
<timestamp> ... |     subsub function logging.2.1
<timestamp> ... |       subsubsub function logging.2.1.1
...

As you can see, the indenting was done, based on the depth within the callstack.
In NLog technology (NLog.xml file), I have seen a depth attribute, but I believe this is only meant for limiting the amount of logs, based on the callstack depth, I don't see any indentation configuration.

Does NLog have that feature, where indentation is added, based on the callstack depth?

Seine answered 4/2, 2022 at 13:55 Comment(9)
Here is similar (same?) question: #5951602. Note that using solution from accepted answer might affect perfomance, because new StackTrace() is not cheap.Hamitosemitic
@Evk: that answer is from 11 years ago, and it gives a solution indeed in case that feature does not exist. Are you aware if in the meantime that feature might be implemented in NLog and if yes, in which version?Seine
See also: https://mcmap.net/q/1175522/-nlog-how-to-indent-scopes-and-use-scope-headlineBorgia
Nope, I'm not aware about built-in implementation of such indentation.Hamitosemitic
@RolfKristensen: Thanks for your proposal, but it means that I would need to start and end scopes in order to have indentation, while I prefer those to be defined automatically by the callstack depth.Seine
@Seine As soon that you start to use Threads or Async-Tasks, then you suddenly have to ignore a lot Microsoft-Specific-StackFrames. Also the indent might suddenly become weird when mixing with other libraries that uses event-handler and calls your code. At the same time the overhead from capturing StackTrace for every LogEvent will give a performance hit.Borgia
@RolfKristensen: adding the capture of the StackTrace by myself is a performance drop, indeed. This is why I asked it to be an extra NLog feature. However, as you say, indenting code is typical for single-threaded code with only synchronous requests (I worked in that before). However now I work in a multi-threaded environment with asynchronous requests, so indenting might cause weird indentation jumps, so my question is senseless. You can write your comment as an answer (with references to the other posts for reference reasons), I'll accept the answer and give you the bounty.Seine
Even if NLog had that as an extra feature - it would still have to use StackTrace with the same perfomance drop. You can try something like this to reduce that drop - https://mcmap.net/q/781544/-for-c-logging-how-do-i-obtain-the-call-stack-depth-with-minimal-overhead/5311735 (while NLog itself cannot afford to use such hacks). But yeah, async-generated junk frames will likely kill this idea, unless you can filter them out, but for that you will need full stack trace (not just depth), which again gets us back to perfomance issues.Hamitosemitic
I was hoping that the NLog application "subscribed" to the main application, keeping track of the stacktrace, but that's probably a question too far :-)Seine
B
1

As soon that you start to use Threads or Async-Tasks, then you suddenly have to ignore a lot Microsoft-Specific-StackFrames. Also the indent might suddenly become weird when mixing with other libraries that uses event-handler and calls your code. At the same time the overhead from capturing StackTrace for every LogEvent will give a performance hit.

An alternative could be to use class-namespaces/inner-classes to provide indenting, that can extracted from NLog ${logger}:

namespace ApplicationName
{
    class Program
    {
         static NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
    }
}

namespace ApplicationName.Controllers
{
    class MyController
    {
         static NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
    }
}

namespace ApplicationName.Models
{
    class MyModel
    {
         static NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();

         class InnerLogic
         {
             static NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
         }
    }
}

Yet another alternative could be using nested states with NLog ScopeContext, that can provide indent with NLog ${scopeindent}.

Borgia answered 26/10, 2022 at 16:21 Comment(1)
Upvoted, accepted and bounty delivered, as agreed :-)Seine

© 2022 - 2024 — McMap. All rights reserved.