SpringBoot使用Logbook記錄HTTP請求響應日誌

寫在前面:2020年面試必備的Java後端進階面試題總結了一份複習指南在Github上,內容詳細,圖文並茂,有需要學習的朋友可以Star一下!
GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/master

Spring Boot的httptrace端口能夠記錄每次訪問的請求和響應信息,但是不能記錄body,這樣在出問題時就不方便排查,而且httptrace不方便在原有的基礎上進行擴展,所以只能尋求其他方式進行記錄。

Logbook是一個可擴展的Java庫,可以爲不同的客戶端和服務端技術提供完整的請求和響應日誌記錄。它能夠滿足一些特殊的需求:

  • 允許web應用記錄程序接收或發送的所有HTTP通信
  • 易於保留和進行分析

Logbook在大部分情況下是開箱即用的,即使對於一些不常用的技術或者應用,實現它們也非常簡單。

特性
日誌記錄:HTTP請求和響應,包含body;未授權的請求會記錄部分日誌(不包含body)
自定義:能夠自定義記錄格式、記錄方式以及請求記錄的條件
支持框架:Servlet容器,Apache’s HTTP client,Square’s OkHttp等
混淆敏感數據
Spring Boot自動配置
合理的默認值
快速開始
Logbook爲Spring Boot用戶提供了很方便的自動配置功能,即我們所熟悉的 starter 。它使用了合理的默認值自動配置了以下功能:

Servlet filter
適用於未授權請求的Servlet filter(如果檢測到項目中使用Spring Security)
Header過濾器、Parameter過濾器、Body過濾器
HTTP格式化器、JSON格式化器
日誌寫入方式
引入 starter 模塊:

默認配置下,輸出的日誌爲JSON格式:

Request
Response
配置
下面的表格展示了可配置的選項:
在這裏插入圖片描述

配置示例
詳細用法
所有的功能集成都需要一個 Logbook 實例來完成,它保存了所有的配置並將所有需要的組件連接在一起。你可以使用所有的默認值創建一個實例:

或者使用 LogbookBuilder 創建一個自定義的版本:

在使用 starter 時,我們只需要自定義相應的 Bean 即可。

策略
Logbook使用一個非常硬性的策略來執行請求/響應日誌記錄:

請求/響應分開記錄
請求/響應儘快記錄
請求/響應一起記錄或不記錄
從2.0版本開始,Logbook引入了一個新的策略模式爲核心,它內置了部分策略:

BodyOnlyIfStatusAtLeastStrategy
StatusAtLeastStrategy
WithoutBodyStrategy
階段
Logbook工作在幾個不同的階段:

條件
過濾
格式化
記錄
每個階段都由一個或多個可以自定義的接口完成。每個階段都有一個合理的默認值。

條件
記錄HTTP消息並且包含其body的代價是非常大的,所以禁用某些請求的日誌記錄非常有意義。一個常見的情景就是忽略一些不必要的請求,比如Spring Boot的Actuator端點。

定義一個條件非常簡單,只需要編寫一個 Predicate 來決定請求是否需要記錄。當然,你也可以組合預定義的 Predicate :

對與路徑的包含和排除也可以通過設置 logbook.include 和 logbook.exclude 屬性實現。

過濾
過濾的目的是防止記錄HTTP請求和響應的某些敏感數據。這通常包括Authorization請求頭,但也可以用於某些明文查詢或表單參數,例如access_token和password。

Logbook支持不同類型的過濾器:

SpringBoot使用Logbook記錄HTTP請求響應日誌
QueryFilter , PathFilter , HeaderFilter 和 BodyFilter 能夠滿足絕大多數情況下的需求,對於更復雜的需求,可以使用 RequestFilter 和 ResponseFilter 。

關聯
Logbook使用一個id來關聯請求和響應,因爲請求和響應通常位於日誌文件中的不同位置。

在Spring Cloud應用中一般會集成Zipkin進行鏈路追蹤,此時可以使用TraceId來關聯請求和響應日誌記錄。

如果默認實現不滿足你的需求,你可以提供一個自定義的實現:

格式化
格式化定義瞭如何把請求和響應轉換爲字符串的方式。格式化不會指定請求和響應的記錄位置,這是由writer來完成的。

Writer
Writer定義了格式化後的請求和響應寫入的位置。Logbook內置了三種實現:Logger,Stream和Chunking。

Logger
默認情況下,請求和響應使用了slf4j來進行日誌記錄,日誌的級別爲 trace 。你也可以自定義:

Stream
另一種實現方式是記錄請求和響應到 PrintStream ,例如 System.out 或 System.err 。在生產環境中這是一個糟糕的選擇,但有時對於短暫的本地開發和調試很有用。

Chunking
ChunkingSink 會把長的消息分割成較小的塊,並且會委託給另一個sink將它們寫入,只需要設置 logbook.write.chunk-size 屬性即可。

Sink
HttpLogFormatter 和 HttpLogWriter 的組合能夠適用於大部分場合,但是也有一些侷限性。實現 Sink 接口可以實現更復雜的需求,例如把請求和響應持久化到數據庫。

你可以使用 CompositeSink 將多個Sink合併爲一個。

Servlet
在Servlet環境中,Logbook是通過 LogbookFilter 來實現的。默認情況下,對於
application/x-www-form-urlencoded 請求會同等對待,即你會在日誌中看到請求body。這種方法的缺點是下游代碼將無法使用任何
HttpServletRequest.getParameter*(…) 方法。

從Logbook 1.5.0開始,可以使用
logbook.servlet.form-request 系統屬性(System Property)指定三種策略之一,這些策略定義Logbook如何處理這種情況:

在這裏插入圖片描述
其他框架支持
Logbook默認還提供了對HTTP Client、JAX-RS、Netty、OkHttp v2.x、OkHttp v3.x的支持,具體使用方法可以參考官方文檔。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章