平常比較容易遇到的有幾種案例:
- 我想要 logback 輸出所有的 log,但特定某些 package 想要隱藏 DEBUG 和 TRACE
- 我想要 logback 只輸出 INFO 以上的 log,但特定某些 package 想要輸出所有 log
- 我想要 logback 只輸出 INFO 以上的 log,但特定某些 package 想要輸出所有 log,而且某個 package 的 INFO 以上 log 要輸出到別的 appender
之前開發時,大多用到的是第一種,但偶而想要第二和第三種時,花了不少時間才調整出來
最後發現一開始對設定的認知其實有點不太正確。
Logback 設定的 Logger
Logger 的設定可以參考官方的文件 [1]。
整個 Logger 的概念,應該要以樹狀結構去思考,其中樹狀結構的組成是 package。
例如我的程式碼中有 com.example 和 org.example 兩個 package
這意味著樹狀結構中,ROOT 有兩個子節點 com 和 org,然後 com 和 org 節點各自都有一個叫做 example 的子節點。
ROOT 是樹狀結構當中的根節點,在 <ROOT> 上做的設定,預設會套用到樹狀結構中的每個節點
但這並不表示 ROOT 的設定是所有東西的預設值(這是我自己原先觀念上的錯誤)。
例如下述的官方範例來說
<logger name="chapters.configuration" level="INFO" /> <!-- turn OFF all logging (children can override) --> <root level="OFF"> <appender-ref ref="STDOUT" /> </root>
如果 ROOT 設定當作是預設值,這個設定應該要認為除了 chapters.configuration 以外的所有 package 都不會輸出 log
但正確的解釋是,chapters.configuration 以及它的所有子節點,都是設為 INFO 等級,除此之外的所有 package 都是 OFF。
Logger name | Assigned Level | Effective Level |
root | OFF | OFF |
chapters.configuration | INFO | INFO |
chapters.configuration.MyApp3 | null | INFO |
chapters.configuration.Foo | null | INFO |
如官網的表格,表格的意思如下:
- root 在設定檔中被設定為 OFF,實際執行時輸出效果為 OFF
- chapters.configuration 在設定檔中被設定為 INFO,實際輸出效果為 INFO
- chapters.configuration.MyApp3 在設定檔中沒有被設定,實際輸出效果為 INFO(因為繼承了由上層節點 chapters.configuration 的設定)
- chapters.configuration.Foo 在設定檔中沒有被設定,實際輸出效果為 INFO(因為繼承了由上層節點 chapters.configuration 的設定)
隱藏特定 Package 的 log
其實這種案例已經在上面的範例中展示了 XD
<logger name="chapters.configuration" level="INFO" /> <root level="ALL"> <appender-ref ref="STDOUT" /> </root>
例如像上述這樣小做調整的結果,就是所有 LOG 都會輸出,只有 chapters.configuration 以及其下的 package 是只輸出 INFO 以上。
只有特定 Package 的 log 輸出全部;其他 Package 都輸出 INFO 以上
這個其實概念也跟上面一樣。
<logger name="chapters.configuration" level="ALL" /> <root level="INFO"> <appender-ref ref="STDOUT" /> </root>
特定 Package 的 INFO 以上 log 輸出到資料庫;我寫的程式的 log 全部輸出到 console;剩下的 log 只輸出 INFO 以上到 console
這個就是這次主要要紀錄的狀況,子標題有點長 XD
具體來說有像是以下的需求:
- com.example 以下的所有 log 都要輸出到 console
- com.example.aaa.bbb 的 log,INFO 以上的要輸出到資料庫,同時 com.example.aaa.bbb 所有的 log 都要輸出到 console
- 除了 com.example 以外的所有函式庫的 log,只輸出 INFO 以上
首先,我本來嘗試的作法是在 com.example.aaa.bbb 上設定 level = INFO
<logger name="com.example.aaa.bbb" level="INFO" additivity="true"> <appender-ref ref="MSSQL" /> </logger> <logger name="com.example" level="ALL" additivity="false"> <appender-ref ref="STDOUT" /> </logger> <root level="INFO"> <appender-ref ref="STDOUT" /> </root>
但結果是 com.example.aaa.bbb 的 DEBUG 和 TRACE 的 log 都沒有印在 console。
實際上這也是正常的,因為 com.example.aaa.bbb 設定為 level = INFO 的話
表示自它以下的 package,DEBUG 和 TRACE 都會被過濾掉。
因為實際上我希望 com.example 的所有 log 都要出現在 console
因此我並不能對 com.example 以下的任何 package 設定 level,而是應該把 level 的篩選設定在 appender 上。
也就是 logger 本身會輸出所有 log 到 appender,但是 appender 負責篩選 level。
最後,設定檔就寫成這樣:
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> ...... </appender> <appender name="MSSQL" class="ch.qos.logback.classic.db.DBAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> ...... </appender> <logger name="com.example.aaa.bbb" level="ALL" additivity="true"> <appender-ref ref="MSSQL" /> </logger> <logger name="com.example" level="ALL" additivity="false"> <appender-ref ref="STDOUT" /> </logger> <root level="INFO"> <appender-ref ref="STDOUT" /> </root>
Logger 的等級關係如下表
Logger name | Assigned Level | Effective Level |
root | INFO | INFO |
com.example | ALL | ALL |
com.example.aaa | null | ALL |
com.example.aaa.bbb | ALL | ALL |
沒有留言:
張貼留言