0

我的代码库中有很多地方我希望在出现问题时得到通知——我想这很常见。看看下面的代码,我怎样才能重构这个方法来抽象出电子邮件/日志记录的细节?目前,这分散在大约 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.
    }
}

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

4

5 回答 5

6

考虑使用 Logging 和 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 上)
于 2012-07-14T15:49:43.747 回答
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>

您需要两个目标 - 一个用于将信息和错误消息写入事件日志,第二个用于通过电子邮件发送错误通知。我还创建了两条规则——所有 Info 及以上级别的消息都将发送到 Event Log,但 Error 和 Fatal 消息将通过电子邮件发送。

顺便说一句,调用站点布局渲染器${callsite:methodName=true}方法名称将被插入到日志消息中。因此,您无需在代码中指定它。

于 2012-07-14T17:14:43.143 回答
0

Microsoft Enterprise Library 有两个非常好的块,日志应用程序块异常处理应用程序块

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

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

可以将异常策略配置为冒泡或不冒泡事件。很不错的图书馆。

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

于 2012-07-14T15:59:34.150 回答
0

几点说明:

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

于 2012-07-14T16:01:29.650 回答
0

如果您想抽象此处其他人建议的日志记录抽象,您可以使用Commons Logging。是的,这是两层间接,但在某些情况下它可能有用。

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

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

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

然后配置公共日志库以使用 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 或可能托管在各种项目类型中的东西,这可能会很有用。当然,它也可以是一个无用的额外间接层。这只是取决于你在做什么。

于 2014-12-11T17:49:45.360 回答