NLog has the ability to include callsite information through the ${callsite:className=Boolean:fileName=Boolean:includeSourcePath=Boolean:methodName=Boolean}:
renderer.
I am assuming NLog gets a stack trace to realize this functionality.
I am wondering whether that is the case, or if NLog has optimizations that go beyond creating a new stack trace on every logging call, and what the performance implications are in an application with a lot of log entries being written?
The .NET framework does not provide many more options [1] to get a stacktrace than to use the StackTrace
class, either directly or via Exception
or Environment.StackTrace
as a string, so there is little more NLog can do. Furthermore the callstack will (potentially) be different for each log call made. The one exception being a log call inside a loop. But even in that case there would need to be some machinery to help NLog even know that the call was made from the "same location" as the previous one. That could only be determined looking (again) at the callstack.
So, all in all, I would assume NLog must do exactly that: capture the callstack on every log call being made (although not for every layout/appender that processes the call) - just like log4net by the way, which "warns" about this option being a performance issue with a high frequency of log calls.
Anyway, you may want to look at the source, which also indicates (although I have not stepped through it in a debugger), that there is one callstack being captured per log call.
UPDATE For completeness sake, starting with .NET 4.5, one could use the caller info attributes. They have there own "limitations" though, like not including the typename. However, they are not currently being used by NLog.
[1] Other than maybe using some IL level rewriting or running the application in a debugger.