Nlog 無法正確寫出 Log

前些日子測試時發現以 debug mode 環境建置後發佈到 dev 環境時,一切都正常無誤,然而要發佈至 prd 環境時,卻發現 log 不會照著 nlog.config 裡的 rules 所設定準則去記 log

確認寫入權限

當下先檢查了寫入的目錄是不是有權限的問題,然而該設定的權限都有設定了

確認 NLog.config 設定 ( NLog 基本介紹與偵錯 )

把 Nlog internalLogLevel 設為 trace, 並把 throwExceptions 設成 true 看看是不是寫入資料有問題,然而也沒看到有什麼問題 

於是回頭檢查了一下 Nlog.config 是否有什麼特別的地方,在 rules 中我是以 logger filter 的方式去決定要寫到哪個 target 

  <targets>
    <target name="InOutLog" xsi:type="File"
            fileName="${basedir}/InOut/log.txt"
            layout="${longdate} | ${level:uppercase=true} | ${logger:shortName=true} | ${message} ${newline}" encoding="utf-8" keepFileOpen="false" />
  </targets>
  
  <rules>
    <logger name="ApiSite.Handler.*" minlevel="Info" writeTo="InOutLog"  />
  </rules>

 

修改 rules

  在 prd 環境中把 rules 修改為任何 logger 都要寫入,結果就成功了!?

  <rules>
    <logger name="*" minlevel="Info" writeTo="InOutLog"  />
  </rules>

所以很明顯就是 logger filter 的問題了,在 debug 與 release mode 所產生的 logger 可能是不同的?

於是我把 dev 的 rules 改成跟 prd 一樣,結果發現 logger 果然是不一樣的!!!

有可能是因為 prd 環境所導致的嗎?

為了澄清 prd 環境並不影響,所以我把 dev 環境的直接佈到 prd 環境中,果然就正常運作了

所以問題並不在於 prd server 上

為何導致 logger 不同?

仔細檢視了一下 Jenkins 發佈的 profile,dev 是用 debug config 去發佈, prd 是用 release 去發佈

唯一的線索就是 debug mode 跟 release mode 輸出不同!!!

Release mode 的不同

release mode 會做一些優化的編譯,但這也許是導致 Nlog 執行結果不同的原因

於專案按右鍵 => properties => build 中分別檢視 debug/release


果然發現在 Define DEBUG constant 與 optimize code 中有所不同

ApiSite.Handler
    public class WebApiMessageLogHandler : DelegatingHandler

namespace ApiSite
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(HttpConfiguration config)
        {
            config.MessageHandlers.Add(new WebApiMessageLogHandler());            
        }
    }
}

在 debug 中記到的是完整的 ApiSite.Handler.WebApiMessageLogHandler

然而在 release 中記到的是上層 caller 的資料 ApiSite.FilterConfig

推論也許跟 optimize code 是有關的

新增一組 config 吧

在 VS2019 中 Build => Configuration Manager 新增一組 config 給 prd 使用,並從 debug 複製出來

接著在發佈的部份改為由 prd 的設定檔去發佈,這樣就能解決掉 logger debug/release 不一致的問題了

如果 applicationSetting 或是 connectionString 也有切 config 的話,記得要再重新產生新的 config (右鍵Add config Transforms)

會自動產出 connectionString.prd.config 

其他可能的解決方案

另一種比較麻煩的解決方案會是根據不同的 debug/release 去設定 nlog.config 的檔案

像是 web.debug.config 與 web.release.config 的方式去決定要寫到哪個

並客製化 nlog.release.config 裡的 target 與 rules 的規則

然而這樣 debug 跟 release mode 的 nlog.config 就會不同,反而導致追查上的困難,一但增加了新的 rules 就得再去同步另一端的 config rules