asp.net-core - NLog 初始发送和多次批量发送电子邮件

标签 asp.net-core asp.net-core-mvc nlog

背景

我有一个用 asp.net core v2.2 编写的 Web 应用程序。我使用 NLog 作为我的第 3 方记录器,每次出现应用程序错误时它都会向我发送电子邮件,效果很好。

    <targets>
       <!--eg email on error -->
        <target xsi:type="Mail"
                  name="emailnotify"
                  header="An Error has been reported By foo.com (${machinename}) ${newline}  "
                  layout="${longdate} ${level:uppercase=true:padding=5} - ${logger:shortName=true} - ${message} ${exception:format=tostring} ${newline}"
                  html="true"
                  addNewLines="true"
                  replaceNewlineWithBrTagInHtml="true"
                  subject="Error on foo.com (${machinename})"
                  to="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bcdad3d3fcdad3d392dfd3d1" rel="noreferrer noopener nofollow">[email protected]</a>"
                  from="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="75131a1a35131a1a5b161a18" rel="noreferrer noopener nofollow">[email protected]</a>"
                  secureSocketOption="StartTls"
                  smtpAuthentication="basic"
                  smtpServer="${environment:EmailConfigNlogSMTPServer}"
                  smtpPort="25"
               smtpusername="${environment:EmailConfigNlogSMTPUsername}"
                smtppassword="${environment:EmailConfigNlogSMTPPassword}" />
        <!-- set up a blackhole log catcher -->
        <target xsi:type="Null" name="blackhole" />
    </targets>

     <rules>
        <!-- Skip Microsoft logs and so log only own logs-->
        <logger name="Microsoft.*" level="Info" writeTo="blackhole" final="true" />
        <!-- Send errors via emailnotify target -->
        <logger name="*" minlevel="Error" writeTo="emailnotify" final="true" />
      </rules>

但是,有时在我有机会解决问题之前,可能会在短时间内连续收到大量电子邮件,让我感觉自己受到了“垃圾邮件”。

  1. 一个例子可能是在极少数情况下,例如我的应用程序的第 3 方搜索引擎出现故障。此时,每个在网站上进行搜索的用户都会生成错误,从而可能产生大量电子邮件。
  2. 另一个例子是,当公司收集网站技术统计数据或只是简单的狡猾请求时,就会出现推测性 404 错误。即/bitcoin/xxx 或/shop/xxx 或 git/.head/xxx。

从历史上看,我在收到的一些 404 中使用过“过滤器”功能,并设置了一些。请参阅下面的示例。但是,在批量格式中,我希望收到有关所有 404 或 500 的通知。我认为尝试过滤掉看起来不相关的内容不是一个好主意,因为您可能会开始错过关键信息,例如黑客尝试、SQL 注入(inject)攻击或应用程序嗅探:

    <filters>
        <when condition="contains('${message}','.php')" action="Ignore" />
        <when condition="contains('${message}','wp-includes')" action="Ignore" />
        <when condition="contains('${message}','wordpress')" action="Ignore" />
        <when condition="contains('${message}','downloader')" action="Ignore" />
      </filters>
    </logger>

要求

我想在我的应用程序日志记录中引入以下逻辑:

  1. 当发生第一个 500 个类型错误时(即在网站上执行搜索时出错、访问数据库时出错),我会收到电子邮件通知,以便我在应用程序第一次出现初始错误时立即知道
  2. 在出现初始错误后批量通知连续 500 个错误,以便我知道何时会发生此错误,但它不会继续向我发送“垃圾邮件”。
  3. 批量通知所有 404、405 错误

这些批量电子邮件会在 50 个错误后通知我,或者每天一次,以先到者为准。

理想情况下,我希望批量电子邮件的格式为:

批量电子邮件

主题:500 个错误 (13) | 404错误(2)

表格格式的正文:

500 Errors (13)
-----------------------------------------------------
| When                 | Message                    |
-----------------------------------------------------
| 2019-11-13 11:10:29  | Website search engine down |
-----------------------------------------------------
| 2019-11-13 11:10:30  | Website search engine down |
-----------------------------------------------------
| 2019-11-13 11:10:31  | Website search engine down |
-----------------------------------------------------
| 2019-11-13 11:10:32  | Website search engine down |
-----------------------------------------------------
| 2019-11-13 11:10:33  | Website search engine down |
-----------------------------------------------------
| 2019-11-13 11:10:34  | Website search engine down |
-----------------------------------------------------
| 2019-11-13 11:10:35  | Website search engine down |
-----------------------------------------------------
| 2019-11-13 11:11:01  | Login failed for user foo  |
-----------------------------------------------------
| 2019-11-13 11:11:01  | Login failed for user foo  |
-----------------------------------------------------
| 2019-11-13 11:11:01  | Login failed for user foo  |
-----------------------------------------------------
| 2019-11-13 11:11:02  | Login failed for user foo  |
-----------------------------------------------------
| 2019-11-13 11:11:02  | Login failed for user foo  |
-----------------------------------------------------
| 2019-11-13 11:11:02  | Login failed for user foo  |
-----------------------------------------------------    

404 Errors (2)
-----------------------------------------------------
| When                 | Message                    |
-----------------------------------------------------
| 2019-11-13 11:10:45  | /bitcoin not found         |
-----------------------------------------------------
| 2019-11-13 11:10:57  | /shop not found            |
-----------------------------------------------------

或者,我很乐意为 500、404 或 405 提供单独的批量电子邮件。

在上面的批量电子邮件示例中,应用程序会立即通过两封单独的电子邮件通知我存在问题

  1. 网站搜索引擎关闭
  2. 用户无法访问 SQL 数据库

然后在遇到 50 个错误或每天一次后,发送批量电子邮件。

问题

仅使用 NLog 配置就可以实现我的要求吗?

我可以看到如何使用 NLog 的 buffer wrapper 执行批量通知配置,尽管我认为不可能以我理想的表格格式输出。

      <target xsi:type="BufferingWrapper"
              name="bulkemailnotify"
              bufferSize="50"
              flushTimeout="86400000‬"
              slidingTimeout="False"
              overflowAction="Flush">
        <target xsi:type="emailnotify" />
      </target>

如果没有,它会考虑以下其中一项吗?

  1. Extending NLog
  2. Removing NLog and adding a custom logger

理想情况下,我会继续使用 NLog,并且只会添加自定义记录器作为最后的手段。

最佳答案

假设 ${aspnet-response-statuscode} 是返回 HTTP 状态代码的:

那么我们可以有以下两个目标:

  • 具有第一个错误的即时邮件目标(通过第一个事件即时触发,并等待 5 分钟后再触发)
  • 包含所有错误的批量邮件目标(所有事件在 5 分钟后触发)

那么你可能会这样做:

<targets async="true">
   <target xsi:type="SplitGroup" name="special-mail">
       <target xsi:type="FilteringWrapper" name="filter-mail">
          <filter type="whenRepeated" layout="${aspnet-response-statuscode}" timeoutSeconds="300" action="Ignore" />
          <target xsi:type="Mail" name="instant-mail">
                 <header>Instant Error Report</header>
          </target>
       </target>
       <target xsi:type="BufferingWrapper" name="buffer-mail" flushTimeout="300000">
           <target xsi:type="Mail" name="bulk-mail">
                <header>Bulk Error Report</header>
           </target>
       </target>
   </target>
</targets>
<rules>
    <logger name="Microsoft.*" maxlevel="Info" final="true" />
    <logger name="*" minlevel="Error" writeTo="special-mail" final="true" />
</rules>

不太熟悉邮件目标布局(页眉+正文+页脚)以及制作美观的 html 电子邮件。但您可能可以从互联网上窃取一些东西。

关于asp.net-core - NLog 初始发送和多次批量发送电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58839987/

相关文章:

c# - 根据模型 asp.net core api 验证 Json 字符串

asp.net-core - ASP.NET Core 2 中 HttpResponseBase.BufferOutput 属性的等价物是什么?

c# - 如何在 ASP.NET Core 中的子域之间共享 session ?

docker - 找不到nlog.config-文件.Net core 3.1和Docker

nlog - 使用 NLog 打印多行消息

缓存过期后 Azure 功能标志不会更新

visual-studio - 在 Docker 容器中运行时的 .NET Core 分析

c# - ASP.Net Core MVC - 在几个 ViewModel 属性上使用 ModelState 验证的 Ajax 表单提交

c# - ASP.NET Core 2.1 - 身份验证 cookie 已删除,但用户仍可登录而无需重定向到外部登录

NLog,Npgsql.PostgresException : '42804: column "DateTime"is of type timestamp without time zone but expression is of type text