2008-11-24 82 views
14

我最近在部署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方法中的事件日志状态,或者你有更好的建议吗?

回答

2

我认为日志记录异常是您最好吞咽异常的罕见情况之一。在大多数情况下,你不希望你的应用程序失败。

但是,为什么你自己写自己的日志代码呢?使用像NLog或Log4Net这样的框架!这些也可以像我刚刚说的那样吞下异常,但只需更改配置,就可以将日志记录输出重定向到其他位置(文件,消息框等)。这使得解决这样的问题变得更容易。

+15

写入事件日志不是“自己写日志代码”。 – MusiGenesis 2008-11-24 10:58:57

+0

@MusiGenesis:请解释一下。对于我来说,编写日志特定的异常处理是编写代码,例如Log4Net或NLog已经做得更好。我没有理由写另一个日志框架。 – Mendelt 2008-11-24 11:10:49

11

使用log4net的

使用的log4net的好处是,你可以检查记录,并与更灵活地控制它比你自己的代码中占了。

如果您正在登录到事件日志,并且看到问题并且没有事件日志条目,那么您总是可以切换到文件appender日志并已经看到它正在工作......然后它会告诉您它是与事件日志有关。

log4net也是防御性的,如果它没有写入日志条目,它不会崩溃你的程序。所以你不会看到这种情况发生(所以你不会有你的日志文件,但你的程序将会运行,并且你可能已经指定了第二种日志记录方法来获取日志文件)。

log4net的文档中的键位是这样的:

[log4net的]是一个尽力而为和故障停机记录系统。

通过失败停止,我们的意思是log4net不会在运行时抛出意外的异常,可能会导致您的应用程序崩溃。如果出于任何原因,log4net会抛出一个未捕获的异常(除了可能抛出的ArgumentException和ArgumentNullException外),请发送电子邮件至[email protected]邮件列表。未捕获的异常被视为需要立即关注的严重错误。

此外,log4net在其指定的输出流未打开,不可写入或变满时,将不会恢复到System.Console.Out或System.Console.Error。这避免了由于记录失败而导致用户的终端泛滥,从而破坏了另外的工作程序。但是,log4net会向System.Console.Error和System.Diagnostics.Trace输出一条消息,指出无法执行日志记录。

(我的重点)

对于大多数的事情,有可能做的更好比你会图书馆。最好的事情是永远不要重新发明,log4net可以解决.Net中的日志记录,并会让你的生活更轻松。

+2

实际上,log4net确实有能力导致应用程序崩溃(至少是紧凑的框架/ Windows移动应用程序) - 有点。使用log4net的UDP appender会使ActiveSync(将设备连接到PC)崩溃。我在演示中了解到这一点,我们失去了一个巨大的联系。 – MusiGenesis 2008-11-24 11:14:33

+0

我认为在Windows服务中使用log4net和Windows事件日志是完全合理的。用于非常高级别的事件的Windows事件日志,即系统管理员可以快速查看的事件日志;和一个更详细的log4net日志,它提供了关于你的代码活动的丰富细节。 – 2013-12-05 09:46:13

2

研究利用Logging App Block

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

  • 事件日志
  • 的电子邮件
  • 数据库
  • 消息队列
  • 的文本文件
  • WMI事件
  • 使用应用程序块扩展点的自定义位置
4
System.Diagnostics.EventLog log = 
    new System.Diagnostics.EventLog("YourLogNameHere"); 
log.ModifyOverflowPolicy(
    System.Diagnostics.OverflowAction.OverwriteAsNeeded, 0); 

这应该解决您的溢出问题。一旦配置正确,事件日志通常非常可靠。在使用事件日志时,我曾经添加一个简单的写入文本文件的紧急备份记录器(这需要大约5分钟的时间)。它从来没有被召唤过。

3

你不能只使用ServiceBase类已经提供的默认事件日志机制吗?如果你的服务没有启动,会自动向事件日志中写入一个条目,说明如此(使用堆栈跟踪)。

除此之外,关于log4net(或任何其他尽力而为的日志系统)的评论,我认为这取决于你想达到的目标。

在您使用log4net的示例中(或者对ServiceBase的eventlogging的内置支持)很可能是可以的。

但是,在某些情况下,即使发生错误并且该事实不能记录在某处也是一个问题。例如,假设一个认证或授权系统。如果您无法成功和可靠地记录该密码,例如由于凭证错误而导致密码验证失败,则可能不允许继续(如果密码验证成功,则同样如此BTW)。

因此,有时您需要知道日志记录尝试失败的时间并自行处理。 这当然是有限制的(鸡 - 鸡蛋问题),你做什么是高度特定于特定的应用程序或场景。

0

让我们退后一步,在这里:

系统事件日志有提醒系统管理员,有与系统上的一些问题。您应该允许服务开始失败。这将在系统错误日志中显示,并报告“服务控制管理器”的来源。这意味着系统管理员将知道失败。

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

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

相关问题