首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >日志信息最佳实践

日志信息最佳实践
EN

Stack Overflow用户
提问于 2010-11-07 18:28:18
回答 4查看 2.1K关注 0票数 4

我正在做生产支持,很大程度上依靠日志来排除故障。我发现现在的日志信息相当混乱。

你能提供写日志信息的最佳实践或指南吗?

顺便说一下:我们使用的是log4Net。你对替代图书馆有什么建议吗?

谢谢。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-11-07 19:05:23

理想情况下,您的日志消息应该包括时间、内容、地点、人员的详细信息,以及触发消息的事件的严重程度的一些指示。

  • 包括日期和时间。如果您的应用程序是跨时区分发的,则还应包含一个时区指示器。如果每个人都确切知道日志记录严重级别中的时间是03:11:04,这将消除混淆。日志消息中包含一些触发日志消息的模块或类的指示。如果可能,鼓励开发人员在消息中包含特定信息:例如,“文件损坏”,远不如“文件损坏:"C:\foo\bar.dat"'
  • If
  • ,让开发人员在错误消息中包含某种类型的会话或事务ID”
  • 有用。能够从日志中筛选出现错误的事务的消息并忽略所有正常的事务,这很方便。
  • 在错误的日志消息中包含错误代码通常是一个好主意。

我赞同@Oded在保持信息整洁方面的建议。对于例程内容,日期和时间,日志级别,错误代码,我会尝试将它们格式化为固定的宽度,并将它们放在开头。它使扫描日志变得更容易。

关于日志消息格式化的好指南,我唯一遇到的是“Release It!”一书的第17章:http://www.pragprog.com/titles/mnee/release-it上面的很多建议都是基于这一点的。

票数 7
EN

Stack Overflow用户

发布于 2010-11-07 18:30:44

ELMAH是一个非常好的日志库,也是log4net的一个不错的替代品。

关于日志的格式化(你说信息“凌乱”,但你没有确切解释这是什么意思)--确保每个条目与其他条目清楚地分开,并以可读的方式格式化(空格、换行符等)。

票数 2
EN

Stack Overflow用户

发布于 2010-11-08 23:32:02

@corriganjc有很多好的建议。

我想补充一些细节:如果可能的话,考虑使用UTC记录消息。一方面,查看在“你的”时区中生成的消息,然后必须记住正确的量来偏移它们以“正确”地解释它们,这可能是令人恼火的。另一方面,您的所有日志消息都可以按时间/日期排序,而无需进一步解释。(如果您记录了来自两个时区的消息,并且您使用“本地”时间记录了这些消息,则无法对它们进行排序,除非您将它们带到一个通用时区)。

使用GlobalContext、ThreadContext和LogicalThreadContext对象向消息中注入额外的上下文。建议记录诸如"session id“或"transaction id”之类的内容是一个很好的建议,并且可能可以使用"context“对象最有效地实现,而不是通过显式地将这些值添加到实际的日志记录调用点。您可以设置上下文一次,并通过添加格式化选项,使用ever message记录该上下文。

如果您使用context对象,请考虑创建“标准”值名称,甚至定义可供开发人员引用的字符串常量,这样他们在尝试添加上下文时就不会出现make输入错误:

代码语言:javascript
复制
//Context value names
public static class DiagnosticContextValueNames
{
  public static string TransactionId = "transactionid";
  public static string SessionId = "sessionid";
}

//In your code
log4net.ThreadContext.Properties[DiagnosticContextValueNames.TransactionId] = GetTransactionId();
log4net.ThreadContext.Properties[DiagnosticContextValueNames.SessionId] = GetSessionId();

//Somewhere later on...
logger.Info("hello");  // this message can be tagged with the transaction id and session id if you use the appropriate formatting options

您甚至可以考虑GlobalContext.Properties、ThreadContext.Properties等扩展方法,以帮助指导开发人员正确设置上下文值:

代码语言:javascript
复制
public static class LoggingExtensions
{
  public static void SetTransactionId(this ThreadContextProperties props, string trans)
  {
    props["TransactionId"] = trans;

    // Or, using constants as defined above...
    props[ThreadContextValueNames.TransactionId] = trans;
  }
}


// In your code...
log4net.ThreadContext.Properties.SetTransactionId(GetTransactionId());

// As compared to this:
log4net.ThreadContext.Properties["transactionid"] = GetTransactionId();

如果包装或继承自log4net记录器,则可以自动添加一些上下文信息,从而减轻开发人员的负担。有一种正确的方法来包装或继承log4net记录器,但这不是火箭科学。关键是将包装的记录器的类型传递给log4net。cfeduke在this post中的回答给出了一种包装log4net记录器的方法。

您可以效仿他的例子,但是按照"ILogger.Log“方法实现所有的日志记录调用。在" log“中,您可以为所有日志消息添加所需的属性:

代码语言:javascript
复制
// This approach requires more effort than simply populating the context properties "normally", and
// is probably overkill for most situations.  However, it can prove useful if you are able
// to have access to the context information that you want to log from within the Log method
// of the logger.
public void Log(type loggerBoundaryDeclaringType, LogLevel level, object message, object exception)
{
  log4net.ThreadContext.Properties["transactionid"] = GetTransactionId();
  log4net.ThreadContext.Properties["sessionid"] = GetSessionId();
  _logger.Log(loggerBoundaryDeclaringType, level, message, exception);
}

至于其他日志记录平台,您可以看看NLog。最近发布了一个新版本作为Beta版本。它有许多类似于log4net的功能。

您也可以考虑使用老的System.Diagnostics.TraceSource。如果你走这条路,看看codeplex上的Ukadc.Diagnostics。这是一个用于System.Diagnostics的附加库,它提供了丰富的消息格式化功能(类似于您可以使用log4net和NLog执行的操作)。Ukadc.Diagnostics的一个好处是它是一个仅限配置的依赖项。您不必接受源或引用依赖项即可使用它。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4117322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档