【问题标题】:Log4Net smtp appender only send email when error with full log(debug & info & error). Only when the application endsLog4Net smtp appender 仅在出现完整日志错误时发送电子邮件(调试 & 信息 & 错误)。仅当应用程序结束时
【发布时间】:2011-08-19 04:33:18
【问题描述】:

我正在尝试在我拥有的 log4net.config 文件中配置一个 smtp 附加程序。问题是我已经查看了整个互联网,但无法找到在包含所有其他日志信息(例如信息、调试、错误、致命)发生错误时如何发送电子邮件。仅在应用程序结束时(不是每次发生错误时)。

所以我只想在以下情况下收到这封电子邮件: 申请结束 + 包含所有日志信息(DEBUG、INFO、ERROR、FATAL)+ 仅当发生错误时。

详细说明这是因为我在 c sharp 中处理我的异常的方式,在整个地方都有多个级别的处理,所以如果发生错误,无论多少次我都只想收到一封电子邮件。另外我不想使用多个日志,而是 根目录中只有一个。

谢谢。

【问题讨论】:

    标签: c# .net smtp log4net log4net-configuration


    【解决方案1】:

    将阈值更改为错误。此外,log 4net 仅在应用程序关闭时发送电子邮件。您可以提前发送。但是您首先需要复制它(因为 org 文件仍在使用中),然后您可以通过电子邮件发送副本。

    【讨论】:

      【解决方案2】:

      SmtpAppender 无法自行完成此操作。所以我所做的是为MemoryAppender 类型的appender 创建另一个appender。我在这个记录器上设置了一个阈值,只包含应该触发SmtpAppender 的消息,例如Error。我们稍后使用它来确定我们是否要发送记录了更多级别的电子邮件。

      我们实际上并不关心MemoryAppender 中的消息——我们只关心它最后是否包含消息。我们通过电子邮件收到的消息实际上来自SmtpAppender

      在我的程序结束时,我检查内存附加程序以查看它的 GetEvents() 是否包含任何事件。如果是这样,我不会阻止SmtpAppender 正常运行。

      两个 appender 的 Log4Net 配置:

      <appender name="ErrorHolder" type="log4net.Appender.MemoryAppender" >
          <onlyFixPartialEventData value="true" />
          <!-- if *any* message is logged with this level, the email appender will 
               be used with its own level -->
          <threshold value="ERROR" />
      </appender>
      
      <appender name="Email" type="log4net.Appender.SmtpAppender">    
          <!-- the level you want to see in the email IF ErrorHolder finds anything -->
          <threshold value="INFO"/> 
          <bufferSize value="512" />
          <lossy value="false" /> <!-- important! -->   
          <to value="name@domain.com" />
          <from value="name@domain.com" />
          <subject value="ERROR: subject" />
          <smtpHost value="smtpserver" />    
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%newline%date [%thread] %-5level %logger [%property{NDC}] - %message%newline%newline%newline" />
          </layout>    
      </appender>
      
      <root>
        <level value="ALL" />
        <appender-ref ref="ErrorHolder" />
        <appender-ref ref="Email" />
      </root>
      

      如果 ErrorHolder 附加程序为空,则在应用程序结束时运行此命令以禁用 SmtpAppender

      // trigger loggers if errors occurred:
      var memoryAppender = ((Hierarchy)LogManager.GetRepository())
          .Root.Appenders.OfType<MemoryAppender>().FirstOrDefault();
      
      if (memoryAppender != null && memoryAppender.GetEvents().Length == 0)
      {
          // there was no error so don't email anything
          var smtpAppender = ((Hierarchy)LogManager.GetRepository())
              .Root.Appenders.OfType<SmtpAppender>().FirstOrDefault();
      
          if (smtpAppender != null)
          {
              smtpAppender.Threshold = Level.Off;
              smtpAppender.ActivateOptions();
          }
      }
      

      【讨论】:

      • 这似乎是我在解决方案中建议的一个相当复杂的版本。
      • 没错,你是对的,我确实接受了你最后检查的想法,这是真的。但是当寻找如何在附加程序中查看某些级别的事件时(在这里)。如果我可以在其中获取事件,我找不到任何关于任何附加程序的东西。所以我唯一能找到的是一个 MemoryAppender 并且我使用了它。
      • 这里有一篇关于追踪 log4net 问题的帖子:stackoverflow.com/questions/756125/…
      【解决方案3】:

      这听起来像是应用程序配置问题,而不是 log4net 配置问题。我建议在您的应用程序关闭时放置一个方法,如果它检测到其中存在错误,则通过电子邮件向您发送日志文件。您可以通过在记录错误的每个位置将全局变量从 false 翻转为 true 来检测此错误,或者您可以等到应用程序结束,然后读取日志文件以查看它是否包含错误。第一种方法在关机时会更快,但这意味着在多个地方修改你的代码。后者允许您只添加一种方法,但在大文件中可能需要更长的时间。

      第三种选择是使用 log4net 将错误发送到第二个日志文件(这样它们会转到两个地方)。然后,当您的应用程序正在关闭并且您正在检查是否应该通过电子邮件发送日志时,只需检查仅错误文件是否存在。如果存在,请将其删除(以便下次不再存在)并通过电子邮件发送完整日志。

      【讨论】:

      • 如何在程序结束时检查是否出现任何错误您要查找什么?在 logger、appender? 中,使用了哪些方法和字段。你能贴一些代码吗?
      • 我发现您在尝试发送实际日志文件时可能会遇到文件 IO 问题(另一个进程已打开它)。即使你刷新fileAppender,释放锁并复制它,如果log4Net当时正在滚动日志文件,我仍然会遇到IO问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-02
      • 1970-01-01
      • 2014-02-21
      • 2019-05-06
      • 2021-12-01
      • 1970-01-01
      相关资源
      最近更新 更多