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
如果您不想手动创建本地范围,则可以使用@NewSpan
Comments。此外,我们提供@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() {
}
您可以在类和接口上都放置@NewSpan
Comments。如果您重写接口的方法并为@NewSpan
注解提供不同的值,则最具体的将获胜(在这种情况下设置customNameOnTestMethod3
)。
60.3 连续 Span
如果要将标记和 Comments 添加到现有范围,则可以使用@ContinueSpan
Comments,如以下示例所示:
// method declaration
@ContinueSpan(log = "testMethod11")
void testMethod11(@SpanTag("testTag11") String param);
// method execution
this.testBean.testMethod11("test");
this.testBean.testMethod13();
(请注意,与@NewSpan
Comments 相反,您还可以使用log
参数添加日志.)
这样,Span 将 continue,并且:
-
创建名为
testMethod11.before
和testMethod11.after
的日志条目。 -
如果引发异常,还将创建名为
testMethod11.afterFailure
的日志条目。 -
将创建一个键为
testTag11
且值为test
的标签。
60.4 高级标记设置
有 3 种不同的方法可以将标签添加到 Span。它们全部由SpanTag
Comments 控制。优先级如下:
-
尝试使用
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"
的标签。