If I do a NLog.Trace():
logger.Trace("Json: {0}", Newtonsoft.Json.JsonConvert.DeserializeObject(myObject));
And my minlevel is on Error:
<logger name="*" minlevel="Error" writeTo="mail" enabled="false" />
Will my object be deserialized for nothing? Yes, of course yes. But how can I avoid this?
if(logger.IsTraceEnabled)
logger.Trace("Json: {0}", Newtonsoft.Json.JsonConvert.SerializeObject(myObject));
See IsTraceEnabled.
This is good practice for logging calls where the call itself can be expensive (like in your case above) or in a repetitive high call loop. For everything else there usually is no need to add the check as there framework itself performs the same check inside the call.
Create an extension method like such
public static class NlogExtensions
{
public static void Trace(this Logger logger, string format, Func<string> func)
{
if (logger.IsTraceEnabled)
{
logger.Trace(format, func());
}
}
}
And change your call of trace to
logger.Trace("Json: {0}", () => Newtonsoft.Json.JsonConvert.DeserializeObject(myObject));
So the myObject will only be serialized when the trace is enabled.
One approach to 'lazy logging' is to use an expression (to create a function delegate that returns the message) rather than using direct evaluation:
logger.Trace(() =>"Json: "+ Newtonsoft.Json.JsonConvert.DeserializeObject(myObject));
This has its own downsides (construction of the delegate), but it can be cheaper than the expensive method. Typically you would provide this as an overload and only use it in the case where you know evaluating the expression is expensive.
Reference: https://stackoverflow.com/a/8347895/2073920
来源:https://stackoverflow.com/questions/39036258/prevent-expensive-log-call-if-log-level-is-below-threshold