应该将哪些类型的日志记录添加到以后有用的应用程序中?
如果您从自己的异常类中抛出异常,或者更好的是,您的所有异常类都派生自基类,请在(基)异常构造函数中添加 ERROR 级别的日志记录;让您不必记住每次接球/投球。如果您有大型代码库,则很有用。
对于 CLR 或第 3 方异常,记录 Exception.ToString() 而不仅仅是消息,否则您会错过完整的堆栈跟踪(假设程序员没有吞下异常或重新抛出内部异常)
在您知道或怀疑您会遇到问题的领域中关注 DEBUG 详细信息(只需询问 QA 或技术支持在哪里查看;-)
如果您关注robustness principle,那么当您忽略或更改输入或预期行为时,您可能需要 INFO 或 WARN 日志记录。如果您的 WCF 服务开始接收意外(但可解析)的输入,这可能会很有用。
为确保您的应用程序运行良好,请不要在默认启用调试级别日志记录的情况下发布/安装它,错误或警告可能是要走的路。
我不同意接受答案的最后一部分,因为 log4net 具有出色的过滤功能;条件是您的程序员了解日志记录是有代价的(根据 CK 的回答)并且他们(以及 QA 和技术支持)知道过滤器,并且在 DEBUG 配置所有内容是一个坏主意。如果您在 DEBUG 级别记录大型对象图、xml 文档、数据库结果等,请将其包装在一些代码中以减少开销:
if (log.IsDebugEnabled)
{
log.DebugFormat("Loaded in {0} ms {1}", timer.ElapsedMilliseconds, dataSet.GetXml());
}
我建议您遵循recommended static logger-per-class 方法,只是因为当您必须实际使用它并使用过滤器缩小问题范围时,它应该使日志记录更有用,例如记录器匹配过滤器。
如果您采用这种方法并且愿意接受(相当小的)性能损失,这里有一种方法可以使用堆栈跟踪为任何类创建 ILog 对象并确保连接配置文件以监控更改:
public static class LogFactory
{
/// <summary>
/// Create log whose name is the calling methods class name.
/// </summary>
/// <remarks>
/// <para>
/// Configures the log repository if it hasn't been configured before.
/// </para>
/// <para>
/// Creates a debug log message right after getting the logger, this follows
/// the log4net recommendation to log first message as early as possible.
/// </para>
/// </remarks>
/// <returns>Log ready for work.</returns>
public static log4net.ILog Create()
{
var method = new StackTrace().GetFrame(1).GetMethod();
var log = log4net.LogManager.GetLogger(method.DeclaringType);
if (log4net.LogManager.GetRepository().Configured == false)
{
try
{
new FileIOPermission(FileIOPermissionAccess.Read,
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile)
.Demand();
var configFile = new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
log4net.Config.XmlConfigurator.ConfigureAndWatch(configFile);
log.DebugFormat("Log4net configured and watching {0}", configFile.FullName);
}
catch (System.Security.SecurityException e)
{
log.DebugFormat("Unable to watch config file due to security permissions. {0}", e.ToString());
}
}
log.DebugFormat("Logging {0}", log.Logger.Name);
return log;
}
}