搶先一步
VMware 提供培訓和認證,以加速您的進度。
了解更多日誌記錄是應用程式故障排除中長期建立的一部分,也是可觀測性的三大支柱之一,與指標和追蹤並列。沒有人喜歡在生產環境中盲目飛行,當事件發生時,開發人員很高興擁有日誌檔案。日誌通常以人類可讀的格式寫出。
結構化日誌是一種技術,其中日誌輸出以定義明確的、通常是機器可讀的格式寫入。 這種格式可以饋送到日誌管理系統,並實現強大的搜索和分析功能。結構化日誌最常用的格式之一是 JSON。
透過 Spring Boot 3.4,結構化日誌已開箱即用。它支援 Elastic Common Schema (ECS) 和 Logstash 格式,但也可以使用您自己的格式來擴展它。
讓我們直接跳進去看看它是如何運作的!
在 start.spring.io 上建立一個新專案。您不需要添加任何依賴項,但請務必至少選擇 Spring Boot 3.4.0-M2。
要在控制台上啟用結構化日誌,請將此添加到您的 application.properties
logging.structured.format.console=ecs
這將指示 Spring Boot 以 Elastic Common Schema (ECS) 格式記錄。
現在啟動應用程式,您會看到日誌以 JSON 格式格式化
{"@timestamp":"2024-07-30T08:41:10.561295200Z","log.level":"INFO","process.pid":67455,"process.thread.name":"main","service.name":"structured-logging-demo","log.logger":"com.example.structured_logging_demo.StructuredLoggingDemoApplication","message":"Started StructuredLoggingDemoApplication in 0.329 seconds (process running for 0.486)","ecs.version":"8.11"}
很酷吧?現在讓我們深入探討更進階的主題。
您也可以啟用將結構化日誌記錄到檔案。例如,這可用於在控制台上列印人類可讀的日誌,並將結構化日誌寫入檔案以供機器擷取。
要啟用該功能,請將此添加到您的 application.properties
並確保刪除 logging.structured.format.console=ecs
設定
logging.structured.format.file=ecs
logging.file.name=log.json
現在啟動您的應用程式,您會看到控制台上有人類可讀的日誌,並且檔案 log.json
包含機器可讀的 JSON 內容。
結構化日誌的一個強大功能是開發人員可以以結構化的方式將資訊添加到日誌事件中。例如,您可以將使用者 ID 新增至每個日誌事件,然後稍後篩選該 ID 以查看該特定使用者所執行的操作。
Elastic Common Schema 和 Logstash 都包含 Mapped Diagnostic Context 的內容在 JSON 中。為了看到它的實際效果,讓我們建立自己的日誌訊息
@Component
class MyLogger implements CommandLineRunner {
private static final Logger LOGGER = LoggerFactory.getLogger(MyLogger.class);
@Override
public void run(String... args) {
MDC.put("userId", "1");
LOGGER.info("Hello structured logging!");
MDC.remove("userId");
}
}
在記錄日誌訊息之前,此程式碼還會在 MDC 中設定使用者 ID。Spring Boot 會自動將使用者 ID 包含在 JSON 中
{ ... ,"message":"Hello structured logging!","userId":"1" ... }
您也可以使用 fluent logging API 來新增其他欄位,而無需依賴 MDC
@Component
class MyLogger implements CommandLineRunner {
private static final Logger LOGGER = LoggerFactory.getLogger(MyLogger.class);
@Override
public void run(String... args) {
LOGGER.atInfo().setMessage("Hello structured logging!").addKeyValue("userId", "1").log();
}
}
Elastic Common Schema 定義了許多欄位名稱,Spring Boot 內建支援服務名稱、服務版本、服務環境和節點名稱。要設定這些欄位的值,您可以在 application.properties
中使用以下內容
logging.structured.ecs.service.name=MyService
logging.structured.ecs.service.version=1
logging.structured.ecs.service.environment=Production
logging.structured.ecs.service.node-name=Primary
查看 JSON 輸出時,現在有 service.name
、service.version
、service.environment
和 service.node.name
的欄位。有了這些,您現在可以在您的日誌記錄系統上按節點名稱、服務版本等進行篩選。
如上所述,Spring Boot 開箱即用地支援 Elastic Common Schema 和 Logstash 格式。要新增您自己的格式,您必須執行以下步驟
StructuredLogFormatter
介面的自訂實作application.properties
中參考您的自訂實作首先,讓我們建立我們自己的自訂實作
class MyStructuredLoggingFormatter implements StructuredLogFormatter<ILoggingEvent> {
@Override
public String format(ILoggingEvent event) {
return "time=" + event.getTimeStamp() + " level=" + event.getLevel() + " message=" + event.getMessage() + "\n";
}
}
如您所見,結構化日誌支援不限於 JSON,您可以傳回您想要的任何 String
。在此範例中,我們選擇使用 key=value
配對。
我們現在需要讓 Spring Boot 知道我們的自訂實作。為此,請將其新增至 application.properties
logging.structured.format.console=com.example.structured_logging_demo.MyStructuredLoggingFormatter
現在可以啟動應用程式並驚嘆於日誌輸出了!
time=1722330118045 level=INFO message=Hello structured logging!
哇,看看那個!多麼美麗的日誌輸出!
如果您想要編寫 JSON,Spring Boot 3.4 中有一個方便的新 JsonWriter
,您可以使用
class MyStructuredLoggingFormatter implements StructuredLogFormatter<ILoggingEvent> {
private final JsonWriter<ILoggingEvent> writer = JsonWriter.<ILoggingEvent>of((members) -> {
members.add("time", (event) -> event.getInstant());
members.add("level", (event) -> event.getLevel());
members.add("thread", (event) -> event.getThreadName());
members.add("message", (event) -> event.getFormattedMessage());
members.add("application").usingMembers((application) -> {
application.add("name", "StructuredLoggingDemo");
application.add("version", "1.0.0-SNAPSHOT");
});
members.add("node").usingMembers((node) -> {
node.add("hostname", "node-1");
node.add("ip", "10.0.0.7");
});
}).withNewLineAtEnd();
@Override
public String format(ILoggingEvent event) {
return this.writer.writeToString(event);
}
}
當然,您也可以使用任何其他 JSON 函式庫(例如 Jackson)來建立 JSON,您不必使用 JsonWriter
。
產生的日誌訊息看起來像這樣
{"time":"2024-07-30T09:14:49.377308361Z","level":"INFO","thread":"main","message":"Hello structured logging!","application":{"name":"StructuredLoggingDemo","version":"1.0.0-SNAPSHOT"},"node":{"hostname":"node-1","ip":"10.0.0.7"}}
我們希望您喜歡 Spring Boot 3.4 中的這個新功能! 文件 也已更新以支援結構化日誌。
請告訴我們您的想法,如果您發現任何問題,我們的 issue tracker 隨時開放!