Observability Support
Micrometer 在应用程序中定义了一个 Observation concept that enables both Metrics and Traces。度量支持提供了一种创建计时器、测量器或计数器的方法,用于收集有关应用程序运行时行为的统计信息。度量可以帮助你跟踪错误率、使用模式、性能等。跟踪提供整个系统的一个整体视图,跨越应用程序边界;你可以深入研究特定的用户请求,并跟踪它们在各个应用程序中的整个完成情况。
Micrometer defines an Observation concept that enables both Metrics and Traces in applications. Metrics support offers a way to create timers, gauges, or counters for collecting statistics about the runtime behavior of your application. Metrics can help you to track error rates, usage patterns, performance, and more. Traces provide a holistic view of an entire system, crossing application boundaries; you can zoom in on particular user requests and follow their entire completion across applications.
如果配置了`ObservationRegistry`,Spring Framework 会对自己的代码库的各个部分进行检测以发布观测结果。你可以了解更多有关[在 Spring Boot 中配置可观测性基础设施](https://spring.io/docs/spring-boot/docs/current/reference/html/actuator.html#actuator.metrics)的信息。
Spring Framework instruments various parts of its own codebase to publish observations if an ObservationRegistry
is configured.
You can learn more about configuring the observability infrastructure in Spring Boot.
List of produced Observations
Spring Framework 检测各种功能以进行观测。如at the beginning of this section所述,观测可以根据配置生成计时器度量和/或跟踪。
Spring Framework instruments various features for observability. As outlined at the beginning of this section, observations can generate timer Metrics and/or Traces depending on the configuration.
Observation name | Description |
---|---|
Time spent for HTTP client exchanges |
|
Processing time for HTTP server exchanges at the Framework level |
|
Time spent sending a JMS message to a destination by a message producer. |
|
Processing time for a JMS message that was previously received by a message consumer. |
|
Processing time for an execution of a |
观察结果使用 Micrometer 的官方命名约定,但指标名称将自动转换 to the format preferred by the monitoring system backend(Prometheus、Atlas、Graphite、InfluxDB…)。 |
Observations are using Micrometer’s official naming convention, but Metrics names will be automatically converted to the format preferred by the monitoring system backend (Prometheus, Atlas, Graphite, InfluxDB…). |
Micrometer Observation concepts
如果您不熟悉 Micrometer 观察,以下是对您应该了解的概念的快速总结。
If you are not familiar with Micrometer Observation, here’s a quick summary of the concepts you should know about.
-
Observation
is the actual recording of something happening in your application. This is processed byObservationHandler
implementations to produce metrics or traces. -
Each observation has a corresponding
ObservationContext
implementation; this type holds all the relevant information for extracting metadata for it. In the case of an HTTP server observation, the context implementation could hold the HTTP request, the HTTP response, any exception thrown during processing, and so forth. -
Each
Observation
holdsKeyValues
metadata. In the case of an HTTP server observation, this could be the HTTP request method, the HTTP response status, and so forth. This metadata is contributed byObservationConvention
implementations which should declare the type ofObservationContext
they support. -
KeyValues
are said to be "low cardinality" if there is a low, bounded number of possible values for theKeyValue
tuple (HTTP method is a good example). Low cardinality values are contributed to metrics only. Conversely, "high cardinality" values are unbounded (for example, HTTP request URIs) and are only contributed to traces. -
An
ObservationDocumentation
documents all observations in a particular domain, listing the expected key names and their meaning.
Configuring Observations
全局配置选项在“ObservationRegistry#observationConfig()”级别可用。每个检测的组件将提供两个扩展点:
Global configuration options are available at the ObservationRegistry#observationConfig()
level.
Each instrumented component will provide two extension points:
-
setting the
ObservationRegistry
; if not set, observations will not be recorded and will be no-ops -
providing a custom
ObservationConvention
to change the default observation name and extractedKeyValues
Using custom Observation conventions
我们以 Spring MVC “http.server.requests”指标检测(使用“ServerHttpObservationFilter”)为例。此观察使用具有“ServerRequestObservationContext”的“ServerRequestObservationConvention”;自定义约定可以在 Servlet 过滤器上配置。如果您想自定义观察结果生成的元数据,您可以根据要求扩展“DefaultServerRequestObservationConvention”:
Let’s take the example of the Spring MVC "http.server.requests" metrics instrumentation with the ServerHttpObservationFilter
.
This observation uses a ServerRequestObservationConvention
with a ServerRequestObservationContext
; custom conventions can be configured on the Servlet filter.
If you would like to customize the metadata produced with the observation, you can extend the DefaultServerRequestObservationConvention
for your requirements:
import io.micrometer.common.KeyValue;
import io.micrometer.common.KeyValues;
import org.springframework.http.server.observation.DefaultServerRequestObservationConvention;
import org.springframework.http.server.observation.ServerRequestObservationContext;
public class ExtendedServerRequestObservationConvention extends DefaultServerRequestObservationConvention {
@Override
public KeyValues getLowCardinalityKeyValues(ServerRequestObservationContext context) {
// here, we just want to have an additional KeyValue to the observation, keeping the default values
return super.getLowCardinalityKeyValues(context).and(custom(context));
}
private KeyValue custom(ServerRequestObservationContext context) {
return KeyValue.of("custom.method", context.getCarrier().getMethod());
}
}
如果您希望完全控制,您可以实现您感兴趣的观察的整个约定合同:
If you want full control, you can implement the entire convention contract for the observation you’re interested in:
import io.micrometer.common.KeyValue;
import io.micrometer.common.KeyValues;
import org.springframework.http.server.observation.ServerHttpObservationDocumentation;
import org.springframework.http.server.observation.ServerRequestObservationContext;
import org.springframework.http.server.observation.ServerRequestObservationConvention;
public class CustomServerRequestObservationConvention implements ServerRequestObservationConvention {
@Override
public String getName() {
// will be used as the metric name
return "http.server.requests";
}
@Override
public String getContextualName(ServerRequestObservationContext context) {
// will be used for the trace name
return "http " + context.getCarrier().getMethod().toLowerCase();
}
@Override
public KeyValues getLowCardinalityKeyValues(ServerRequestObservationContext context) {
return KeyValues.of(method(context), status(context), exception(context));
}
@Override
public KeyValues getHighCardinalityKeyValues(ServerRequestObservationContext context) {
return KeyValues.of(httpUrl(context));
}
private KeyValue method(ServerRequestObservationContext context) {
// You should reuse as much as possible the corresponding ObservationDocumentation for key names
return KeyValue.of(ServerHttpObservationDocumentation.LowCardinalityKeyNames.METHOD, context.getCarrier().getMethod());
}
// status(), exception(), httpUrl()...
private KeyValue status(ServerRequestObservationContext context) {
return KeyValue.of(ServerHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, String.valueOf(context.getResponse().getStatus()));
}
private KeyValue exception(ServerRequestObservationContext context) {
String exception = (context.getError() != null ? context.getError().getClass().getSimpleName() : KeyValue.NONE_VALUE);
return KeyValue.of(ServerHttpObservationDocumentation.LowCardinalityKeyNames.EXCEPTION, exception);
}
private KeyValue httpUrl(ServerRequestObservationContext context) {
return KeyValue.of(ServerHttpObservationDocumentation.HighCardinalityKeyNames.HTTP_URL, context.getCarrier().getRequestURI());
}
}
您还可以使用自定义“ObservationFilter”来实现类似的目标——为观察添加或删除键值。过滤器不会替换默认约定,而是用作后期处理组件。
You can also achieve similar goals using a custom ObservationFilter
– adding or removing key values for an observation.
Filters do not replace the default convention and are used as a post-processing component.
import io.micrometer.common.KeyValue;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationFilter;
import org.springframework.http.server.observation.ServerRequestObservationContext;
public class ServerRequestObservationFilter implements ObservationFilter {
@Override
public Observation.Context map(Observation.Context context) {
if (context instanceof ServerRequestObservationContext serverContext) {
context.setName("custom.observation.name");
context.addLowCardinalityKeyValue(KeyValue.of("project", "spring"));
String customAttribute = (String) serverContext.getCarrier().getAttribute("customAttribute");
context.addLowCardinalityKeyValue(KeyValue.of("custom.attribute", customAttribute));
}
return context;
}
}
您可以在“ObservationRegistry”上配置“ObservationFilter”实例。
You can configure ObservationFilter
instances on the ObservationRegistry
.
@Scheduled tasks instrumentation
为 xref:integration/scheduling.adoc#scheduling-enable-annotation-support[each execution of an @Scheduled
任务创建了观察。应用程序需要在 ScheduledTaskRegistrar
上配置 ObservationRegistry
以启用观察记录。可以通过声明一个设置观察注册表的 SchedulingConfigurer
Bean 来完成此操作:
An Observation is created for each execution of an @Scheduled
task.
Applications need to configure the ObservationRegistry
on the ScheduledTaskRegistrar
to enable the recording of observations.
This can be done by declaring a SchedulingConfigurer
bean that sets the observation registry:
import io.micrometer.observation.ObservationRegistry;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
public class ObservationSchedulingConfigurer implements SchedulingConfigurer {
private final ObservationRegistry observationRegistry;
public ObservationSchedulingConfigurer(ObservationRegistry observationRegistry) {
this.observationRegistry = observationRegistry;
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setObservationRegistry(this.observationRegistry);
}
}
默认情况下,它使用由 ScheduledTaskObservationContext
支持的 org.springframework.scheduling.support.DefaultScheduledTaskObservationConvention
。你可以在 ObservationRegistry
上直接配置自定义实现。在执行计划方法时,当前观察结果会还原到 ThreadLocal
上下文或 Reactor 上下文(如果计划方法返回 Mono
或 Flux
类型)。
It is using the org.springframework.scheduling.support.DefaultScheduledTaskObservationConvention
by default, backed by the ScheduledTaskObservationContext
.
You can configure a custom implementation on the ObservationRegistry
directly.
During the execution of the scheduled method, the current observation is restored in the ThreadLocal
context or the Reactor context (if the scheduled method returns a Mono
or Flux
type).
默认情况下,将创建以下 KeyValues
:
By default, the following KeyValues
are created:
Name |
Description |
|
Name of Java |
|
Canonical name of the class of the bean instance that holds the scheduled method, or |
|
Class name of the exception thrown during the execution, or |
|
Duplicates the |
|
Outcome of the method execution. Can be |
JMS messaging instrumentation
如果 classpath 中存在 io.micrometer:micrometer-jakarta9
依赖项,Spring 框架会使用 Micrometer 提供的 Jakarta JMS 检测器。io.micrometer.jakarta9.instrument.jms.JmsInstrumentation
检测器检测 jakarta.jms.Session
并在相关观察结果中记录该检测器。
Spring Framework uses the Jakarta JMS instrumentation provided by Micrometer if the io.micrometer:micrometer-jakarta9
dependency is on the classpath.
The io.micrometer.jakarta9.instrument.jms.JmsInstrumentation
instruments jakarta.jms.Session
and records the relevant observations.
此检测器将创建 2 种类型的观察结果:
This instrumentation will create 2 types of observations:
-
"jms.message.publish"
when a JMS message is sent to the broker, typically withJmsTemplate
. -
"jms.message.process"
when a JMS message is processed by the application, typically with aMessageListener
or a@JmsListener
annotated method.
目前没有用于 |
currently there is no instrumentation for |
默认情况下,这两个观察结果共享同一组可能的 KeyValues
:
By default, both observations share the same set of possible KeyValues
:
Name |
Description |
|
Class name of the exception thrown during the messaging operation (or "none"). |
|
Duplicates the |
|
Whether the destination is a |
|
Name of JMS operation being performed (values: |
Name |
Description |
|
The correlation ID of the JMS message. |
|
The name of destination the current message was sent to. |
|
Value used by the messaging system as an identifier for the message. |
JMS message Publication instrumentation
当 JMS 消息发送到代理时,将记录 "jms.message.publish"
观察结果。它们会衡量发送消息所需的时间,并使用传出的 JMS 消息标头传播跟踪信息。
"jms.message.publish"
observations are recorded when a JMS message is sent to the broker.
They measure the time spent sending the message and propagate the tracing information with outgoing JMS message headers.
你需要在 JmsTemplate
上配置 ObservationRegistry
来启用观察结果:
You will need to configure the ObservationRegistry
on the JmsTemplate
to enable observations:
import io.micrometer.observation.ObservationRegistry;
import jakarta.jms.ConnectionFactory;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.jms.core.JmsTemplate;
public class JmsTemplatePublish {
private final JmsTemplate jmsTemplate;
private final JmsMessagingTemplate jmsMessagingTemplate;
public JmsTemplatePublish(ObservationRegistry observationRegistry, ConnectionFactory connectionFactory) {
this.jmsTemplate = new JmsTemplate(connectionFactory);
// configure the observation registry
this.jmsTemplate.setObservationRegistry(observationRegistry);
// For JmsMessagingTemplate, instantiate it with a JMS template that has a configured registry
this.jmsMessagingTemplate = new JmsMessagingTemplate(this.jmsTemplate);
}
public void sendMessages() {
this.jmsTemplate.convertAndSend("spring.observation.test", "test message");
}
}
默认情况下,它使用由 io.micrometer.jakarta9.instrument.jms.JmsPublishObservationContext
支持的 io.micrometer.jakarta9.instrument.jms.DefaultJmsPublishObservationConvention
。
It uses the io.micrometer.jakarta9.instrument.jms.DefaultJmsPublishObservationConvention
by default, backed by the io.micrometer.jakarta9.instrument.jms.JmsPublishObservationContext
.
JMS message Processing instrumentation
当应用程序处理 JMS 消息时,将记录 "jms.message.process"
观察结果。它们会衡量处理消息所需的时间,并使用传出的 JMS 消息标头传播跟踪上下文。
"jms.message.process"
observations are recorded when a JMS message is processed by the application.
They measure the time spent processing the message and propagate the tracing context with incoming JMS message headers.
大多数应用程序将使用 @JmsListener
annotated methods 机制来处理传入消息。你需要确保在专用 JmsListenerContainerFactory
上配置了 ObservationRegistry
:
Most applications will use the @JmsListener
annotated methods mechanism to process incoming messages.
You will need to ensure that the ObservationRegistry
is configured on the dedicated JmsListenerContainerFactory
:
import io.micrometer.observation.ObservationRegistry;
import jakarta.jms.ConnectionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
@Configuration
@EnableJms
public class JmsConfiguration {
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory, ObservationRegistry observationRegistry) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setObservationRegistry(observationRegistry);
return factory;
}
}
一个 default container factory is required to enable the annotation support, 但请注意,@JmsListener
注释可以引用特定目的的特定容器工厂 bean。在所有情况下,仅当在容器工厂上配置了观察注册中心时才记录观察结果。
A default container factory is required to enable the annotation support,
but note that @JmsListener
annotations can refer to specific container factory beans for specific purposes.
In all cases, Observations are only recorded if the observation registry is configured on the container factory.
当 MessageListener
处理消息时,会在 JmsTemplate
中记录类似的观察结果。此类侦听器是在会话回调中的 MessageConsumer
上设置的(请参见 JmsTemplate.execute(SessionCallback<T>)
)。
Similar observations are recorded with JmsTemplate
when messages are processed by a MessageListener
.
Such listeners are set on a MessageConsumer
within a session callback (see JmsTemplate.execute(SessionCallback<T>)
).
默认情况下,此观察结果使用由 io.micrometer.jakarta9.instrument.jms.JmsProcessObservationContext
支持的 io.micrometer.jakarta9.instrument.jms.DefaultJmsProcessObservationConvention
。
This observation uses the io.micrometer.jakarta9.instrument.jms.DefaultJmsProcessObservationConvention
by default, backed by the io.micrometer.jakarta9.instrument.jms.JmsProcessObservationContext
.
HTTP Server instrumentation
HTTP 服务器交换观察结果使用 Servlet 和 Reactive 应用程序的名称 "http.server.requests"
创建。
HTTP server exchange observations are created with the name "http.server.requests"
for Servlet and Reactive applications.
Servlet applications
应用程序需要在其应用程序中配置 org.springframework.web.filter.ServerHttpObservationFilter
Servlet 过滤器。默认情况下,它使用由 ServerRequestObservationContext
支持的 org.springframework.http.server.observation.DefaultServerRequestObservationConvention
。
Applications need to configure the org.springframework.web.filter.ServerHttpObservationFilter
Servlet filter in their application.
It uses the org.springframework.http.server.observation.DefaultServerRequestObservationConvention
by default, backed by the ServerRequestObservationContext
.
这只会将观测结果记录为错误,如果 web 框架没有处理`Exception`,并且已上升到 Servlet 过滤器。通常,Spring MVC 的`@ExceptionHandler`和ProblemDetail
support处理的所有异常都不会记录在观测结果中。你可以在请求处理过程中的任何时候自行设置`ObservationContext`上的错误字段:
This will only record an observation as an error if the Exception
has not been handled by the web framework and has bubbled up to the Servlet filter.
Typically, all exceptions handled by Spring MVC’s @ExceptionHandler
and ProblemDetail
support will not be recorded with the observation.
You can, at any point during request processing, set the error field on the ObservationContext
yourself:
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.filter.ServerHttpObservationFilter;
@Controller
public class UserController {
@ExceptionHandler(MissingUserException.class)
ResponseEntity<Void> handleMissingUser(HttpServletRequest request, MissingUserException exception) {
// We want to record this exception with the observation
ServerHttpObservationFilter.findObservationContext(request)
.ifPresent(context -> context.setError(exception));
return ResponseEntity.notFound().build();
}
static class MissingUserException extends RuntimeException {
}
}
由于会在 Servlet Filter 级别执行监测,观测范围仅涵盖此 Filter 之后指定的 Filter 以及请求处理。通常,Servlet 容器错误处理是在较低级别执行的,且不会有任何活动观测或范围。对于此用例,需要一个特定于容器的实现,例如 |
Because the instrumentation is done at the Servlet Filter level, the observation scope only covers the filters ordered after this one as well as the handling of the request.
Typically, Servlet container error handling is performed at a lower level and won’t have any active observation or span.
For this use case, a container-specific implementation is required, such as a |
默认情况下,将创建以下 KeyValues
:
By default, the following KeyValues
are created:
Name |
Description |
|
Class name of the exception thrown during the exchange, or |
|
Duplicates the |
|
Name of HTTP request method or |
|
Outcome of the HTTP server exchange. |
|
HTTP response raw status code, or |
|
URI pattern for the matching handler if available, falling back to |
Name |
Description |
|
HTTP request URI. |
Reactive applications
应用程序需要使用 MeterRegistry
配置 WebHttpHandlerBuilder
以启用服务器工具。这可以在 `WebHttpHandlerBuilder`上按如下方式完成:
Applications need to configure the WebHttpHandlerBuilder
with a MeterRegistry
to enable server instrumentation.
This can be done on the WebHttpHandlerBuilder
, as follows:
import io.micrometer.observation.ObservationRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
@Configuration(proxyBeanMethods = false)
public class HttpHandlerConfiguration {
private final ApplicationContext applicationContext;
public HttpHandlerConfiguration(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Bean
public HttpHandler httpHandler(ObservationRegistry registry) {
return WebHttpHandlerBuilder.applicationContext(this.applicationContext)
.observationRegistry(registry)
.build();
}
}
它默认使用 org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention
,由 ServerRequestObservationContext
提供支持。
It is using the org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention
by default, backed by the ServerRequestObservationContext
.
仅当 Exception
未被应用程序控制器处理时,才会将观察记录为错误。通常,由 Spring WebFlux 的 @ExceptionHandler
和 xref:web.adoc#webflux-ann-rest-exceptions[ProblemDetail
支持处理的所有异常都不会记录到观察中。在请求处理期间的任何时候,您都可以自己设置 ObservationContext
上的错误字段:
This will only record an observation as an error if the Exception
has not been handled by an application Controller.
Typically, all exceptions handled by Spring WebFlux’s @ExceptionHandler
and ProblemDetail
support will not be recorded with the observation.
You can, at any point during request processing, set the error field on the ObservationContext
yourself:
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.reactive.observation.ServerRequestObservationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.server.ServerWebExchange;
@Controller
public class UserController {
@ExceptionHandler(MissingUserException.class)
ResponseEntity<Void> handleMissingUser(ServerWebExchange exchange, MissingUserException exception) {
// We want to record this exception with the observation
ServerRequestObservationContext.findCurrent(exchange.getAttributes())
.ifPresent(context -> context.setError(exception));
return ResponseEntity.notFound().build();
}
static class MissingUserException extends RuntimeException {
}
}
默认情况下,将创建以下 KeyValues
:
By default, the following KeyValues
are created:
Name |
Description |
|
Class name of the exception thrown during the exchange, or |
|
Duplicates the |
|
Name of HTTP request method or |
|
Outcome of the HTTP server exchange. |
|
HTTP response raw status code, or |
|
URI pattern for the matching handler if available, falling back to |
Name |
Description |
|
HTTP request URI. |
HTTP Client Instrumentation
HTTP 客户端交换观察结果使用名称 "http.client.requests"
为阻塞和反应客户端创建。与服务器对应项不同,仪表化直接在客户端中实现,因此唯一必需的步骤是在客户端上配置 ObservationRegistry
。
HTTP client exchange observations are created with the name "http.client.requests"
for blocking and reactive clients.
Unlike their server counterparts, the instrumentation is implemented directly in the client so the only required step is to configure an ObservationRegistry
on the client.
RestTemplate
应用程序必须在 RestTemplate
实例上配置 ObservationRegistry
以启用仪表化;如果没有它,观察结果就是“无操作”。Spring Boot 将自动配置已设置观察结果注册表的 RestTemplateBuilder
bean。
Applications must configure an ObservationRegistry
on RestTemplate
instances to enable the instrumentation; without that, observations are "no-ops".
Spring Boot will auto-configure RestTemplateBuilder
beans with the observation registry already set.
仪表化默认情况下使用 org.springframework.http.client.observation.ClientRequestObservationConvention
,该约定由 ClientRequestObservationContext
提供支持。
Instrumentation uses the org.springframework.http.client.observation.ClientRequestObservationConvention
by default, backed by the ClientRequestObservationContext
.
Name |
Description |
|
Name of HTTP request method or |
|
URI template used for HTTP request, or |
|
Client name derived from the request URI host. |
|
HTTP response raw status code, or |
|
Outcome of the HTTP client exchange. |
|
Class name of the exception thrown during the exchange, or |
|
Duplicates the |
Name |
Description |
|
HTTP request URI. |
RestClient
应用程序必须在 RestClient.Builder
上配置 ObservationRegistry
以启用仪表化;如果没有它,观察结果就是“无操作”。
Applications must configure an ObservationRegistry
on the RestClient.Builder
to enable the instrumentation; without that, observations are "no-ops".
仪表化默认情况下使用 org.springframework.http.client.observation.ClientRequestObservationConvention
,该约定由 ClientRequestObservationContext
提供支持。
Instrumentation uses the org.springframework.http.client.observation.ClientRequestObservationConvention
by default, backed by the ClientRequestObservationContext
.
Name |
Description |
|
Name of HTTP request method or |
|
URI template used for HTTP request, or |
|
Client name derived from the request URI host. |
|
HTTP response raw status code, or |
|
Outcome of the HTTP client exchange. |
|
Class name of the exception thrown during the exchange, or |
|
Duplicates the |
Name |
Description |
|
HTTP request URI. |
WebClient
应用程序必须在 WebClient
构建器上配置 ObservationRegistry
以启用仪表化;如果没有它,观察结果就是“无操作”。Spring Boot 将自动配置已设置观察结果注册表的 WebClient.Builder
bean。
Applications must configure an ObservationRegistry
on the WebClient
builder to enable the instrumentation; without that, observations are "no-ops".
Spring Boot will auto-configure WebClient.Builder
beans with the observation registry already set.
仪表化默认情况下使用 org.springframework.web.reactive.function.client.ClientRequestObservationConvention
,该约定由 ClientRequestObservationContext
提供支持。
Instrumentation uses the org.springframework.web.reactive.function.client.ClientRequestObservationConvention
by default, backed by the ClientRequestObservationContext
.
Name |
Description |
|
Name of HTTP request method or |
|
URI template used for HTTP request, or |
|
Client name derived from the request URI host. |
|
HTTP response raw status code, or |
|
Outcome of the HTTP client exchange. |
|
Class name of the exception thrown during the exchange, or |
|
Duplicates the |
Name |
Description |
|
HTTP request URI. |
Application Events and @EventListener
Spring 框架不为 xref:core/beans/context-introduction.adoc#context-functionality-events-annotation[@EventListener
调用提供观察,因为它们没有此类检测的正确语义。默认情况下,事件发布和处理是同步进行的,并且在同一线程上。这意味着在执行该任务期间,ThreadLocals 和日志记录上下文将与事件发布方相同。
Spring Framework does not contribute Observations for @EventListener
calls,
as they don’t have the right semantics for such instrumentation.
By default, event publication and processing are done synchronously and on the same thread.
This means that during the execution of that task, the ThreadLocals and logging context will be the same as the event publisher.
如果应用程序通过一种将事件处理计划到不同线程中的策略来全局配置一个自定义 ApplicationEventMulticaster
,则这将不再成立。所有 @EventListener
方法都将在不同的线程中进行处理,而不是主事件发布线程。在这些情况下, Micrometer Context Propagation library 可以帮助传播此类值并更好地关联事件处理。应用程序可以配置所选 TaskExecutor
以使用装饰任务和传播上下文的 ContextPropagatingTaskDecorator
。要实现此操作,类路径中必须存在 io.micrometer:context-propagation
库:
If the application globally configures a custom ApplicationEventMulticaster
with a strategy that schedules event processing on different threads, this is no longer true.
All @EventListener
methods will be processed on a different thread, outside the main event publication thread.
In these cases, the Micrometer Context Propagation library can help propagate such values and better correlate the processing of the events.
The application can configure the chosen TaskExecutor
to use a ContextPropagatingTaskDecorator
that decorates tasks and propagates context.
For this to work, the io.micrometer:context-propagation
library must be present on the classpath:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.support.ContextPropagatingTaskDecorator;
@Configuration
public class ApplicationEventsConfiguration {
@Bean(name = "applicationEventMulticaster")
public SimpleApplicationEventMulticaster simpleApplicationEventMulticaster() {
SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();
SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
// decorate task execution with a decorator that supports context propagation
taskExecutor.setTaskDecorator(new ContextPropagatingTaskDecorator());
eventMulticaster.setTaskExecutor(taskExecutor);
return eventMulticaster;
}
}
类似地,如果为每个带有 @EventListener
注释的方法在本地做出了异步选择,通过向其中添加 @Async
,你可以通过按其限定符引用 TaskExecutor
来选择传播上下文的 TaskExecutor
。给定以下 TaskExecutor
bean 定义,并使用专门的任务装饰器进行配置:
Similarly, if that asynchronous choice is made locally for each @EventListener
annotated method, by adding @Async
to it,
you can choose a TaskExecutor
that propagates context by referring to it by its qualifier.
Given the following TaskExecutor
bean definition, configured with the dedicated task decorator:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.core.task.support.ContextPropagatingTaskDecorator;
@Configuration
public class EventAsyncExecutionConfiguration {
@Bean(name = "propagatingContextExecutor")
public TaskExecutor propagatingContextExecutor() {
SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
// decorate task execution with a decorator that supports context propagation
taskExecutor.setTaskDecorator(new ContextPropagatingTaskDecorator());
return taskExecutor;
}
}
使用“@Async”和相关限定词对事件监听器进行注释将获得类似的上下文传播结果:
Annotating event listeners with @Async
and the relevant qualifier will achieve similar context propagation results:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class EmailNotificationListener {
private final Log logger = LogFactory.getLog(EmailNotificationListener.class);
@EventListener(EmailReceivedEvent.class)
@Async("propagatingContextExecutor")
public void emailReceived(EmailReceivedEvent event) {
// asynchronously process the received event
// this logging statement will contain the expected MDC entries from the propagated context
logger.info("email has been received");
}
}