我最近在部署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
方法,或者你有更好的建议吗?
答案 0 :(得分:11)
使用log4net
使用log4net的优势在于,您可以检查日志记录并对其进行控制,其灵活性远远超出您在代码中所占用的灵活性。
如果您正在登录事件日志,并且看到问题而没有事件日志条目,您可以随时切换到文件追加器日志并看到它正常工作......然后会告诉您这是某事与事件日志有关。
log4net也是防御性的,如果它无法写入日志条目,它不会崩溃你的程序。所以你不会看到这种情况发生(所以你不会有你的日志文件,但你的程序会运行,你可以再次指定第二种日志文件获取日志文件)。
log4net文档中的关键位是:
[log4net]是尽力而为的故障停止日志记录系统。
通过失败停止,我们的意思是 log4net不会在运行时抛出意外异常,从而可能导致应用程序崩溃。如果由于任何原因,log4net抛出一个未捕获的异常(可能抛出的ArgumentException和ArgumentNullException除外),请发送电子邮件至log4net-user@logging.apache.org邮件列表。未捕获的异常被视为需要立即关注的严重错误。
此外,当log4net的指定输出流未打开,不可写或变满时,log4net将不会还原为System.Console.Out或System.Console.Error。这样可以避免因为日志记录失败而淹没用户终端而破坏其他工作程序。但是,log4net将向System.Console.Error和System.Diagnostics.Trace输出单个消息,指示无法执行日志记录。
(我的重点)
对于大多数事情来说,有一个图书馆比你做得更好。最好的办法是永远不要重新发明,log4net解决了登录.Net的问题,让你的生活更轻松。
答案 1 :(得分:4)
System.Diagnostics.EventLog log =
new System.Diagnostics.EventLog("YourLogNameHere");
log.ModifyOverflowPolicy(
System.Diagnostics.OverflowAction.OverwriteAsNeeded, 0);
这应该可以解决您的溢出问题。一旦正确配置,事件日志通常非常可靠。使用事件日志时,我曾经添加了一个简单写入文本文件的快速紧急备份记录器(这需要大约5分钟才能写入)。它永远不会被召唤。
答案 2 :(得分:3)
您不能只使用ServiceBase类已经提供的默认事件日志机制吗?如果您的服务没有启动,则会自动在事件日志中写入条目(使用stacktrace)。
除此之外,关于log4net(或任何其他最好的努力,如日志系统)的评论,我认为这实际上取决于你想要实现的目标。
在您的示例中使用log4net(或ServiceBase的事件记录的内置支持)很可能是正常的。
但是,有些情况甚至会发生错误并且无法在某处记录该事实是一个问题。例如,假设一个身份验证或授权系统。如果您无法成功且可靠地记录密码认证因密码错误而失败,则可能不允许继续(如果您的密码认证成功,则BTW也是如此)。
因此,有时您需要知道日志记录尝试何时失败并自行处理。 这当然是有限的(鸡蛋问题),你做的是特定的应用程序或场景。
答案 3 :(得分:2)
我认为记录异常是您最好吞下异常的罕见情况之一。在大多数情况下,您不希望您的应用程序失败。
但是你为什么要自己编写日志代码呢?使用像NLog或Log4Net这样的框架!这些也像我刚刚说的那样吞下异常,但你可以通过配置更改将日志记录输出重定向到不同的位置(文件,消息框等)。这使得解决这类问题变得更加容易。
答案 4 :(得分:2)
考虑使用Logging App Block。
企业库日志记录应用程序块简化了常见日志记录功能的实现。开发人员可以使用Logging Block将信息写入各个位置:
- 事件日志
- 电子邮件
- 数据库
- 消息队列
- 文本文件
- WMI事件
- 使用应用程序块扩展点的自定义位置
答案 5 :(得分:0)
我们在这里退后一步:
系统事件日志用于警告系统管理员系统上出现问题。您应该允许服务启动失败。这将显示在系统错误日志中,并显示“Service Control Manager”的报告源。这意味着系统管理员将知道失败。
接下来,如果您需要进行故障排除,则应将异常记录到程序顶层磁盘上的文件中。您还应该重新抛出它们,以便服务启动失败。
然后,您可以识别系统事件日志中的任何问题,并将失败时间交叉引用到应用程序日志中。