可观测性支持
Micrometer 定义了一个 观测概念,它支持应用程序中的指标和跟踪。
指标支持提供了一种创建计时器、计量器或计数器的方式,用于收集有关应用程序运行时行为的统计数据。
指标可以帮助您跟踪错误率、使用模式、性能等。
跟踪提供了整个系统的整体视图,跨越应用程序边界;您可以深入查看特定的用户请求,并跟踪它们在应用程序中的整个完成过程。
如果配置了 ObservationRegistry,Spring Framework 会对其自身代码库的各个部分进行插桩,以发布观测。
您可以了解更多关于 在 Spring Boot 中配置可观测性基础设施的信息。
生成的观测列表
Spring Framework 对各种功能进行了插桩,以实现可观测性。 如 本节开头所述,观测可以根据配置生成计时器指标和/或跟踪。
| 观测名称 | 描述 |
|---|---|
HTTP 客户端交换所花费的时间 |
|
框架级别 HTTP 服务器交换的处理时间 |
|
消息生产者向目标发送 JMS 消息所花费的时间。 |
|
消息消费者先前接收到的 JMS 消息的处理时间。 |
|
|
|
观测使用 Micrometer 的官方命名约定,但指标名称将自动转换为 监控系统后端(Prometheus、Atlas、Graphite、InfluxDB…)首选的格式。 |
Micrometer 观测概念
如果您不熟悉 Micrometer 观测,这里快速总结一下您应该了解的概念。
-
Observation是应用程序中发生的实际记录。这由ObservationHandler实现处理,以生成指标或跟踪。 -
每个观测都有一个对应的
ObservationContext实现;此类型包含所有相关信息,用于提取其元数据。 在 HTTP 服务器观测的情况下,上下文实现可以包含 HTTP 请求、HTTP 响应、处理过程中抛出的任何异常等。 -
每个
Observation都包含KeyValues元数据。在 HTTP 服务器观测的情况下,这可以是 HTTP 请求方法、HTTP 响应状态等。 此元数据由ObservationConvention实现提供,这些实现应声明它们支持的ObservationContext类型。 -
如果
KeyValue元组的可能值数量有限且有界(HTTP 方法是一个很好的例子),则称KeyValues为“低基数”。 低基数的值仅贡献给指标。 相反,“高基数”值是无界的(例如,HTTP 请求 URI),并且仅贡献给跟踪。 -
ObservationDocumentation记录特定领域中的所有观测,列出预期的键名及其含义。
配置观测
全局配置选项可在 ObservationRegistry#observationConfig() 级别使用。
每个被插桩的组件将提供两个扩展点:
-
设置
ObservationRegistry;如果未设置,观测将不会被记录并且是空操作 -
提供自定义
ObservationConvention以更改默认观测名称和提取的KeyValues
使用自定义观测约定
让我们以 Spring MVC “http.server.requests”指标插桩与 ServerHttpObservationFilter 为例。
此观测使用 ServerRequestObservationConvention 和 ServerRequestObservationContext;可以在 Servlet 过滤器上配置自定义约定。
如果您想自定义观测生成的元数据,可以根据您的要求扩展 DefaultServerRequestObservationConvention:
如果您想完全控制,可以为感兴趣的观测实现整个约定契约:
您还可以使用自定义 ObservationFilter 实现类似目标——为观测添加或删除键值。
过滤器不会替换默认约定,而是用作后处理组件。
您可以在 ObservationRegistry 上配置 ObservationFilter 实例。
@Scheduled 任务插桩
每次执行 @Scheduled 任务都会创建一个观测。
应用程序需要配置 ScheduledTaskRegistrar 上的 ObservationRegistry 以启用观测记录。
这可以通过声明一个设置观测注册表的 SchedulingConfigurer bean 来完成:
它默认使用 org.springframework.scheduling.support.DefaultScheduledTaskObservationConvention,并由 ScheduledTaskObservationContext 支持。
您可以直接在 ObservationRegistry 上配置自定义实现。
在计划方法的执行期间,当前观测会在 ThreadLocal 上下文或 Reactor 上下文(如果计划方法返回 Mono 或 Flux 类型)中恢复。
默认情况下,会创建以下 KeyValues:
名称 |
描述 |
|
计划执行的 Java |
|
持有计划方法的 bean 实例的类的规范名称,或匿名类的 |
|
执行期间抛出的异常的类名,如果没有发生异常则为 |
|
复制 |
|
方法执行的结果。可以是 |
JMS 消息传递插桩
如果类路径上存在 io.micrometer:micrometer-jakarta9 依赖项,Spring Framework 将使用 Micrometer 提供的 Jakarta JMS 插桩。
io.micrometer.jakarta9.instrument.jms.JmsInstrumentation 对 jakarta.jms.Session 进行插桩并记录相关观测。
此插桩将创建 2 种类型的观测:
-
当 JMS 消息发送到消息代理时,通常使用
JmsTemplate,会创建"jms.message.publish"。 -
当 JMS 消息由应用程序处理时,通常使用
MessageListener或@JmsListener注解方法,会创建"jms.message.process"。
|
目前没有针对 |
默认情况下,这两种观测共享同一组可能的 KeyValues:
名称 |
描述 |
|
消息操作期间抛出的异常的类名(或“none”)。 |
|
复制 |
|
目标是否是 |
|
正在执行的 JMS 操作的名称(值:“ |
名称 |
描述 |
|
JMS 消息的关联 ID。 |
|
当前消息发送到的目标的名称。 |
|
消息系统用作消息标识符的值。 |
JMS 消息发布插桩
当 JMS 消息发送到消息代理时,会记录 "jms.message.publish" 观测。
它们测量发送消息所花费的时间,并通过传出的 JMS 消息头传播跟踪信息。
您需要配置 JmsTemplate 上的 ObservationRegistry 以启用观测:
它默认使用 io.micrometer.jakarta9.instrument.jms.DefaultJmsPublishObservationConvention,并由 io.micrometer.jakarta9.instrument.jms.JmsPublishObservationContext 支持。
当响应消息从侦听器方法返回时,@JmsListener 注解方法会记录类似的观测。
JMS 消息处理插桩
当 JMS 消息由应用程序处理时,会记录 "jms.message.process" 观测。
它们测量处理消息所花费的时间,并通过传入的 JMS 消息头传播跟踪上下文。
大多数应用程序将使用 @JmsListener 注解方法机制来处理传入消息。
您需要确保在专用的 JmsListenerContainerFactory 上配置了 ObservationRegistry:
需要一个默认的容器工厂来启用注解支持,
但请注意,@JmsListener 注解可以引用特定的容器工厂 bean 以用于特定目的。
在所有情况下,只有当在容器工厂上配置了观测注册表时,才会记录观测。
当 MessageListener 处理消息时,JmsTemplate 会记录类似的观测。
此类侦听器在会话回调中设置在 MessageConsumer 上(请参阅 JmsTemplate.execute(SessionCallback<T>))。
此观测默认使用 io.micrometer.jakarta9.instrument.jms.DefaultJmsProcessObservationConvention,并由 io.micrometer.jakarta9.instrument.jms.JmsProcessObservationContext 支持。
HTTP 服务器插桩
HTTP 服务器交换观测以名称 "http.server.requests" 为 Servlet 和 Reactive 应用程序创建,
如果使用 OpenTelemetry 约定,则为 "http.server.request.duration"。
Servlet 应用程序
应用程序需要在其应用程序中配置 org.springframework.web.filter.ServerHttpObservationFilter Servlet 过滤器。
这只会将观测记录为错误,如果 Exception 未被 Web 框架处理并已冒泡到 Servlet 过滤器。
通常,所有由 Spring MVC 的 @ExceptionHandler 和 ProblemDetail 支持处理的异常都不会被观测记录。
您可以在请求处理的任何时候自行在 ObservationContext 上设置错误字段:
|
由于插桩是在 Servlet 过滤器级别完成的,因此观测范围仅涵盖在此过滤器之后排序的过滤器以及请求的处理。
通常,Servlet 容器错误处理是在较低级别执行的,并且不会有任何活动的观测或 span。
对于此用例,需要容器特定的实现,例如 Tomcat 的 |
默认语义约定
它默认使用 org.springframework.http.server.observation.DefaultServerRequestObservationConvention,并由 ServerRequestObservationContext 支持。
默认情况下,会创建以下 KeyValues:
名称 |
描述 |
|
交换期间抛出的异常的类名,如果没有发生异常则为 |
|
复制 |
|
HTTP 请求方法的名称,如果不是众所周知的方法则为 |
|
HTTP 服务器交换的结果。 |
|
HTTP 响应原始状态码,如果未创建响应则为 |
|
匹配处理程序的 URI 模式(如果可用),否则对于 3xx 响应回退到 |
名称 |
描述 |
|
HTTP 请求 URI。 |
Reactive 应用程序
应用程序需要使用 MeterRegistry 配置 WebHttpHandlerBuilder 以启用服务器插桩。
这可以在 WebHttpHandlerBuilder 上完成,如下所示:
它默认使用 org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention,并由 ServerRequestObservationContext 支持。
这只会将观测记录为错误,如果 Exception 未被应用程序控制器处理。
通常,所有由 Spring WebFlux 的 @ExceptionHandler 和 ProblemDetail 支持处理的异常都不会被观测记录。
您可以在请求处理的任何时候自行在 ObservationContext 上设置错误字段:
默认情况下,会创建以下 KeyValues:
名称 |
描述 |
|
交换期间抛出的异常的类名,如果没有发生异常则为 |
|
复制 |
|
HTTP 请求方法的名称,如果不是众所周知的方法则为 |
|
HTTP 服务器交换的结果。 |
|
HTTP 响应原始状态码,如果未创建响应则为 |
|
匹配处理程序的 URI 模式(如果可用),否则对于 3xx 响应回退到 |
名称 |
描述 |
|
HTTP 请求 URI。 |
HTTP 客户端插桩
HTTP 客户端交换观测以名称 "http.client.requests" 为阻塞和响应式客户端创建。
此观测测量整个 HTTP 请求/响应交换,从连接建立到正文反序列化。
与服务器端不同,插桩直接在客户端中实现,因此唯一需要的步骤是在客户端上配置 ObservationRegistry。
RestTemplate
应用程序必须在 RestTemplate 实例上配置 ObservationRegistry 以启用插桩;否则,观测将是“空操作”。
Spring Boot 将自动配置已设置观测注册表的 RestTemplateBuilder bean。
插桩默认使用 org.springframework.http.client.observation.ClientRequestObservationConvention,并由 ClientRequestObservationContext 支持。
名称 |
描述 |
|
HTTP 请求方法的名称,如果不是众所周知的方法则为 |
|
用于 HTTP 请求的 URI 模板,如果未提供则为 |
|
从请求 URI 主机派生的客户端名称。 |
|
HTTP 响应原始状态码,如果发生 |
|
HTTP 客户端交换的结果。 |
|
交换期间抛出的异常的类名,如果没有发生异常则为 |
|
复制 |
名称 |
描述 |
|
HTTP 请求 URI。 |
RestClient
应用程序必须在 RestClient.Builder 上配置 ObservationRegistry 以启用插桩;否则,观测将是“空操作”。
插桩默认使用 org.springframework.http.client.observation.ClientRequestObservationConvention,并由 ClientRequestObservationContext 支持。
名称 |
描述 |
|
HTTP 请求方法的名称,如果无法创建请求则为 |
|
用于 HTTP 请求的 URI 模板,如果未提供则为 |
|
从请求 URI 主机派生的客户端名称。 |
|
HTTP 响应原始状态码,如果发生 |
|
HTTP 客户端交换的结果。 |
|
交换期间抛出的异常的类名,如果没有发生异常则为 |
|
复制 |
名称 |
描述 |
|
HTTP 请求 URI。 |
WebClient
应用程序必须在 WebClient.Builder 上配置 ObservationRegistry 以启用插桩;否则,观测将是“空操作”。
Spring Boot 将自动配置已设置观测注册表的 WebClient.Builder bean。
插桩默认使用 org.springframework.web.reactive.function.client.ClientRequestObservationConvention,并由 ClientRequestObservationContext 支持。
名称 |
描述 |
|
HTTP 请求方法的名称,如果不是众所周知的方法则为 |
|
用于 HTTP 请求的 URI 模板,如果未提供则为 |
|
从请求 URI 主机派生的客户端名称。 |
|
HTTP 响应原始状态码,如果发生 |
|
HTTP 客户端交换的结果。 |
|
交换期间抛出的异常的类名,如果没有发生异常则为 |
|
复制 |
名称 |
描述 |
|
HTTP 请求 URI。 |
应用程序事件和 @EventListener
Spring Framework 不为 @EventListener 调用贡献观测,
因为它们没有适合此类插桩的正确语义。
默认情况下,事件发布和处理是同步的,并且在同一线程上完成。
这意味着在任务执行期间,ThreadLocals 和日志上下文将与事件发布者相同。
如果应用程序全局配置了一个自定义 ApplicationEventMulticaster,其策略是在不同线程上调度事件处理,则情况不再如此。
所有 @EventListener 方法都将在不同的线程上处理,在主事件发布线程之外。
在这些情况下,https://docs.micrometer.io/context-propagation/reference/[Micrometer 上下文传播库]可以帮助传播这些值并更好地关联事件的处理。
应用程序可以将选择的 TaskExecutor 配置为使用 ContextPropagatingTaskDecorator,该装饰器装饰任务并传播上下文。
为此,io.micrometer:context-propagation 库必须存在于类路径中:
同样,如果为每个 @EventListener 注解方法局部做出异步选择,通过向其添加 @Async,
您可以选择一个通过引用其限定符来传播上下文的 TaskExecutor。
给定以下配置了专用任务装饰器的 TaskExecutor bean 定义:
使用 @Async 和相关限定符注解事件侦听器将实现类似的上下文传播结果: