我怎么能抽出记录细节呢?

时间:2012-07-14 15:45:42

标签: c# .net windows-services error-logging

我的代码库中有很多地方,我希望在出现问题时得到通知 - 这是我想象的很常见。查看以下代码,我如何重新考虑此方法以抽象出电子邮件/日志记录详细信息?目前,这分散在大约100个地方,我真的需要做点什么!

public bool MethodOne() {
    string message;
    bool success = new Task().Execute();

    message = string.Format( "MethodOne was {0} successful.", 
        success ? "" : "not");

    if( !success )
        SMTP.send( to, from, message );

    System.Diagnostic.EventLog.WriteEntry( executingAssembly, message);

    return success; 
};

我目前的想法是做类似以下的事情:

public class Log
{
    string to = "me@me.com",
        from = "system@me.com",
        subject = "Error occured";

    public void Write( string executingAssembly, string message, bool sendEmail )
    {
        System.Diagnostic.EventLog.WriteEntry( executingAssembly, message);

        if( sendEmail )
            SendEmail( to, from, subject, message );
    }

    private void SendEmail( to, from, subject, message )
    {
        // Details to send email.
    }
}

问题: 如何在应用程序中提高日志记录错误和发送通知的可维护性?

5 个答案:

答案 0 :(得分:6)

考虑使用Logging and Log Manager程序,例如NLog。然后,您可以编写一组业务规则来登录nlog.config(或application.config)文件,该文件指定要记录到的不同位置(目标),您可以指定要为每个位置记录的内容(取决于严重性和类) 。

取自NLog网站

一些NLog支持的目标

  • 文件 - 单个文件或多个文件,具有自动文件命名和存档
  • 事件日志 - 本地或远程
  • 数据库 - 将您的日志存储在.NET支持的数据库中
  • 网络 - 使用TCP,UDP,SOAP,MSMQ协议
  • 命令行控制台 - 包括消息的颜色编码
  • 电子邮件 - 只要发生应用程序错误,您就可以收到电子邮件
  • ASP.NET跟踪

使用NLog的一些主要功能

  • 通过配置文件和编程方式配置非常简单
  • log4xxx中已知的易于使用的记录器模式
  • 使用缓冲,异步日志记录,负载平衡,故障转移等的高级路由
  • 跨平台支持:.NET Framework,.NET Compact Framework和Mono(在Windows和Unix上)

答案 1 :(得分:0)

Microsoft Enterprise Library有两个非常好的块,Logging Application BlockException Handling Application Block

这是一个基于策略的系统,允许您在.config文件中定义不同的策略。有了适当的策略和一些异常处理程序,您可以编写诸如以下的catch块:

catch(Exception ex)
{
  if(HandleException("My Datalayer Policy", ex)) throw;
} 

可以将异常策略配置为使事件冒泡。非常好的图书馆。

Logging块也使用.config中的“策略”,这些策略称为类别。例如,如果我想记录一些消息,但我想要发送电子邮件,我会使用两个类别和两个监听器,一个用于记录事件,另一个用于通过电子邮件发送事件的详细信息。如果未指定电子邮件类别,例如,当Sucess为true时,则仅发生日志记录事件。当成功为假时,将应用“电子邮件”类别,并且两个侦听器都会触发。

答案 2 :(得分:0)

一些评论:

您的日志类应该是静态类 您应该尝试/捕获所有错误处理代码,因为错误管理应该做的最后一件事......是导致错误! 您可以使用枚举列出主要错误类型和/或另一个严重性/ ...
我更喜欢将日志错误放入与App相同的文件夹中的小文本文件中。更容易处理,客户可以通过邮件发送(我不喜欢应用程序通过邮件发送数据的想法,你应该检查你的客户/用户是否正常。)。
您可以从Reflection获取执行程序集或其他信息 您可能还会从StackTrace中获取其他有价值的信息(我会在错误日志中编写Stacktrace,保存了很长时间)。
您还应该在应用程序级别捕获未处理的异常。 请描述更多错误以获得更具体的答案。

答案 3 :(得分:0)

我认为没有成功的任务执行是特殊的(否则你会发送很多电子邮件给某人)。因此,在任务失败时抛出异常(您还可以提供有关任务失败原因的其他详细信息)。以下是一些使用NLog的代码:

private static Logger _logger = LogManager.GetCurrentClassLogger();

public bool MethodFoo() 
{
   try
   {
       new Task().Execute();
       _logger.Info("Task executed successfully");
       return true;           
   }
   catch(YourCustomException ex)
   {
       _logger.ErrorException("Cannot execute task", ex);
       return false;
   }
}

唯一剩下的就是NLog配置:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <targets>
        <target name="eventLog" xsi:type="EventLog" 
                log="Application" source="Your Source" machineName="."
                layout="${longdate}|${level}|${callsite:methodName=true}${message}" />
        <target name="email" xsi:type="Mail" 
                subject="Error occured"
                to="me@me.com"
                from="system@me.com"
                smtpServer="127.0.0.1"
                smtpPort="25"
                body="${longdate}|${message}" />  
    </targets> 
    <rules>
        <logger name="*" minlevel="Info" writeTo="eventLog" />
        <logger name="*" minlevel="Error" writeTo="email" />
    </rules>
</nlog>

您需要两个目标 - 一个用于将信息和错误消息写入事件日志,另一个用于通过电子邮件发送错误通知。此外,我创建了两个规则 - 所有级别信息及以上的消息都将发送到事件日志,但错误和致命消息将通过电子邮件发送。

BTW与呼叫站点布局渲染器${callsite:methodName=true}方法名称将插入到日志消息中。因此,您无需在代码中指定它。

答案 4 :(得分:0)

如果要抽象其他人建议的日志记录抽象,可以使用Commons Logging。是的,这是两层间接,但有些情况可能会有用。

您可以安装NuGet包,然后在您的代码中使用它:

// obtain logger instance
ILog log = LogManager.GetCurrentClassLogger();

// log something
log.Info("Some Debug Log Output");

然后将commons日志库配置为使用NLog,如下所示:

<common>
  <logging>
    <factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog20">
      <arg key="configType" value="INLINE" />
    </factoryAdapter>
  </logging>
</common>

然后您可以配置NLog。 @Sergey Berezovskiy的回答就是一个例子。

关键是,Commons Logging库不允许您在NLog或log4net或Logging Application Block之间进行选择。您可以将后端切换到您想要的任何内容。如果您正在编写可能托管在各种项目类型中的dll或其他内容,这将非常有用。当然,它也可能是一个无用的额外间接层。这取决于你正在做什么。