代码之家  ›  专栏  ›  技术社区  ›  Treb

写事件日志条目的最佳方法是什么?

  •  14
  • Treb  · 技术社区  · 16 年前

    我最近在部署Windows服务时遇到了一个问题。四台计算机没有造成任何问题,但在第五台计算机上,由于一个异常,任何启动服务的尝试都失败了。异常堆栈跟踪被写入事件日志,因此我认为应该很容易确定原因:

    protected override void OnStart(string[] args)
    {
        EventLog.WriteEntry("Starting service", EventLogEntryType.Information);
    
        try
        {
            //...
            base.OnStart(args);
        }
        catch (Exception ex)
        {
            EventLog.WriteEntry("Service can not start. Stack trace:" + ex.StackTrace, EventLogEntryType.Error);
            Stop();
            return;
        }
    
        EventLog.WriteEntry("Service started", EventLogEntryType.Information);           
    }
    

    但遗憾的是,没有任何信息被写入日志。我最后追踪到第一个日志条目。它引发了一个异常,因为应用程序事件日志中包含最近的条目,并且配置为仅覆盖7天以上的条目。

    考虑到我不能更改应用程序事件日志的配置,写入事件日志的最佳实践是什么?

    我应该一直把 EventLog.WriteEntry 在try块中,如果是,我应该如何处理异常(将异常写入事件日志可能是一个坏主意),我应该在 OnStart 方法,还是你有更好的建议?

    6 回复  |  直到 15 年前
        1
  •  2
  •   Mendelt    16 年前

    我认为记录异常是一种罕见的情况,在这种情况下你最好接受异常。在大多数情况下,你不希望你的应用在这一点上失败。

    但你为什么要自己写日志代码呢?使用像nlog或log4net这样的框架!这些异常也可以像我刚才所说的那样接受,但是您可以将日志输出重定向到另一个位置(文件、消息框等),只需更改配置即可。这使得解决这样的问题更加容易。

        2
  •  11
  •   community wiki anonymous    16 年前

    使用Log4NET

    使用log4net的好处是,您可以检查日志并以比在代码中考虑的更大的灵活性控制它。

    如果您正在记录事件日志,并且看到问题和没有事件日志条目,那么您可能总是切换到一个文件附加器日志,并且看到它在工作…它会告诉你这和事件日志有关。

    log4net也是防御性的,如果它不能写入日志条目,它不会使程序崩溃。所以您不会看到这种情况发生(这样您就不会有日志文件,但您的程序会运行,您可以再次指定第二种日志方法来获取日志文件)。

    log4net文档中的关键位是:

    [log4net]是一个尽最大努力的故障停止日志记录系统。

    “故障停止”是指 log4net不会在运行时抛出意外的异常,这可能会导致应用程序崩溃。 . 如果由于任何原因,log4net引发了未捕获的异常(除了可能引发的argumentexception和argumentnullexception),请向log4net-user@logging.apache.org邮件列表发送电子邮件。未捕获的异常作为需要立即关注的严重错误处理。

    此外,当指定的输出流未打开、不可写或已满时,log4net将不会还原为System.console.out或System.console.error。这样可以避免由于日志记录失败而淹没用户终端,从而损坏其他工作程序。但是,log4net将向system.console.error和system.diagnostics.trace输出一条消息,指示无法执行日志记录。

    (我的重点)

    大多数情况下,都有一个图书馆比你做得更好。最好的事情是永远不要重新发明,log4net解决了登录.net的问题,会让你的生活更轻松。

        3
  •  4
  •   MusiGenesis    16 年前
    System.Diagnostics.EventLog log = 
        new System.Diagnostics.EventLog("YourLogNameHere");
    log.ModifyOverflowPolicy(
        System.Diagnostics.OverflowAction.OverwriteAsNeeded, 0);
    

    这样可以解决溢出问题。一旦正确配置,事件日志通常非常可靠。在使用事件日志时,我曾经添加了一个快速的紧急备份日志程序,它只需写入一个文本文件(这需要大约5分钟的时间)。从来没有人打过电话。

        4
  •  3
  •   Christian.K    16 年前

    您不能只使用ServiceBase类已经提供的默认事件日志机制吗?如果您的服务没有启动,那么它会自动在事件日志中写入一个条目,说明是这样(使用stacktrace)。

    除此之外,关于log4net(或任何其他最好的工作,如日志系统)的评论,我认为这真的取决于您试图实现什么。

    在您的示例中,使用log4net(或对ServiceBase事件日志的内置支持)很可能是正常的。

    但是,在某些情况下,即使发生了错误,并且无法将该事实记录到某个地方,这也是一个问题。例如,假设一个身份验证或授权系统。如果您不能成功可靠地登录,例如,由于错误的凭据而导致密码验证失败,则可能不允许您继续(同样,如果您的密码验证成功,那么顺便说一句)。

    因此,有时您需要知道日志记录尝试何时失败,并自行处理。 当然,这是有限制的(鸡蛋问题),并且您所做的工作非常特定于特定的应用程序或场景。

        5
  •  2
  •   gimel    16 年前

    研究如何利用 Logging App Block .

    企业库日志记录应用程序块简化了常见日志记录功能的实现。开发人员可以使用日志块将信息写入各种位置:

    • 事件日志
    • 电子邮件
    • 数据库
    • 消息队列
    • 文本文件
    • WMI事件
    • 使用应用程序块扩展点的自定义位置
        6
  •  0
  •   Ed Sykes    15 年前

    让我们后退一步:

    系统事件日志用于提醒系统管理员系统上的某个问题。您应该允许服务启动失败。这将显示在系统错误日志中,报告的源代码为“服务控制管理器”。这意味着系统管理员将知道故障。

    接下来,如果您需要进行故障排除,那么应该将异常记录到程序顶层的磁盘文件中。您还应该重新传输它们,以便服务启动失败。

    然后,您可以在系统事件日志中识别任何问题,并将失败时间交叉引用到应用程序日志中。