領先一步
VMware 提供培訓和認證,助您加速進步。
瞭解更多Spring可觀測性團隊在為Spring應用程式新增可觀測性支援方面已經工作了一段時間,我們很高興地通知您,此功能將隨Spring Framework 6和Spring Boot 3一起正式釋出!
什麼是可觀測性?在我們看來,它是“透過檢查系統的輸出,您能夠多好地理解系統內部”。我們相信,指標、日誌和分散式跟蹤之間的相互關聯,使您能夠對系統狀態進行推理,從而除錯應用程式中的異常和延遲。您可以在本期與 Jonatan Ivanov 的 Enlightning 節目中觀看更多關於我們對可觀測性的看法。
即將釋出的 Spring Boot 3.0.0-RC1 版本將包含許多自動配置,用於改進 Micrometer 的指標和 Micrometer Tracing(以前是 Spring Cloud Sleuth)的新分散式跟蹤支援。最顯著的變化是它將包含對日誌關聯的內建支援,W3C 上下文傳播將成為預設傳播型別,並且我們將支援自動傳播元資料,供跟蹤基礎設施(稱為“遠端行李”)使用,以幫助標記觀測結果。
在今年,我們對 Micrometer API 進行了很多更改。最重要的變化是,我們引入了一個新的 API:Observation API。
其創立的理念是,我們希望使用者使用單個 API 對其程式碼進行一次檢測,並從中獲得多重好處(例如,指標、跟蹤、日誌記錄)。
這篇部落格文章詳細介紹了您需要了解的有關該 API 的資訊以及如何使用它來為您的應用程式提供更多洞察。
要進行任何觀測,您需要透過 ObservationRegistry 註冊 ObservationHandler 物件。ObservationHandler 只對 Observation.Context 的受支援實現做出反應,並且可以透過對觀測的生命週期事件(例如)做出反應來建立計時器、跨度和日誌:
start - 觀測已啟動。在呼叫 Observation#start() 方法時發生。
stop - 觀測已停止。在呼叫 Observation#stop() 方法時發生。
error - 觀測時發生錯誤。在呼叫 Observation#error(exception) 方法時發生。
event - 觀測時發生事件。在呼叫 Observation#event(event) 方法時發生。
scope started - 觀測開啟一個範圍。範圍在不再使用時必須關閉。處理程式可以在啟動時建立執行緒區域性變數,這些變數在範圍關閉時被清除。在呼叫 Observation#openScope() 方法時發生。
scope stopped - 觀測停止一個範圍。在呼叫 Observation.Scope#close() 方法時發生。
每當呼叫這些方法中的任何一個時,都會呼叫一個 ObservationHandler 方法(例如 onStart(T extends Observation.Context ctx)、onStop(T extends Observation.Context ctx) 等)。為了在處理程式方法之間傳遞狀態,您可以使用 Observation.Context。
觀測狀態圖如下所示
Observation Observation
Context Context
Created ----------> Started ----------> Stopped
觀測範圍狀態圖如下所示
Observation
Context
Scope Started ----------> Scope Closed
為了能夠除錯生產問題,觀測需要額外的元資料,例如鍵值對(也稱為標籤)。然後,您可以使用這些標籤查詢您的指標或分散式跟蹤後端,以查詢所需資料。標籤可以是高基數或低基數。
這是 Micrometer Observation API 的一個示例。
// Create an ObservationRegistry
ObservationRegistry registry = ObservationRegistry.create();
// Register an ObservationHandler
registry.observationConfig().observationHandler(new MyHandler());
// Create an Observation and observe your code!
Observation.createNotStarted("user.name", registry)
.contextualName("getting-user-name")
.lowCardinalityKeyValue("userType", "userType1") // let's assume that you can have 3 user types
.highCardinalityKeyValue("userId", "1234") // let's assume that this is an arbitrary number
.observe(() -> log.info("Hello")); // this is a shortcut for starting an observation, opening a scope, running user's code, closing the scope and stopping the observation
重要
高基數意味著一個對將具有無限數量的可能值。HTTP URL 是這種鍵值的一個很好的例子(例如,/user/user1234、/user/user2345 等)。低基數意味著一個鍵值將具有有限數量的可能值。模板化HTTP URL(例如 /user/{userId})是這種鍵值的一個很好的例子。
為了將觀測生命週期操作與觀測配置(例如名稱以及高基數和低基數標籤)分開,您可以使用 ObservationConvention,它提供了一種覆蓋預設命名約定的簡便方法。
最簡單的入門方法是使用 https://start.spring.io 建立一個新專案。請務必選擇 Spring Boot 3.0.0-SNAPSHOT(釋出 RC1 後您可以切換到 RC1)以及您喜歡的構建工具。
我們將構建一個 Spring WebMvc 伺服器應用程式和一個使用 RestTemplate 呼叫伺服器的客戶端。我們從伺服器端開始。
由於我們要啟動一個 HTTP 伺服器,因此我們必須選擇 org.springframework.boot:spring-boot-starter-web 依賴項。
要使用 @Observed 切面建立觀測,我們需要新增 org.springframework.boot:spring-boot-starter-aop 依賴項。
要為您的應用程式新增觀測功能,請選擇 spring-boot-starter-actuator(將 Micrometer 新增到類路徑)。
現在是時候新增與可觀測性相關的功能了!
指標
io.micrometer:micrometer-registry-prometheus 依賴項。跟蹤
對於使用 Micrometer Tracing 的跟蹤上下文傳播,我們需要選擇一個tracer橋(tracer是用於處理跨度生命週期的庫)。我們透過新增 io.micrometer:micrometer-tracing-bridge-brave 來選擇 Zipkin Brave。
為了延遲視覺化,我們需要將完成的跨度以某種格式傳送到伺服器。在我們的例子中,我們生成一個 Zipkin 相容的跨度。為了實現這一點,我們需要新增 io.zipkin.reporter2:zipkin-reporter-brave 依賴項。
日誌
com.github.loki4j:loki-logback-appender 依賴項來實現這一點(請檢視 此連結 獲取最新發布版本)。重要
如果您是跟蹤新手,我們需要快速定義幾個基本術語。您可以將任何操作包裝在 span 中。它具有唯一的 span id 幷包含時間資訊和一些附加元資料(鍵值對)。由於您可以從跨度生成子跨度,因此整個跨度樹形成一個共享相同 trace id(即關聯識別符號)的 trace。
現在我們需要新增一些配置。我們設定 actuator 和 metrics 以釋出百分位數直方圖,並重新定義日誌模式以包含跟蹤和跨度識別符號。我們將取樣機率設定為 1.0 以將所有跟蹤傳送到延遲分析工具。
/src/main/resources/application.properties
server.port=7654
spring.application.name=server
# All traces should be sent to latency analysis tool
management.tracing.sampling.probability=1.0
management.endpoints.web.exposure.include=prometheus
# For Exemplars to work we need histogram buckets
management.metrics.distribution.percentiles-histogram.http.server.requests=true
# traceID and spanId are predefined MDC keys - we want the logs to include them
logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]
由於我們正在本地執行帶有 Loki 和 Tempo 的 Grafana 棧,我們將 loki-logback-appender 配置為將日誌傳送到本地 Loki 例項。
/src/main/resources/logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<springProperty scope="context" name="appName" source="spring.application.name"/>
<appender name="LOKI" class="com.github.loki4j.logback.Loki4jAppender">
<http>
<url>https://:3100/loki/api/v1/push</url>
</http>
<format>
<label>
<pattern>app=${appName},host=${HOSTNAME},traceID=%X{traceId:-NONE},level=%level</pattern>
</label>
<message>
<pattern>${FILE_LOG_PATTERN}</pattern>
</message>
<sortByTime>true</sortByTime>
</format>
</appender>
<root level="INFO">
<appender-ref ref="LOKI"/>
</root>
</configuration>
是時候編寫一些伺服器端程式碼了!我們希望實現應用程式的全面可觀測性,包括指標、跟蹤和附加日誌記錄。
首先,我們編寫一個控制器,它將訊息記錄到控制檯並將工作委託給服務。
MyController.java
@RestController
class MyController {
private static final Logger log = LoggerFactory.getLogger(MyController.class);
private final MyUserService myUserService;
MyController(MyUserService myUserService) {
this.myUserService = myUserService;
}
@GetMapping("/user/{userId}")
String userName(@PathVariable("userId") String userId) {
log.info("Got a request");
return myUserService.userName(userId);
}
}
我們希望對 MyUserService#userName 方法進行詳細的觀測。由於添加了 AOP 支援,我們可以使用 @Observed 註解。為此,我們可以註冊一個 ObservedAspect bean。
MyConfiguration.java
@Configuration(proxyBeanMethods = false)
class MyConfiguration {
// To have the @Observed support we need to register this aspect
@Bean
ObservedAspect observedAspect(ObservationRegistry observationRegistry) {
return new ObservedAspect(observationRegistry);
}
}
MyUserService.java
@Service
class MyUserService {
private static final Logger log = LoggerFactory.getLogger(MyUserService.class);
private final Random random = new Random();
// Example of using an annotation to observe methods
// <user.name> will be used as a metric name
// <getting-user-name> will be used as a span name
// <userType=userType2> will be set as a tag for both metric & span
@Observed(name = "user.name",
contextualName = "getting-user-name",
lowCardinalityKeyValues = {"userType", "userType2"})
String userName(String userId) {
log.info("Getting user name for user with id <{}>", userId);
try {
Thread.sleep(random.nextLong(200L)); // simulates latency
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "foo";
}
}
在類路徑上擁有指標和跟蹤的情況下,此註解會導致建立 timer、long task timer 和 span。計時器將被命名為 user.name,長任務計時器將被命名為 user.name.active,跨度將被命名為 getting-user-name。
日誌呢?我們不想在每次觀測發生時手動編寫日誌語句。我們可以做的是建立一個專用的處理程式,為每次觀測記錄一些文字。
MyHandler.java
// Example of plugging in a custom handler that in this case will print a statement before and after all observations take place
@Component
class MyHandler implements ObservationHandler<Observation.Context> {
private static final Logger log = LoggerFactory.getLogger(MyHandler.class);
@Override
public void onStart(Observation.Context context) {
log.info("Before running the observation for context [{}], userType [{}]", context.getName(), getUserTypeFromContext(context));
}
@Override
public void onStop(Observation.Context context) {
log.info("After running the observation for context [{}], userType [{}]", context.getName(), getUserTypeFromContext(context));
}
@Override
public boolean supportsContext(Observation.Context context) {
return true;
}
private String getUserTypeFromContext(Observation.Context context) {
return StreamSupport.stream(context.getLowCardinalityKeyValues().spliterator(), false)
.filter(keyValue -> "userType".equals(keyValue.getKey()))
.map(KeyValue::getValue)
.findFirst()
.orElse("UNKNOWN");
}
}
就是這樣!是時候進行客戶端了。
和以前一樣,我們新增 spring-boot-starter-web 和 spring-boot-starter-actuator 依賴項,以使 Web 伺服器執行並新增 Micrometer 支援。
是時候新增與可觀測性相關的功能了!
指標
io.micrometer:micrometer-registry-prometheus 依賴項。跟蹤
對於使用 Micrometer Tracing 的跟蹤上下文傳播,我們需要選擇一個tracer橋。我們透過新增 io.micrometer:micrometer-tracing-bridge-otel 來選擇 OpenTelemetry。
為了進行延遲視覺化,我們需要將完成的跨度以某種格式傳送到伺服器。在我們的例子中,我們生成一個 OpenZipkin 相容的跨度。為了實現這一點,我們需要新增 io.opentelemetry:opentelemetry-exporter-zipkin 依賴項。
日誌
com.github.loki4j:loki-logback-appender 依賴項(檢視 此連結 獲取最新發布版本)以將日誌傳送到 Loki。現在我們需要新增一些配置。我們添加了與伺服器端幾乎相同的配置。
/src/main/resources/application.properties
server.port=6543
spring.application.name=client
# All traces should be sent to latency analysis tool
management.tracing.sampling.probability=1.0
management.endpoints.web.exposure.include=prometheus
# traceID and spanId are predefined MDC keys - we want the logs to include them
logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]
Loki Appender 的配置看起來完全相同。
/src/main/resources/logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<springProperty scope="context" name="appName" source="spring.application.name"/>
<appender name="LOKI" class="com.github.loki4j.logback.Loki4jAppender">
<http>
<url>https://:3100/loki/api/v1/push</url>
</http>
<format>
<label>
<pattern>app=${appName},host=${HOSTNAME},traceID=%X{traceId:-NONE},level=%level</pattern>
</label>
<message>
<pattern>${FILE_LOG_PATTERN}</pattern>
</message>
<sortByTime>true</sortByTime>
</format>
</appender>
<root level="INFO">
<appender-ref ref="LOKI"/>
</root>
</configuration>
現在是時候編寫一些客戶端程式碼了!我們使用 RestTemplate 向伺服器端傳送請求,我們希望實現應用程式的全面可觀測性,包括指標和跟蹤。
首先,我們需要一個由 Spring Boot 自動檢測的 RestTemplate bean。請記住注入 RestTemplateBuilder 並從構建器構造一個 RestTemplate 例項。
MyConfiguration.java
@Configuration(proxyBeanMethods = false)
class MyConfiguration {
// IMPORTANT! To instrument RestTemplate you must inject the RestTemplateBuilder
@Bean
RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
現在我們可以編寫一個由 Observation API 包裝並向伺服器端傳送請求的 CommandLineRunner bean。API 的所有部分都在以下程式碼片段中更詳細地描述。
MyConfiguration.java
@Configuration(proxyBeanMethods = false)
class MyConfiguration {
@Bean
CommandLineRunner myCommandLineRunner(ObservationRegistry registry, RestTemplate restTemplate) {
Random highCardinalityValues = new Random(); // Simulates potentially large number of values
List<String> lowCardinalityValues = Arrays.asList("userType1", "userType2", "userType3"); // Simulates low number of values
return args -> {
String highCardinalityUserId = String.valueOf(highCardinalityValues.nextLong(100_000));
// Example of using the Observability API manually
// <my.observation> is a "technical" name that does not depend on the context. It will be used to name e.g. Metrics
Observation.createNotStarted("my.observation", registry)
// Low cardinality means that the number of potential values won't be big. Low cardinality entries will end up in e.g. Metrics
.lowCardinalityKeyValue("userType", randomUserTypePicker(lowCardinalityValues))
// High cardinality means that the number of potential values can be large. High cardinality entries will end up in e.g. Spans
.highCardinalityKeyValue("userId", highCardinalityUserId)
// <command-line-runner> is a "contextual" name that gives more details within the provided context. It will be used to name e.g. Spans
.contextualName("command-line-runner")
// The following lambda will be executed with an observation scope (e.g. all the MDC entries will be populated with tracing information). Also the observation will be started, stopped and if an error occurred it will be recorded on the observation
.observe(() -> {
log.info("Will send a request to the server"); // Since we're in an observation scope - this log line will contain tracing MDC entries ...
String response = restTemplate.getForObject("https://:7654/user/{userId}", String.class, highCardinalityUserId); // Boot's RestTemplate instrumentation creates a child span here
log.info("Got response [{}]", response); // ... so will this line
});
};
}
}
我們已在 此連結 下準備了整個可觀測性基礎設施的 Docker 設定。按照以下步驟執行基礎設施和兩個應用程式。
執行示例
啟動可觀測性堆疊(為了演示目的,您可以使用提供的 Grafana、Tempo 和 Loki 堆疊)並等待其啟動。
$ docker compose up
要訪問 Prometheus,請訪問 https://:9090/
要訪問 Grafana,請訪問 https://:3000/
執行伺服器端應用程式(這將阻塞您當前的終端視窗)。
$ ./mvnw spring-boot:run -pl :server
執行客戶端應用程式(這將阻塞您當前的終端視窗)
$ ./mvnw spring-boot:run -pl :client
您應該看到類似以下的日誌語句
2022-10-04T15:04:55.345+02:00 INFO [client,bbe3aea006077640b66d40f3e62f04b9,93b7a150b7e293ef] 92556 --- [ main] com.example.client.ClientApplication : Will send a request to the server
2022-10-04T15:04:55.385+02:00 INFO [client,bbe3aea006077640b66d40f3e62f04b9,93b7a150b7e293ef] 92556 --- [ main] com.example.client.ClientApplication : Got response [foo]
進入 Grafana,進入儀表板,點選 Logs, Traces, Metrics 儀表板。您可以在那裡選擇一個跟蹤 ID 值(例如,bbe3aea006077640b66d40f3e62f04b9)以查詢與該跟蹤 ID 對應的來自兩個應用程式的所有日誌和跟蹤。您應該會看到與同一跟蹤識別符號相關的日誌和跟蹤的以下關聯檢視,並且您將看到在相同時間範圍內發生的指標。這些指標與 HTTP 請求處理延遲相關。這些來自使用 Micrometer API 的自動 Spring Boot WebMvc 檢測。

請注意指標中的菱形。這些是 Exemplars。它們是“在給定時間間隔內進行的測量的特定追蹤代表”。如果您點選該形狀,您可以跳轉到追蹤 ID 檢視以檢視相應的追蹤。

要麼單擊追蹤 ID 以 Query it with Tempo,要麼轉到 Tempo 並自行選擇追蹤識別符號。您將看到以下螢幕。

每個條形代表一個 span。您可以檢視每個操作完成所需的時間。如果您單擊給定的跨度,您可以看到與該特定操作相關的標籤(鍵值元資料)和時間資訊。

這是 Loki 中關聯日誌檢視的樣子。

如果您想檢視 @Observed 註解方法的指標,您可以前往 Prometheus 檢視並找到 user_name 定時器。

如果您想檢視您手動建立的 Observation 的指標,請轉到 Prometheus 檢視並找到 my_observation 定時器。

為了更好地理解 Spring Boot 如何支援 Native,請閱讀 這篇優秀的部落格文章。我們重用這些知識來使用 Spring Native 執行之前建立的應用程式。
要構建應用程式,您需要在路徑中配置 GraalVM。如果您使用 SDKMan,請呼叫以下命令
sdk install java 22.3.r17.ea-nik
另請參閱 GraalVM 快速入門。
要使用 Maven 構建應用程式,您需要啟用 native 配置檔案
$ ./mvnw native:compile -Pnative
首先執行伺服器端應用程式
$ ./server/target/server
接下來,執行客戶端應用程式。
$ ./client/target/client
您應該會得到類似以下的輸出
客戶端日誌
2022-10-10T12:57:17.712+02:00 INFO \[client,,\] 82009 --- \[ main\] com.example.client.ClientApplication : Starting ClientApplication using Java 17.0.4 on marcin-precision5560 with PID 82009 (/home/marcin/repo/observability/blogs/bootRc1/client/target/client started by marcin in /home/marcin/repo/observability/blogs/bootRc1)
2022-10-10T12:57:17.712+02:00 INFO \[client,,\] 82009 --- \[ main\] com.example.client.ClientApplication : No active profile set, falling back to 1 default profile: "default"
2022-10-10T12:57:17.723+02:00 INFO \[client,,\] 82009 --- \[ main\] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 6543 (http)
2022-10-10T12:57:17.723+02:00 INFO \[client,,\] 82009 --- \[ main\] o.apache.catalina.core.StandardService : Starting service \[Tomcat\]
2022-10-10T12:57:17.723+02:00 INFO \[client,,\] 82009 --- \[ main\] o.apache.catalina.core.StandardEngine : Starting Servlet engine: \[Apache Tomcat/10.0.23\]
2022-10-10T12:57:17.727+02:00 INFO \[client,,\] 82009 --- \[ main\] o.a.c.c.C.\[Tomcat\].\[localhost\].\[/\] : Initializing Spring embedded WebApplicationContext
2022-10-10T12:57:17.727+02:00 INFO \[client,,\] 82009 --- \[ main\] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 15 ms
2022-10-10T12:57:17.731+02:00 WARN \[client,,\] 82009 --- \[ main\] i.m.c.i.binder.jvm.JvmGcMetrics : GC notifications will not be available because MemoryPoolMXBeans are not provided by the JVM
2022-10-10T12:57:17.781+02:00 INFO \[client,,\] 82009 --- \[ main\] o.s.b.a.e.web.EndpointLinksResolver : Exposing 15 endpoint(s) beneath base path '/actuator'
2022-10-10T12:57:17.783+02:00 INFO \[client,,\] 82009 --- \[ main\] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 6543 (http) with context path ''
2022-10-10T12:57:17.783+02:00 INFO \[client,,\] 82009 --- \[ main\] com.example.client.ClientApplication : Started ClientApplication in 0.077 seconds (process running for 0.079)
2022-10-10T12:57:17.784+02:00 INFO \[client,27c1113e4276c4173daec3675f536bf4,e0f2db8b983607d8\] 82009 --- \[ main\] com.example.client.ClientApplication : Will send a request to the server
2022-10-10T12:57:17.820+02:00 INFO \[client,27c1113e4276c4173daec3675f536bf4,e0f2db8b983607d8\] 82009 --- \[ main\] com.example.client.ClientApplication : Got response \[foo\]
2022-10-10T12:57:18.966+02:00 INFO \[client,,\] 82009 --- \[nio-6543-exec-1\] o.a.c.c.C.\[Tomcat\].\[localhost\].\[/\] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-10-10T12:57:18.966+02:00 INFO \[client,,\] 82009 --- \[nio-6543-exec-1\] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-10-10T12:57:18.966+02:00 INFO \[client,,\] 82009 --- \[nio-6543-exec-1\] o.s.web.servlet.DispatcherServlet : Completed initialization in 0 ms
伺服器端日誌
2022-10-10T12:57:07.200+02:00 INFO \[server,,\] 81760 --- \[ main\] com.example.server.ServerApplication : Starting ServerApplication using Java 17.0.4 on marcin-precision5560 with PID 81760 (/home/marcin/repo/observability/blogs/bootRc1/server/target/server started by marcin in /home/marcin/repo/observability/blogs/bootRc1)
2022-10-10T12:57:07.201+02:00 INFO \[server,,\] 81760 --- \[ main\] com.example.server.ServerApplication : No active profile set, falling back to 1 default profile: "default"
2022-10-10T12:57:07.213+02:00 INFO \[server,,\] 81760 --- \[ main\] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 7654 (http)
2022-10-10T12:57:07.213+02:00 INFO \[server,,\] 81760 --- \[ main\] o.apache.catalina.core.StandardService : Starting service \[Tomcat\]
2022-10-10T12:57:07.213+02:00 INFO \[server,,\] 81760 --- \[ main\] o.apache.catalina.core.StandardEngine : Starting Servlet engine: \[Apache Tomcat/10.0.23\]
2022-10-10T12:57:07.217+02:00 INFO \[server,,\] 81760 --- \[ main\] o.a.c.c.C.\[Tomcat\].\[localhost\].\[/\] : Initializing Spring embedded WebApplicationContext
2022-10-10T12:57:07.217+02:00 INFO \[server,,\] 81760 --- \[ main\] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 16 ms
2022-10-10T12:57:07.222+02:00 WARN \[server,,\] 81760 --- \[ main\] i.m.c.i.binder.jvm.JvmGcMetrics : GC notifications will not be available because MemoryPoolMXBeans are not provided by the JVM
2022-10-10T12:57:07.278+02:00 INFO \[server,,\] 81760 --- \[ main\] o.s.b.a.e.web.EndpointLinksResolver : Exposing 15 endpoint(s) beneath base path '/actuator'
2022-10-10T12:57:07.280+02:00 INFO \[server,,\] 81760 --- \[ main\] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 7654 (http) with context path ''
2022-10-10T12:57:07.281+02:00 INFO \[server,,\] 81760 --- \[ main\] com.example.server.ServerApplication : Started ServerApplication in 0.086 seconds (process running for 0.088)
2022-10-10T12:57:07.639+02:00 INFO \[server,,\] 81760 --- \[nio-7654-exec-1\] o.a.c.c.C.\[Tomcat\].\[localhost\].\[/\] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-10-10T12:57:07.639+02:00 INFO \[server,,\] 81760 --- \[nio-7654-exec-1\] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-10-10T12:57:07.640+02:00 INFO \[server,,\] 81760 --- \[nio-7654-exec-1\] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
2022-10-10T12:57:17.785+02:00 INFO \[server,,\] 81760 --- \[nio-7654-exec-8\] com.example.server.MyHandler : Before running the observation for context \[http.server.requests\]
2022-10-10T12:57:17.785+02:00 INFO \[server,27c1113e4276c4173daec3675f536bf4,9affba5698490e2d\] 81760 --- \[nio-7654-exec-8\] com.example.server.MyController : Got a request
2022-10-10T12:57:17.820+02:00 INFO \[server,,\] 81760 --- \[nio-7654-exec-8\] com.example.server.MyHandler : After running the observation for context \[http.server.requests\]
您可以檢查 Grafana 以獲取指標、跟蹤和日誌!
在客戶端,我們需要手動提供 reflect-config.js 配置。有關更多資訊,請參閱 此 PR。
在這篇部落格文章中,我們向您介紹了 Micrometer Observability API 的主要概念。我們還向您展示瞭如何使用 Observation API 和註解建立觀測。您還可以視覺化延遲、檢視關聯日誌並檢查來自 Spring Boot 應用程式的指標。
您還可以使用 Spring Native 的原生映象來觀測您的應用程式。
如果沒有整個 Spring 團隊、Tadaya Tsuyukubo、Johnny Lim 以及所有其他貢獻者和審閱者的廣泛支援,Micrometer Observability 的工作是不可能完成的。
基於社群反饋,我們將繼續改進我們的可觀測性故事。我們計劃在今年11月釋出GA版本。
這對我們來說是一個激動人心的時刻。我們再次感謝所有已經貢獻並提供反饋的人,我們期待更多的反饋!請檢視 Spring Boot 的最新快照!請檢視我們專案的文件:Micrometer 上下文傳播、Micrometer、Micrometer 觀測、Micrometer 跟蹤 和 Micrometer 文件生成器!點選這裡檢視本部落格文章使用的程式碼。