今天我們要探討一個常被忽視,但卻至關重要的話題:日誌記錄
我們將聚焦於 SLF4J 和 Logback 這對強大的組合,看看如何讓它們在我們的 Todo List API 中大顯身手
SLF4J 是一個抽象層(Facade Pattern),它提供了一個統一的接口,允許你在寫程式時使用統一的日誌 API
讓你的程式碼可以與各種日誌實現框架溝通,使用 SLF4J,你就不用擔心將來可能需要更換日誌框架的問題了。
Logback 則是實際執行日誌記錄的實現。它是 log4j 創始人設計的新一代日誌框架,擁有更高的性能和更豐富的功能
Logback 負責將日誌寫入檔案或輸出到控制台
Spring 框架本身使用 SLF4J 作為其日誌抽象層,當你在 Spring 項目中配置 Logback 時,它會作為 SLF4J 的底層實現
Spring Boot 3.3 已經使用 spring-boot-starter-logging
作為預設的日誌啟動器,其中已經包含了 SLF4J 和 Logback,所以不用再額外添加任何的依賴
+-------------------+
| Spring Framework |
+-------------------+
|
| 使用
v
+-------------------+
| SLF4J |
| (日誌抽象層) |
+-------------------+
|
| 實現
v
+-------------------+
| Logback |
| (具體日誌實現) |
+-------------------+
我們來修改 TodoController
@RestController
@RequestMapping("/api/todos")
public class TodoController {
private static final Logger logger = LoggerFactory.getLogger(TodoController.class);
@PostMapping
public ResponseEntity<ApiResponse<Todo>> createTodo(@RequestBody Todo todo) {
logger.info("create new todo: {}", todo);
long id = idCounter.incrementAndGet();
todo.setId(id);
todos.add(todo);
return ResponseEntity.ok(new ApiResponse<>(true, todo, null));
}
// 其他方法類似,可以參考 Github 上 repository 的 commit ...
}
然後,修改全局異常處理器:
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiResponse<Void>> handleException(Exception e) {
logger.error("Unhandled exception occurred", e);
String apiPath = apiPath();
ApiResponse.ErrorDetails error = new ApiResponse.ErrorDetails(
"https://example.com/errors/internal-error",
"Internal Server Error",
HttpStatus.INTERNAL_SERVER_ERROR,
e.getMessage(),
apiPath
);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ApiResponse<>(false, null, error));
}
// 其他方法類似,可以參考 Github 上 repository 的 commit ...
}
必須注意,匯入(import)時要選擇正確的套件(package),因為有相當多的選項
實際呼叫 API 進行測試,可以看到 log 有輸出到 console
現在,讓我們來配置 Logback,實現每天一個日誌文件,並在文件大小超過 5MB 時進行切分。在 src/main/resources 目錄下創建 logback-spring.xml
<configuration>
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/todo-api.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/todo-api-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>5MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="ROLLING_FILE" />
</root>
</configuration>
logs/todo-api.log
的檔案todo-api-2024-09-03.0.log
)todo-api-2024-09-03.1.log
)呼叫 API 測試一下,可以在資料夾內看到有產生了 log 檔案,而且相關的 log 有輸出到檔案裡面
Logback 的設定檔可以設定的參數非常多,可以參考官網的說明
另外,現在大多數應用程式可能都不會將日誌寫入自己的伺服器了,以 sentry 為例,可以參考官方文件
// 推薦
logger.debug("Processing request for user: {}", username);
// 不推薦
logger.debug("Processing request for user: " + username);
通過今天的文章,我們不僅掌握了如何使用 SLF4J 和 Logback 來改進 Todo List API,還學會了如何配置 Logback 來管理日誌文件
記住,良好的日誌記錄就像是給未來的自己或其他開發者留下的路標,能夠在錯綜複雜的程式碼中指明方向
同步刊登於 Blog 「Spring Boot API 開發:從 0 到 1」Day 14 日誌記錄
我的粉絲專頁
圖片來源:AI 產生