C#日志记录的性能技巧

时间:2010-04-12 02:50:26

标签: c# performance logging

我正在研究C#日志记录,如果消息低于日志记录阈值,我不希望我的日志消息花费任何时间进行处理。我可以看到log4net最好的是在评估日志参数后进行阈值检查。

示例:

_logger.Debug( "My complicated log message " + thisFunctionTakesALongTime() + " will take a long time" )

即使阈值高于Debug,仍会评估thisFunctionTakesALongTime。

在log4net中,您应该使用_logger.isDebugEnabled,以便最终得到

if( _logger.isDebugEnabled )
    _logger.Debug( "Much faster" )

我想知道是否有更好的.net日志记录解决方案,每次我都想记录时都不会进行检查。

在C ++中,我被允许做

LOG_DEBUG( "My complicated log message " + thisFunctionTakesALongTime() + " will take no time" )

因为我的LOG_DEBUG宏执行日志级别检查。这让我在整个应用程序中都有一行日志消息,我更喜欢这个消息。有人知道在C#中复制这种行为的方法吗?

4 个答案:

答案 0 :(得分:9)

如果您可以使用.NET 3.5(C#3.0),则可以使用extension methods来包装if语句。

所以你可以做相同的“宏”:

logger.Log_Debug("Much faster");

logger.Log_Debug(() => { "My complicated log message " + thisFunctionTakesALongTime() + " will take no time" });

将检查包装在此方法中:

public class Log4NetExtensionMethods {
    // simple string wrapper
    public void Log_Debug(this log4net.ILog logger, string logMessage) {
        if(logger.isDebugEnabled) {
             logger.Debug(logMessage);
        }
    }

    // this takes a delegate so you can delay execution
    // of a function call until you've determined it's necessary
    public void Log_Debug(this log4net.ILog logger, Func<string> logMessageDelegate) {
        if(logger.isDebugEnabled) {
             logger.Debug(logMessageDelegate());
        }
    }
}

答案 1 :(得分:3)

17.4.2条件属性

Conditional属性启用条件方法的定义。 Conditional属性通过测试条件编译符号来指示条件。根据是否在调用点定义了此符号,可以包含或省略对条件方法的调用。如果定义了符号,则包括呼叫;否则,省略呼叫(包括对呼叫参数的评估)。

[ Conditional("DEBUG") ]
public static void LogLine(string msg,string detail)
{
    Console.WriteLine("Log: {0} = {1}",msg,detail);
}

public static void Main(string[] args)
{
    int Total = 0;
    for(int Lp = 1; Lp < 10; Lp++)
    {
        LogLine("Total",Total.ToString());
        Total = Total + Lp;
    }
}

答案 2 :(得分:1)

这里的问题是必须在调用方法之前评估所有方法参数。根据您使用的语法,没有办法解决这个问题。由于C#没有真正的预处理器或宏,因此您无法执行“LOG_DEBUG”之类的操作。您可以做的最好的事情是按照建议使用if (logger.isDebugEnable)

我唯一能想到的就是使用lambda表达式来延迟评估。但是我会警告你,这几乎肯定会最终影响性能

internal class Sample
{
    private static void Main(string[] args)
    {
        DelayedEvaluationLogger.Debug(logger, () => "This is " + Expensive() + " to log.");
    }

    private static string Expensive()
    {
        // ...
    }
}

internal static class DelayedEvaluationLogger
{
    public static void Debug(ILog logger, Func<string> logString)
    {
        if (logger.isDebugEnabled)
        {
            logger.Debug(logString());
        }
    }
}

答案 3 :(得分:-1)

没有预处理器,你就是SOL。当然,在将代码提供给C#编译器之前,没有什么可以阻止您使用它。