此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.1.10Spring中文文档

此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.1.10Spring中文文档

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

Spring Framework 检测其自身代码库的各个部分,以便在配置了 您可以了解有关在 Spring Boot 中配置可观测性基础结构的更多信息。ObservationRegistrySpring中文文档

产生的观察结果清单

Spring Framework 检测了各种特性以实现可观测性。 如本节开头所述,观察点可以根据配置生成计时器指标和/或跟踪。Spring中文文档

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

"http.client.requests"Spring中文文档

HTTP 客户端交换所花费的时间Spring中文文档

"http.server.requests"Spring中文文档

框架级别的 HTTP 服务器交换的处理时间Spring中文文档

观测值使用 Micrometer 的官方命名约定,但度量名称将自动转换为监控系统后端首选的格式(Prometheus、Atlas、Graphite、InfluxDB 等)。
表 1.Spring Framework 生成的观察结果
观察任务名称 描述

"http.client.requests"Spring中文文档

HTTP 客户端交换所花费的时间Spring中文文档

"http.server.requests"Spring中文文档

框架级别的 HTTP 服务器交换的处理时间Spring中文文档

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

千分尺观察概念

如果您不熟悉千分尺观察,这里是您应该了解的概念的快速摘要。Spring中文文档

  • Observation是应用程序中发生的实际记录。这由实现处理以生成指标或跟踪。ObservationHandlerSpring中文文档

  • 每个观察值都有相应的实现;此类型包含为其提取元数据的所有相关信息。 在 HTTP 服务器观察的情况下,上下文实现可以保存 HTTP 请求、HTTP 响应、处理过程中引发的任何异常等。ObservationContextSpring中文文档

  • 每个都包含元数据。在 HTTP 服务器观察的情况下,这可能是 HTTP 请求方法、HTTP 响应状态等。 此元数据由实现提供,这些实现应声明它们支持的类型。ObservationKeyValuesObservationConventionObservationContextSpring中文文档

  • KeyValues如果元组的可能值数量有限,则称为“低基数”(HTTP 方法就是一个很好的例子)。 低基数值仅计入指标。 相反,“高基数”值是无限制的(例如,HTTP 请求 URI),并且仅参与跟踪。KeyValueSpring中文文档

  • An 记录了特定域中的所有观察结果,列出了预期的键名称及其含义。ObservationDocumentationSpring中文文档

配置观测点

全局配置选项在级别上可用。 每个检测组件将提供两个扩展点:ObservationRegistry#observationConfig()Spring中文文档

  • 设置 ;如果未设置,则不会记录观测值,并且将无操作ObservationRegistrySpring中文文档

  • 提供自定义以更改默认观察点名称并提取ObservationConventionKeyValuesSpring中文文档

使用自定义观察约定

让我们以 Spring MVC“http.server.requests”指标检测为例,其中包含 . 此观察结果使用 a 和 ;可以在 Servlet 过滤器上配置自定义约定。 如果要自定义使用观测值生成的元数据,可以根据您的要求扩展:ServerHttpObservationFilterServerRequestObservationConventionServerRequestObservationContextDefaultServerRequestObservationConventionSpring中文文档

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中文文档

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

}

您还可以使用自定义实现类似的目标 - 添加或删除观测值的关键值。 筛选器不会替换默认约定,而是用作后处理组件。ObservationFilterSpring中文文档

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

您可以在 上配置实例。ObservationFilterObservationRegistrySpring中文文档

HTTP Server 检测

使用 Servlet 和 Reactive 应用程序的名称创建 HTTP 服务器交换观察。"http.server.requests"Spring中文文档

Servlet 应用程序

应用程序需要在其应用程序中配置 Servlet 过滤器。 默认情况下,它使用 .org.springframework.web.filter.ServerHttpObservationFilterorg.springframework.http.server.observation.DefaultServerRequestObservationConventionServerRequestObservationContextSpring中文文档

只有当 Web 框架未处理并已冒泡到 Servlet 过滤器时,才会将观察结果记录为错误。 通常,Spring MVC 和 ProblemDetail 支持处理的所有异常都不会记录在观察结果中。 在请求处理过程中的任何时候,您都可以在 yourself 上设置错误字段:Exception@ExceptionHandlerObservationContextSpring中文文档

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

默认情况下,将创建以下内容:KeyValuesSpring中文文档

表 2.低基数键

exception (必填)Spring中文文档

交换期间引发的异常的名称,如果没有发生异常,则为 }。KeyValue#NONE_VALUESpring中文文档

method (必填)Spring中文文档

HTTP 请求方法的名称,或者如果不是众所周知的方法。"none"Spring中文文档

outcome (必填)Spring中文文档

HTTP 服务器交换的结果。Spring中文文档

status (必填)Spring中文文档

HTTP 响应原始状态代码,或者如果未创建响应。"UNKNOWN"Spring中文文档

uri (必填)Spring中文文档

匹配处理程序的 URI 模式(如果可用),回退到 3xx 响应、404 响应、没有路径信息的请求以及所有其他请求。REDIRECTIONNOT_FOUNDrootUNKNOWNSpring中文文档

表 3.高基数键

http.url (必填)Spring中文文档

HTTP 请求 URI。Spring中文文档

反应式应用

应用程序需要在其应用程序中配置响应式。 默认情况下,它使用 .org.springframework.web.filter.reactive.ServerHttpObservationFilterWebFilterorg.springframework.http.server.reactive.observation.DefaultServerRequestObservationConventionServerRequestObservationContextSpring中文文档

只有当 Web 框架尚未处理并且已冒泡到 . 通常,Spring WebFlux 和 ProblemDetail 支持处理的所有异常都不会记录在观察结果中。 在请求处理过程中的任何时候,您都可以在 yourself 上设置错误字段:ExceptionWebFilter@ExceptionHandlerObservationContextSpring中文文档

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.filter.reactive.ServerHttpObservationFilter;
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
		ServerHttpObservationFilter.findObservationContext(exchange)
				.ifPresent(context -> context.setError(exception));
		return ResponseEntity.notFound().build();
	}

	static class MissingUserException extends RuntimeException {
	}

}

默认情况下,将创建以下内容:KeyValuesSpring中文文档

表 4.低基数键

exception (必填)Spring中文文档

交换期间抛出的异常的名称,或者如果没有发生异常。"none"Spring中文文档

method (必填)Spring中文文档

HTTP 请求方法的名称,或者如果不是众所周知的方法。"none"Spring中文文档

outcome (必填)Spring中文文档

HTTP 服务器交换的结果。Spring中文文档

status (必填)Spring中文文档

HTTP 响应原始状态代码,或者如果未创建响应。"UNKNOWN"Spring中文文档

uri (必填)Spring中文文档

匹配处理程序的 URI 模式(如果可用),回退到 3xx 响应、404 响应、没有路径信息的请求以及所有其他请求。REDIRECTIONNOT_FOUNDrootUNKNOWNSpring中文文档

表 5.高基数键

http.url (必填)Spring中文文档

HTTP 请求 URI。Spring中文文档

由于检测是在 Servlet 过滤器级别完成的,因此观察范围仅涵盖在此之后订购的过滤器以及请求的处理。 通常,Servlet 容器错误处理在较低级别执行,并且不会有任何活动观察或跨度。 对于此用例,需要特定于容器的实现,例如 Tomcat;这超出了本项目的范围。org.apache.catalina.Valve
表 2.低基数键

exception (必填)Spring中文文档

交换期间引发的异常的名称,如果没有发生异常,则为 }。KeyValue#NONE_VALUESpring中文文档

method (必填)Spring中文文档

HTTP 请求方法的名称,或者如果不是众所周知的方法。"none"Spring中文文档

outcome (必填)Spring中文文档

HTTP 服务器交换的结果。Spring中文文档

status (必填)Spring中文文档

HTTP 响应原始状态代码,或者如果未创建响应。"UNKNOWN"Spring中文文档

uri (必填)Spring中文文档

匹配处理程序的 URI 模式(如果可用),回退到 3xx 响应、404 响应、没有路径信息的请求以及所有其他请求。REDIRECTIONNOT_FOUNDrootUNKNOWNSpring中文文档

表 3.高基数键

http.url (必填)Spring中文文档

HTTP 请求 URI。Spring中文文档

表 4.低基数键

exception (必填)Spring中文文档

交换期间抛出的异常的名称,或者如果没有发生异常。"none"Spring中文文档

method (必填)Spring中文文档

HTTP 请求方法的名称,或者如果不是众所周知的方法。"none"Spring中文文档

outcome (必填)Spring中文文档

HTTP 服务器交换的结果。Spring中文文档

status (必填)Spring中文文档

HTTP 响应原始状态代码,或者如果未创建响应。"UNKNOWN"Spring中文文档

uri (必填)Spring中文文档

匹配处理程序的 URI 模式(如果可用),回退到 3xx 响应、404 响应、没有路径信息的请求以及所有其他请求。REDIRECTIONNOT_FOUNDrootUNKNOWNSpring中文文档

表 5.高基数键

http.url (必填)Spring中文文档

HTTP 请求 URI。Spring中文文档

HTTP 客户端检测

HTTP 客户端交换观察结果是使用阻塞客户端和反应式客户端的名称创建的。 与服务器对应项不同,检测是直接在客户端中实现的,因此唯一需要的步骤是在客户端上配置。"http.client.requests"ObservationRegistrySpring中文文档

RestTemplate

应用程序必须配置 on 实例才能启用检测;没有这一点,观察就是“无操作”。 Spring Boot 将在已设置观察注册表的情况下自动配置 bean。ObservationRegistryRestTemplateRestTemplateBuilderSpring中文文档

默认情况下,检测使用 ,由 .org.springframework.http.client.observation.ClientRequestObservationConventionClientRequestObservationContextSpring中文文档

表 6.低基数键

method (必填)Spring中文文档

HTTP 请求方法的名称,或者如果不是众所周知的方法。"none"Spring中文文档

uri (必填)Spring中文文档

用于 HTTP 请求的 URI 模板,或者如果未提供任何模板。仅考虑 URI 的路径部分。"none"Spring中文文档

client.name (必填)Spring中文文档

派生自请求 URI 主机的客户端名称。Spring中文文档

status (必填)Spring中文文档

HTTP 响应原始状态代码,或者如果是 ,或者如果未收到响应。"IO_ERROR"IOException"CLIENT_ERROR"Spring中文文档

outcome (必填)Spring中文文档

HTTP 客户端交换的结果。Spring中文文档

exception (必填)Spring中文文档

交换期间抛出的异常的名称,或者如果没有发生异常。"none"Spring中文文档

表 7.高基数键

http.url (必填)Spring中文文档

HTTP 请求 URI。Spring中文文档

Web客户端

应用程序必须在生成器上配置一个以启用检测;没有这一点,观察就是“无操作”。 Spring Boot 将在已设置观察注册表的情况下自动配置 bean。ObservationRegistryWebClientWebClient.BuilderSpring中文文档

默认情况下,检测使用 ,由 .org.springframework.web.reactive.function.client.ClientRequestObservationConventionClientRequestObservationContextSpring中文文档

表 8.低基数键

method (必填)Spring中文文档

HTTP 请求方法的名称,或者如果不是众所周知的方法。"none"Spring中文文档

uri (必填)Spring中文文档

用于 HTTP 请求的 URI 模板,或者如果未提供任何模板。仅考虑 URI 的路径部分。"none"Spring中文文档

client.name (必填)Spring中文文档

派生自请求 URI 主机的客户端名称。Spring中文文档

status (必填)Spring中文文档

HTTP 响应原始状态代码,或者如果是 ,或者如果未收到响应。"IO_ERROR"IOException"CLIENT_ERROR"Spring中文文档

outcome (必填)Spring中文文档

HTTP 客户端交换的结果。Spring中文文档

exception (必填)Spring中文文档

交换期间抛出的异常的名称,或者如果没有发生异常。"none"Spring中文文档

表 9.高基数键

http.url (必填)Spring中文文档

HTTP 请求 URI。Spring中文文档

表 6.低基数键

method (必填)Spring中文文档

HTTP 请求方法的名称,或者如果不是众所周知的方法。"none"Spring中文文档

uri (必填)Spring中文文档

用于 HTTP 请求的 URI 模板,或者如果未提供任何模板。仅考虑 URI 的路径部分。"none"Spring中文文档

client.name (必填)Spring中文文档

派生自请求 URI 主机的客户端名称。Spring中文文档

status (必填)Spring中文文档

HTTP 响应原始状态代码,或者如果是 ,或者如果未收到响应。"IO_ERROR"IOException"CLIENT_ERROR"Spring中文文档

outcome (必填)Spring中文文档

HTTP 客户端交换的结果。Spring中文文档

exception (必填)Spring中文文档

交换期间抛出的异常的名称,或者如果没有发生异常。"none"Spring中文文档

表 7.高基数键

http.url (必填)Spring中文文档

HTTP 请求 URI。Spring中文文档

表 8.低基数键

method (必填)Spring中文文档

HTTP 请求方法的名称,或者如果不是众所周知的方法。"none"Spring中文文档

uri (必填)Spring中文文档

用于 HTTP 请求的 URI 模板,或者如果未提供任何模板。仅考虑 URI 的路径部分。"none"Spring中文文档

client.name (必填)Spring中文文档

派生自请求 URI 主机的客户端名称。Spring中文文档

status (必填)Spring中文文档

HTTP 响应原始状态代码,或者如果是 ,或者如果未收到响应。"IO_ERROR"IOException"CLIENT_ERROR"Spring中文文档

outcome (必填)Spring中文文档

HTTP 客户端交换的结果。Spring中文文档

exception (必填)Spring中文文档

交换期间抛出的异常的名称,或者如果没有发生异常。"none"Spring中文文档

表 9.高基数键

http.url (必填)Spring中文文档

HTTP 请求 URI。Spring中文文档