60. 使用注解 ManagementSpan

您可以使用各种 Comments 来 ManagementSpan。

60.1 Rationale

有很多理由来 Management 带有注解的 Span,包括:

  • 与 API 无关的方法可以与 Span 进行协作。使用 Comments 使用户可以添加到 Span,而 Spanapi 不依赖库。这样,Sleuth 可以更改其核心 API,以减少对用户代码的影响。

  • 减少基本跨距操作的表面积。如果没有此功能,则必须使用 span api,该 api 的生命周期命令可能无法正确使用。通过仅公开范围,标记和日志功能,您可以进行协作而不会意外中断 Span 生命周期。

  • 与运行时生成的代码协作。使用诸如 Spring Data 和 Feign 之类的库,可以在运行时生成接口的实现。因此,对象的 Span 包裹是乏味的。现在,您可以在接口和这些接口的参数上提供 Comments。

60.2 创建新的 Span

如果您不想手动创建本地范围,则可以使用@NewSpanComments。此外,我们提供@SpanTag注解以自动方式添加标签。

现在我们可以考虑一些用法示例。

@NewSpan
void testMethod();

在不带任何参数的情况下对方法进行 Comments 会导致创建一个新的 Span,该 Span 的名称等于带 Comments 的方法名称。

@NewSpan("customNameOnTestMethod4")
void testMethod4();

如果您在注解中提供值(直接或通过设置name参数),则创建的 Span 将提供的值作为名称。

// method declaration
@NewSpan(name = "customNameOnTestMethod5")
void testMethod5(@SpanTag("testTag") String param);

// and method execution
this.testBean.testMethod5("test");

您可以将名称和标签结合在一起。让我们专注于后者。在这种情况下,带 Comments 的方法的参数运行时值的值将成为标记的值。在我们的示例中,标记键是testTag,标记值是test

@NewSpan(name = "customNameOnTestMethod3")
@Override
public void testMethod3() {
}

您可以在类和接口上都放置@NewSpanComments。如果您重写接口的方法并为@NewSpan注解提供不同的值,则最具体的将获胜(在这种情况下设置customNameOnTestMethod3)。

60.3 连续 Span

如果要将标记和 Comments 添加到现有范围,则可以使用@ContinueSpanComments,如以下示例所示:

// method declaration
@ContinueSpan(log = "testMethod11")
void testMethod11(@SpanTag("testTag11") String param);

// method execution
this.testBean.testMethod11("test");
this.testBean.testMethod13();

(请注意,与@NewSpanComments 相反,您还可以使用log参数添加日志.)

这样,Span 将 continue,并且:

  • 创建名为testMethod11.beforetestMethod11.after的日志条目。

  • 如果引发异常,还将创建名为testMethod11.afterFailure的日志条目。

  • 将创建一个键为testTag11且值为test的标签。

60.4 高级标记设置

有 3 种不同的方法可以将标签添加到 Span。它们全部由SpanTagComments 控制。优先级如下:

  • 尝试使用TagValueResolver类型的 bean 和提供的名称。

  • 如果未提供 Bean 名称,请尝试评估表达式。我们搜索一个TagValueExpressionResolver bean。默认实现使用 SPEL 表达式解析。 重要 您只能从 SPEL 表达式中引用属性。由于安全限制,不允许执行方法。

  • 如果找不到任何要求值的表达式,请返回该参数的toString()值。

60.4.1 自定义提取器

用于以下方法的标记的值是通过TagValueResolver接口的实现来计算的。必须将其类名作为resolver属性的值传递。

考虑以下带 Comments 的方法:

@NewSpan
public void getAnnotationForTagValueResolver(
		@SpanTag(key = "test", resolver = TagValueResolver.class) String test) {
}

现在进一步考虑以下TagValueResolver bean 实现:

@Bean(name = "myCustomTagValueResolver")
public TagValueResolver tagValueResolver() {
	return parameter -> "Value from myCustomTagValueResolver";
}

前面的两个示例导致将标签值设置为Value from myCustomTagValueResolver

60.4.2 为值解析表达式

考虑以下带 Comments 的方法:

@NewSpan
public void getAnnotationForTagValueExpression(
		@SpanTag(key = "test", expression = "'hello' + ' characters'") String test) {
}

没有对TagValueExpressionResolver的自定义实现导致对 SPEL 表达式的求值,并且在 Span 上设置了值为4 characters的标签。如果要使用其他表达式解析机制,则可以创建自己的 bean 实现。

60.4.3 使用 toString()方法

考虑以下带 Comments 的方法:

@NewSpan
public void getAnnotationForArgumentToString(@SpanTag("test") Long param) {
}

15的值运行前面的方法会导致设置一个 String 值为"15"的标签。