此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-doc.cadn.net.cn

可观测性支持

Micrometer 定义了一个 Observation 概念,该概念在应用程序中同时启用 Metrics 和 Traces。 Metrics Support 提供了一种创建计时器、仪表或计数器的方法,用于收集有关应用程序运行时行为的统计信息。 指标可以帮助您跟踪错误率、使用模式、性能等。 跟踪提供了整个系统的整体视图,跨越了应用程序边界;您可以放大特定用户请求,并跟踪它们在应用程序中的整个完成情况。spring-doc.cadn.net.cn

Spring 框架检测其自身代码库的各个部分以发布观察结果,如果ObservationRegistry已配置。 您可以了解有关在 Spring Boot 中配置可观测性基础设施的更多信息。spring-doc.cadn.net.cn

生成的 Observation 列表

Spring Framework 检测各种功能以实现可观察性。 如本节开头所述,观察可以生成计时器指标和/或跟踪,具体取决于配置。spring-doc.cadn.net.cn

表 1.Spring Framework 生成的观察结果
观察项名称 描述

"http.client.requests"spring-doc.cadn.net.cn

HTTP 客户端交换所花费的时间spring-doc.cadn.net.cn

"http.server.requests"spring-doc.cadn.net.cn

框架级别的 HTTP 服务器交换的处理时间spring-doc.cadn.net.cn

"jms.message.publish"spring-doc.cadn.net.cn

消息生成者将 JMS 消息发送到目标所花费的时间。spring-doc.cadn.net.cn

"jms.message.process"spring-doc.cadn.net.cn

消息使用者以前收到的 JMS 消息的处理时间。spring-doc.cadn.net.cn

"tasks.scheduled.execution"spring-doc.cadn.net.cn

执行@Scheduled任务spring-doc.cadn.net.cn

观测使用 Micrometer 的官方命名约定,但 Metrics 名称将自动转换为监控系统后端首选的格式(Prometheus、Atlas、Graphite、InfluxDB 等)。

千分尺观察概念

如果您不熟悉千分尺观察,以下是您应该了解的概念的快速总结。spring-doc.cadn.net.cn

  • Observation是应用程序中发生的事情的实际记录。这由ObservationHandler实现来生成指标或跟踪。spring-doc.cadn.net.cn

  • 每个观察结果都有一个对应的ObservationContext实现;此类型包含用于提取其元数据的所有相关信息。 对于 HTTP 服务器观察,上下文实现可以保存 HTTP 请求、HTTP 响应、处理过程中引发的任何异常等。spring-doc.cadn.net.cn

  • Observation保留KeyValues元数据。对于 HTTP 服务器观察,这可能是 HTTP 请求方法、HTTP 响应状态等。 此元数据由ObservationConvention应该声明ObservationContext他们支持。spring-doc.cadn.net.cn

  • KeyValues如果KeyValuetuple (HTTP 方法就是一个很好的例子)。 低基数值仅贡献给量度。 相反,“高基数”值是无限的(例如,HTTP 请求 URI),并且仅参与跟踪。spring-doc.cadn.net.cn

  • ObservationDocumentation记录特定域中的所有观察结果,列出预期的键名称及其含义。spring-doc.cadn.net.cn

配置观测

全局配置选项位于ObservationRegistry#observationConfig()水平。 每个 instrumented 组件将提供两个扩展点:spring-doc.cadn.net.cn

  • 设置ObservationRegistry;如果未设置,则不会记录观测值,并且将为 NO-OPSspring-doc.cadn.net.cn

  • 提供自定义ObservationConvention更改默认观测项名称和提取的KeyValuesspring-doc.cadn.net.cn

使用自定义 Observation 约定

让我们以 Spring MVC“http.server.requests”指标插桩为例,其中ServerHttpObservationFilter. 此观察使用ServerRequestObservationConvention替换为ServerRequestObservationContext;可以在 Servlet 过滤器上配置自定义约定。 如果要自定义使用观察生成的元数据,可以扩展DefaultServerRequestObservationConvention根据您的要求:spring-doc.cadn.net.cn

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());
	}

}

如果您想要完全控制,可以为您感兴趣的观察实现整个约定协定:spring-doc.cadn.net.cn

import java.util.Locale;

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(Locale.ROOT);
	}

	@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– 添加或删除观察的关键值。 过滤器不会替换默认约定,而是用作后处理组件。spring-doc.cadn.net.cn

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;
	}
}

您可以配置ObservationFilter实例ObservationRegistry.spring-doc.cadn.net.cn

@Scheduled 任务检测

为 Observation (观察) 创建每次执行@Scheduled任务. 应用程序需要配置ObservationRegistryScheduledTaskRegistrar以启用观测记录。 这可以通过声明SchedulingConfigurer设置 observation 注册表的 bean:spring-doc.cadn.net.cn

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);
	}

}

它使用org.springframework.scheduling.support.DefaultScheduledTaskObservationConvention默认情况下,由ScheduledTaskObservationContext. 您可以在ObservationRegistry径直。 在执行 scheduled 方法期间,当前观察结果将在ThreadLocalcontext 或 Reactor 上下文(如果 scheduled 方法返回MonoFluxtype) 的 intent 的 intentspring-doc.cadn.net.cn

默认情况下,以下KeyValues创建:spring-doc.cadn.net.cn

表 2.低基数键

code.function (必填)spring-doc.cadn.net.cn

Java 的名称Method,该 ID 已计划执行。spring-doc.cadn.net.cn

code.namespace (必填)spring-doc.cadn.net.cn

保存 scheduled 方法的 bean 实例的类的规范名称,或者"ANONYMOUS"对于匿名类。spring-doc.cadn.net.cn

error (必填)spring-doc.cadn.net.cn

执行期间引发的异常的类名,或者"none"如果没有发生异常。spring-doc.cadn.net.cn

exception (已弃用)spring-doc.cadn.net.cn

复制error键,将来可能会将其删除。spring-doc.cadn.net.cn

outcome (必填)spring-doc.cadn.net.cn

方法执行的结果。可以是"SUCCESS","ERROR""UNKNOWN"(例如,如果在执行期间取消了作)。spring-doc.cadn.net.cn

JMS 消息传递检测

Spring 框架使用 Micrometer 提供的 Jakarta JMS 插桩,如果io.micrometer:micrometer-jakarta9dependency 在 Classpath 上。 这io.micrometer.jakarta9.instrument.jms.JmsInstrumentation仪器jakarta.jms.Session并记录相关观察结果。spring-doc.cadn.net.cn

此检测将创建 2 种类型的观察值:spring-doc.cadn.net.cn

  • "jms.message.publish"当 JMS 消息发送到代理时,通常使用JmsTemplate.spring-doc.cadn.net.cn

  • "jms.message.process"当应用程序处理 JMS 消息时,通常使用MessageListener@JmsListenerannotated 方法。spring-doc.cadn.net.cn

目前没有"jms.message.receive"observations 的 S ,因为测量等待收到消息所花费的时间几乎没有价值。 此类集成通常会检测MessageConsumer#receive方法调用。但是,一旦这些返回,则不会测量处理时间,并且跟踪范围无法传播到应用程序。

默认情况下,两个观测值共享同一组 possibleKeyValues:spring-doc.cadn.net.cn

表 3.低基数键

消息传送作期间引发的异常的类名(或“none”)。spring-doc.cadn.net.cn

exception (已弃用)spring-doc.cadn.net.cn

复制error键,将来可能会将其删除。spring-doc.cadn.net.cn

messaging.destination.temporary (必填)spring-doc.cadn.net.cn

目标是否为TemporaryQueueTemporaryTopic(值:"true""false").spring-doc.cadn.net.cn

messaging.operation (必填)spring-doc.cadn.net.cn

正在执行的 JMS作的名称(值:"publish""process").spring-doc.cadn.net.cn

表 4.高基数键

messaging.message.conversation_idspring-doc.cadn.net.cn

JMS 消息的相关 ID。spring-doc.cadn.net.cn

messaging.destination.namespring-doc.cadn.net.cn

当前邮件发送到的目标的名称。spring-doc.cadn.net.cn

messaging.message.idspring-doc.cadn.net.cn

消息系统用作消息标识符的值。spring-doc.cadn.net.cn

JMS 消息发布检测

"jms.message.publish"将 JMS 消息发送到 Broker 时,将记录观察结果。 它们测量发送消息所花费的时间,并使用传出的 JMS 消息标头传播跟踪信息。spring-doc.cadn.net.cn

您需要配置ObservationRegistryJmsTemplate要启用观察:spring-doc.cadn.net.cn

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.DefaultJmsPublishObservationConvention默认情况下,由io.micrometer.jakarta9.instrument.jms.JmsPublishObservationContext.spring-doc.cadn.net.cn

类似的观测值记录为@JmsListener从 listener 方法返回响应消息时的 annotated methods。spring-doc.cadn.net.cn

JMS 消息处理检测

"jms.message.process"当应用程序处理 JMS 消息时,将记录观察结果。 它们测量处理消息所花费的时间,并使用传入的 JMS 消息标头传播跟踪上下文。spring-doc.cadn.net.cn

大多数应用程序将使用@JmsListener带注释的方法处理传入消息的机制。 您需要确保ObservationRegistry在专用的JmsListenerContainerFactory:spring-doc.cadn.net.cn

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;
	}

}

需要默认的容器工厂才能启用注解支持, 但请注意,@JmsListener注释可以出于特定目的引用特定的容器工厂 Bean。 在所有情况下,只有在容器工厂上配置了 observation 注册表时,才会记录 Observations。spring-doc.cadn.net.cn

类似的观测值记录为JmsTemplate当消息由MessageListener. 此类侦听器在MessageConsumer在会话回调中(请参阅JmsTemplate.execute(SessionCallback<T>)).spring-doc.cadn.net.cn

此观察使用io.micrometer.jakarta9.instrument.jms.DefaultJmsProcessObservationConvention默认情况下,由io.micrometer.jakarta9.instrument.jms.JmsProcessObservationContext.spring-doc.cadn.net.cn

HTTP 服务器检测

HTTP 服务器交换观察是使用名称"http.server.requests"适用于 Servlet 和 Reactive 应用程序。spring-doc.cadn.net.cn

Servlet 应用程序

应用程序需要配置org.springframework.web.filter.ServerHttpObservationFilterServlet 过滤器。 它使用org.springframework.http.server.observation.DefaultServerRequestObservationConvention默认情况下,由ServerRequestObservationContext.spring-doc.cadn.net.cn

这只会在出现Exception尚未由 Web 框架处理,并且已冒泡到 Servlet 过滤器。 通常,所有异常都由 Spring MVC 的@ExceptionHandlerProblemDetail支持不会与观测值一起记录。 在请求处理过程中,您可以随时在ObservationContext你自己:spring-doc.cadn.net.cn

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 级别完成的,因此观察范围仅涵盖在此过滤器之后排序的过滤器以及请求的处理。 通常,Servlet 容器错误处理在较低级别执行,并且不会有任何活动的观察或 span。 对于此用例,需要特定于容器的实现,例如org.apache.catalina.Valve对于 Tomcat;这超出了本项目的范围。

默认情况下,以下KeyValues创建:spring-doc.cadn.net.cn

表 5.低基数键

error (必填)spring-doc.cadn.net.cn

交换期间引发的异常的类名,或"none"如果没有发生异常。spring-doc.cadn.net.cn

exception (已弃用)spring-doc.cadn.net.cn

复制error键,将来可能会将其删除。spring-doc.cadn.net.cn

method (必填)spring-doc.cadn.net.cn

HTTP 请求方法的名称或"none"如果不是众所周知的方法。spring-doc.cadn.net.cn

outcome (必填)spring-doc.cadn.net.cn

HTTP 服务器交换的结果。spring-doc.cadn.net.cn

status (必填)spring-doc.cadn.net.cn

HTTP 响应原始状态代码,或"UNKNOWN"如果未创建响应。spring-doc.cadn.net.cn

uri (必填)spring-doc.cadn.net.cn

匹配处理程序的 URI 模式(如果可用),回退到REDIRECTION对于 3xx 响应,NOT_FOUND对于 404 个回复,root对于没有路径信息的请求,以及UNKNOWN对于所有其他请求。spring-doc.cadn.net.cn

表 6.高基数键

http.url (必填)spring-doc.cadn.net.cn

HTTP 请求 URI。spring-doc.cadn.net.cn

响应式应用程序

应用程序需要配置WebHttpHandlerBuilder替换为MeterRegistry以启用服务器插桩。 这可以在WebHttpHandlerBuilder如下:spring-doc.cadn.net.cn

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.spring-doc.cadn.net.cn

这只会在出现Exception尚未由应用程序控制器处理。 通常,所有异常都由 Spring WebFlux 的@ExceptionHandlerProblemDetail支持不会与观测值一起记录。 在请求处理过程中,您可以随时在ObservationContext你自己:spring-doc.cadn.net.cn

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创建:spring-doc.cadn.net.cn

表 7.低基数键

error (必填)spring-doc.cadn.net.cn

交换期间引发的异常的类名,或"none"如果没有发生异常。spring-doc.cadn.net.cn

exception (已弃用)spring-doc.cadn.net.cn

复制error键,将来可能会将其删除。spring-doc.cadn.net.cn

method (必填)spring-doc.cadn.net.cn

HTTP 请求方法的名称或"none"如果不是众所周知的方法。spring-doc.cadn.net.cn

outcome (必填)spring-doc.cadn.net.cn

HTTP 服务器交换的结果。spring-doc.cadn.net.cn

status (必填)spring-doc.cadn.net.cn

HTTP 响应原始状态代码,或"UNKNOWN"如果未创建响应。spring-doc.cadn.net.cn

uri (必填)spring-doc.cadn.net.cn

匹配处理程序的 URI 模式(如果可用),回退到REDIRECTION对于 3xx 响应,NOT_FOUND对于 404 个回复,root对于没有路径信息的请求,以及UNKNOWN对于所有其他请求。spring-doc.cadn.net.cn

表 8.高基数键

http.url (必填)spring-doc.cadn.net.cn

HTTP 请求 URI。spring-doc.cadn.net.cn

HTTP 客户端检测

HTTP 客户端交换观察是使用名称"http.client.requests"用于阻塞和反应式客户端。 与服务器对应项不同,插桩直接在客户端中实现,因此唯一需要的步骤是配置ObservationRegistry在客户端上。spring-doc.cadn.net.cn

RestTemplate (休息模板)

应用程序必须配置ObservationRegistryRestTemplate实例来启用插桩;没有它,观察就是 “无作”。 Spring Boot 将自动配置RestTemplateBuilder已经设置了 observation 注册表的 bean。spring-doc.cadn.net.cn

插桩使用org.springframework.http.client.observation.ClientRequestObservationConvention默认情况下,由ClientRequestObservationContext.spring-doc.cadn.net.cn

表 9.低基数键

method (必填)spring-doc.cadn.net.cn

HTTP 请求方法的名称或"none"如果不是众所周知的方法。spring-doc.cadn.net.cn

uri (必填)spring-doc.cadn.net.cn

用于 HTTP 请求的 URI 模板,或"none"如果未提供。仅考虑 URI 的 path 部分。spring-doc.cadn.net.cn

client.name (必填)spring-doc.cadn.net.cn

从请求 URI 主机派生的客户端名称。spring-doc.cadn.net.cn

status (必填)spring-doc.cadn.net.cn

HTTP 响应原始状态代码,或"IO_ERROR"如果IOException"CLIENT_ERROR"如果未收到响应。spring-doc.cadn.net.cn

outcome (必填)spring-doc.cadn.net.cn

HTTP 客户端交换的结果。spring-doc.cadn.net.cn

error (必填)spring-doc.cadn.net.cn

交换期间引发的异常的类名,或"none"如果没有发生异常。spring-doc.cadn.net.cn

exception (已弃用)spring-doc.cadn.net.cn

复制error键,将来可能会将其删除。spring-doc.cadn.net.cn

表 10.高基数键

http.url (必填)spring-doc.cadn.net.cn

HTTP 请求 URI。spring-doc.cadn.net.cn

Rest客户端

应用程序必须配置ObservationRegistryRestClient.Builder启用检测;没有它,观察就是 “无作”。spring-doc.cadn.net.cn

插桩使用org.springframework.http.client.observation.ClientRequestObservationConvention默认情况下,由ClientRequestObservationContext.spring-doc.cadn.net.cn

表 11.低基数键

method (必填)spring-doc.cadn.net.cn

HTTP 请求方法的名称或"none"如果无法创建请求。spring-doc.cadn.net.cn

uri (必填)spring-doc.cadn.net.cn

用于 HTTP 请求的 URI 模板,或"none"如果未提供。仅考虑 URI 的 path 部分。spring-doc.cadn.net.cn

client.name (必填)spring-doc.cadn.net.cn

从请求 URI 主机派生的客户端名称。spring-doc.cadn.net.cn

status (必填)spring-doc.cadn.net.cn

HTTP 响应原始状态代码,或"IO_ERROR"如果IOException"CLIENT_ERROR"如果未收到响应。spring-doc.cadn.net.cn

outcome (必填)spring-doc.cadn.net.cn

HTTP 客户端交换的结果。spring-doc.cadn.net.cn

error (必填)spring-doc.cadn.net.cn

交换期间引发的异常的类名,或"none"如果没有发生异常。spring-doc.cadn.net.cn

exception (已弃用)spring-doc.cadn.net.cn

复制error键,将来可能会将其删除。spring-doc.cadn.net.cn

表 12.高基数键

http.url (必填)spring-doc.cadn.net.cn

HTTP 请求 URI。spring-doc.cadn.net.cn

Web客户端

应用程序必须配置ObservationRegistryWebClient.Builder启用检测;没有它,观察就是 “无作”。 Spring Boot 将自动配置WebClient.Builder已经设置了 observation 注册表的 bean。spring-doc.cadn.net.cn

插桩使用org.springframework.web.reactive.function.client.ClientRequestObservationConvention默认情况下,由ClientRequestObservationContext.spring-doc.cadn.net.cn

表 13.低基数键

method (必填)spring-doc.cadn.net.cn

HTTP 请求方法的名称或"none"如果不是众所周知的方法。spring-doc.cadn.net.cn

uri (必填)spring-doc.cadn.net.cn

用于 HTTP 请求的 URI 模板,或"none"如果未提供。仅考虑 URI 的 path 部分。spring-doc.cadn.net.cn

client.name (必填)spring-doc.cadn.net.cn

从请求 URI 主机派生的客户端名称。spring-doc.cadn.net.cn

status (必填)spring-doc.cadn.net.cn

HTTP 响应原始状态代码,或"IO_ERROR"如果IOException"CLIENT_ERROR"如果未收到响应。spring-doc.cadn.net.cn

outcome (必填)spring-doc.cadn.net.cn

HTTP 客户端交换的结果。spring-doc.cadn.net.cn

error (必填)spring-doc.cadn.net.cn

交换期间引发的异常的类名,或"none"如果没有发生异常。spring-doc.cadn.net.cn

exception (已弃用)spring-doc.cadn.net.cn

复制error键,将来可能会将其删除。spring-doc.cadn.net.cn

表 14.高基数键

http.url (必填)spring-doc.cadn.net.cn

HTTP 请求 URI。spring-doc.cadn.net.cn

Application Events 和@EventListener

Spring Framework 不提供@EventListener调用, 因为他们没有用于此类检测的正确语义。 默认情况下,事件发布和处理是在同一线程上同步完成的。 这意味着在执行该任务期间,ThreadLocals 和日志记录上下文将与事件发布者相同。spring-doc.cadn.net.cn

如果应用程序全局配置了自定义ApplicationEventMulticaster对于在不同线程上调度事件处理的策略,这不再是事实。 都@EventListener方法将在 Main Event 发布线程之外的其他线程上进行处理。 在这些情况下,Micrometer Context Propagation 库可以帮助传播这些值并更好地关联事件的处理。 应用程序可以配置所选的TaskExecutor要使用ContextPropagatingTaskDecorator它装饰任务并传播上下文。 为此,需要io.micrometer:context-propagationlibrary 必须存在于 Classpath 中:spring-doc.cadn.net.cn

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;
	}

}

同样,如果该异步选择是在本地为每个@EventListenerannotated 方法,通过添加@Async对它, 您可以选择TaskExecutor它通过其限定符引用它来传播上下文。 给定以下内容TaskExecutorbean 定义,配置了专用的任务装饰器:spring-doc.cadn.net.cn

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;
	}

}

使用 Comments 事件侦听器@Async并且相关的 qualifier 会得到类似的上下文传播结果:spring-doc.cadn.net.cn

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");
	}

}

APP信息