跳到主要内容

介绍

DeepSeek V3 中英对照 Introduction

要使任何观测(Observation)发生,你需要通过 ObservationRegistry 注册 ObservationHandler 对象。一个 ObservationHandler 只会对支持的 Observation.Context 实现做出反应,并且可以通过对观测的生命周期事件做出反应来创建计时器(timers)、跨度(spans)和日志(logs),这些事件包括:

  • start - 观察已启动。当调用 Observation#start() 方法时发生。

  • stop - 观察已停止。当调用 Observation#stop() 方法时发生。

  • error - 观察过程中发生错误。当调用 Observation#error(exception) 方法时发生。

  • event - 观察过程中发生事件。当调用 Observation#event(event) 方法时发生。

  • scope started - 观察开启了一个作用域(Scope)。当不再使用时,必须关闭该作用域。处理器可以在启动时创建线程局部变量,这些变量在作用域关闭时被清除。当调用 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
none

这是观测范围(Observation Scope)状态图的样子:

Observation
Context
Scope Started ----------> Scope Finished
none

为了使生产环境中的问题调试成为可能,一个 Observation 需要额外的元数据,例如键值对(也称为标签)。然后,您可以通过这些标签查询您的指标或分布式追踪后端,以找到所需的数据。标签可以是高基数或低基数的。

important

高基数 意味着一个键值对可能有无限多个可能的值。HTTP URL 就是一个很好的例子(例如 /example/user1234/example/user2345 等)。低基数 意味着一个键值对可能有有限数量的可能值。模板化 的 HTTP URL 就是一个很好的例子(例如 /example/{userId})。

为了将观测生命周期操作与观测配置(如名称和高低基数标签)分离,您可以使用 ObservationConvention,它提供了一种简单的方式来覆盖默认的命名约定。

以下示例使用了 Observation API:

static class Example {

private final ObservationRegistry registry;

Example(ObservationRegistry registry) {
this.registry = registry;
}

void run() {
Observation.createNotStarted("foo", registry)
.lowCardinalityKeyValue("lowTag", "lowTagValue")
.highCardinalityKeyValue("highTag", "highTagValue")
.observe(() -> System.out.println("Hello"));
}

}
java
提示

调用 observe(() → …​) 会启动观察(Observation),将其置于作用域中,执行 lambda 表达式,如果发生错误,则将错误记录到观察中,关闭作用域并停止观察。

构建模块

在本节中,我们将对 Micrometer 观测组件进行简要概述。你可以在文档的这一部分中阅读更多相关内容。

术语表

  • ObservationRegistry - 包含 Observation 相关配置的注册表(例如处理程序、谓词、过滤器)

  • ObservationHandler - 处理 Observation 的生命周期(例如在观察开始时创建计时器,在观察结束时停止它)

  • ObservationFilter - 在 Observation 停止之前修改 Context(例如添加一个高基数的键值对,表示云服务器区域)

  • ObservationPredicate - 禁用创建 Observation 的条件(例如不创建具有给定键值对的观察)

  • Context(实际上是 Observation.Context)- 附加到 Observation 的可变映射,在处理程序之间传递(这样你可以在不使用任何线程本地变量的情况下传递状态)

  • ObservationConvention - 将 Observation 生命周期(开始、停止、打开作用域)与添加元数据(例如观察名称、键值对)分离的方式。这样,观察的命名和元数据处理就变成了一个配置问题(例如,添加键值对不需要更改检测代码,而是更改约定)

使用流程

┌──────────────────┐┌─────────────────┐┌────────────────────┐┌───────┐┌─────────────────────┐
│ObservationHandler││ObservationFilter││ObservationPredicate││Context││ObservationConvention│
└┬─────────────────┘└┬────────────────┘└┬───────────────────┘└┬──────┘└┬────────────────────┘
┌▽───────────────────▽──────────────────▽┐ │ │
│ObservationRegistry │ │ │
└┬───────────────────────────────────────┘ │ │
┌▽────────────────────────────────────────────────────────────▽────────▽┐
│Observation │
└───────────────────────────────────────────────────────────────────────┘
none
  • ObservationHandlerObservationFilterObservationPredicate 会被注册到 ObservationRegistry

    • ObservationHandler 可以组合在一起(例如通过 FirstMatchingCompositeObservationHandler - 当你将多个相同类型的处理器分组时,这很有用,例如 TracingHandlerMeterHandler
  • 创建 Observation 时,ObservationRegistryContext 是必需的

    • 你可以通过名称、ObservationRegistryContext 创建 Observation,或者通过 ObservationRegistryObservationConvention 创建
  • Observation 调用其生命周期方法时,所有通过 supportsContext 检查的 ObservationHandlers 将执行其生命周期方法(例如,如果一个处理器在 supportsContext 中有 instanceof SenderContext 检查,那么它只会针对这种类型的上下文被调用)