2011年10月17日 星期一

使用NLog - Advanced .NET Logging (5)

透過Mail target將Log訊息寄發到指定的Email中

在之前介紹的ELMAH文章中「ASP.NET MVC + ELMAH 監控並記錄你的網站錯誤資訊 3」有介紹到,當系統發生了 Exception 狀況時,就會寄發通知信件到指定的 Email 中,雖然說我們可以在某些特定的 Exception 發生時在去寄發通知(詳見「ELMAH - 自訂錯誤通知郵件的設定(於特定Exception)」),但是只依據特定的 Exception 種類來通知,光是設定就很累人,因為Exception的種類有很多,並非我們可以完全掌握住。

最好的方式就是在程式之中,於捕捉 Exception 的程式碼去使用 NLog 記錄Exception訊息,並且做好 Exception 的Log 分級,然後在 NLog.Config 中再去做設定,當 Log 於什麼樣的等級發生時就去使用 Mail target 寄發通知給特定人員的 Email 信箱中。

接下來就會說明如何設定並透過Mail Target 將Log訊息寄發給特定人員。

 



Mail Taget的設定

NLog Documentation – Mail target 的內容中已經有很詳盡的說明了,在說明文件的一開始就明白的表示「Sends log messages by email using SMTP protocol.

Configuration Syntax:

<targets>
  <target xsi:type="Mail"
          name="String"
          header="Layout"
          footer="Layout"
          layout="Layout"
          html="Boolean"
          addNewLines="Boolean"
          encoding="Encoding"
          subject="Layout"
          to="Layout"
          bcc="Layout"
          cc="Layout"
          from="Layout"
          body="Layout"
          smtpUserName="Layout"
          enableSsl="Boolean"
          smtpPassword="Layout"
          smtpAuthentication="Enum"
          smtpServer="Layout"
          smtpPort="Integer" />
</targets>

而最簡單也是最基本的Mail target 設定方式如下:

<target name="Mail_Terget_名稱" type="Mail"
    smtpServer="用來寄信的Smtp Mail Server"
    smtpPort="Smtp Server 的 Port"
    smtpUsername="寄發信件的使用者名稱"
    smtpPassword="寄發信件的使用者密碼"
    from="寄出信件的Email"
    to="主要收信的Email"
    cc="要CC的Email"
/>

在上面的設定當中,並沒有設定信件的Subject以及信件的Body,先用預設的格式來寄發,以下為收到通知信件的主旨:沒有設定Subject的話,就是會以「Message from NLog on MACHINE_NAME」來當做信件主旨。

image

而信件的內容:

image

是的,只有短短的訊息而已,文件的說明就是「Default: ${message}」,其實要什麼樣的格式與內容都可以自訂,進階一點的話,可以用「${longdate}|${level:uppercase=true}|${logger}|${message}」,這樣設定的信件內容則是:

image

我們再來改變一下寄出信件的Subject與body內容,並且試著加入一些屬性: 

image

信件主旨:

image

信件內容:

image

所以信件的內容與主旨都可以讓我們自己去做設定,如果說要讓信件主旨能夠清楚顯示錯誤在哪裡發生、發生了什麼樣的Exception,都可以在Subject中去使用Layout Renderer做設定。

 

Mail Target 進階設定

修改後Mail target設定:

image

寄出的通知主旨與內容:

image

 

使用Gmail來寄發NLog通知信件

有些網站專案不太可能有專用的Email或是SMTP Mail Server來使用,而最多人會想到的就是申請一個Gmail拿來寄發,這邊是NLog文件中所提供使用Gmail寄發通知信的 Mail target 設定範例:

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <targets>
    <target name="gmail" type="Mail"
            smtpServer="smtp.gmail.com"
            smtpPort="587"
            smtpAuthentication="Basic"
            smtpUsername="user@gmail.com"
            smtpPassword="password"
            enableSsl="true"
            from="emailaddress@gmail.com"
            to="recipient@example.com"
            cc="alice@example.com;bob@example.com;charlie@example.com"
          />
  </targets>
  <rules>
    <logger name="*" minlevel="Debug" writeTo="gmail" />
  </rules>
</nlog>

參考連結:NLog Documnetation - Using NLog with GMail

原本在NLog 2.0 之前的版本,Mail target 是沒有支援 enableSsl 的參數設定,而這個屬性是使用Gmail寄信最重要的設定之一,

NLog Fourm -  Unable to send email to receiver using mail target

所以在NLog 2.0就已經把 EnableSSL的參數給加入,所以我們可以使用NLog 所提供的 Using NLog with Gmail的Mail target設定,來達到使用Gmail寄發通知信的功能。

 

使用Gamil發信的限制

Gmail 傳送限制

Google 應用服務 > 說明文章 > 電子郵件 > 限制與安全性 > 傳送限制

IT邦幫忙 - 你未必知的Gmail發信限制

所以這時候Log等級的使用上就有好處,再加上使用Buffering Wrapper target 的使用,就可以盡量避免掉這些問題。

 

NLog Documentation - BufferingWrapper target

「A target that buffers log events and sends them in batches to the wrapped target.

我們可以在BufferingWrapper Target中去加入 bufferSize 的參數,給一個緩衝的數目,當Log訊息未達到 bufferSize  時,NLog會把Log訊息給Hold住,一直到Log訊息的數目到達 bufferSize 後才會把Log訊息給丟出去,所以可以使用這個特性加上Log等級,適當地透過Gmail寄出通知。

BufferingWrapper Target 參數「bufferSize」的預設值為100。

 

例如:

當Log等級為「Fatal」時,因為此通知屬於比較危急,所以就不用去加BufferingWrapper target,有Fatal Log出現時就立即寄發通知。

當Log等級為「Error」時,此為程式中有產生的錯誤,可以不用加上BufferingWrapper,或是說加上BufferingWrapper並且設定 bufferSize為5,當Error Log數目到達五個時才寄出通知郵件。

當Log等極為「Warm」時,多為程式中的警告,不致於影響系統流程的運作也不會影響資料的正確性,可以將 bufferSize 設為大一點的數目,例如50或是100。

而其他等級的Log訊息就以此類推,而等級Trace, Debug, Info 的訊息就完全不用考慮寄發通知。

 

以下是我為了做個範例,所以將原本是Fatal等級所使用的Mail Target 做了修改,加上了 BufferingWrapper Target:

image

當Fatal Log數目達到2個的時候,就會透過Gmail寄出通知郵件,而兩個Fatal Log的內容都將會在同一封信件當中,

image

透過加入BufferingWrapper Target以及Log等級的分別,減少透過Gmail寄發Email的數量,以閃避Gmail發信的限制,此外透過這些設定也可以不必一天到晚都在收這些NLog的通知訊息,讓真正需要立即處理的訊息可以被突顯出來。

 

參考連結:

NLog Documentation - Mail target

NLog Documentation - Using NLog with GMail

NLog Documentation – Taget – Wrapper Targets

NLog Documentation - BufferingWrapper target

Gmail 傳送限制

Google 應用服務 > 說明文章 > 電子郵件 > 限制與安全性 > 傳送限制

IT邦幫忙 - 你未必知的Gmail發信限制

 

以上

4 則留言:

  1. 請問一下.........我照著文章去做,甚至是看過您在tw.mvc的影片示範,但我這邊還是不能寄出EMAIL,我截了一些圖片給您看。
    我這邊的環境是WEB API2.1,然後在本機測試....
    http://i.imgur.com/UscfAAs.png
    http://i.imgur.com/P4QtWkd.png
    http://i.imgur.com/OShF8Sa.png
    http://i.imgur.com/hsWvAFG.png
    大致上都跟您的CODE差不多,不過就是寄不出去,想說是不是新版有變動了....

    回覆刪除
    回覆
    1. 因為同樣的設定我無論是放在 Server 或是 Local 的開發環境都可以執行,這個部份並沒有因為版本的更新而有所變動,
      所以你可以另外寫個小程式,直接在程式裡寫個簡單的寄信功能,然後使用相同的 SMTP Server 帳號密碼,
      並且寄信者與收件者也使用一樣的設定,看看是不是能夠寄送與收到,
      再來就是去檢查寄信的 Email 寄信備份裡有無資料,然後收信的 Email 也要檢查一下是不是被移到垃圾信件裡。
      .
      除了這些還有個可能就是網路環境是否有被擋住,
      再來就是換個信箱,尤其是收件的信箱(用 yahoo 信箱... 這應該很多信會收不到,所以範例裡我才會用 pchome 的信箱)
      先就以上的內容做嘗試與檢查。

      刪除
    2. 感謝您的回答,不過我在GMAIL的寄信備份和YAHOO的垃圾信箱都有檢查,兩邊都沒有看到所以我才會打擾您,這樣子看來可能我只能開個新的專案來試試看,還是感謝您熱心的回應^_^

      刪除
    3. Hello, 你在開發環境下可以改用 demo 在這一篇文章「http://demo.tc/Post/793」裡所介紹的「smtp4dev」,用來觀察寄發與接收是否正常,這樣會比較快直接找出原因。

      刪除

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。