On this page
58. 使用 Annotations 管理 Spans
您可以使用各种注释管理 spans。
58.1 基本原理
使用 annotations 管理 spans 有很多很好的理由,包括:
API-agnostic 表示与 span 合作。使用 annotations 可以让用户在 span api 上添加没有 library 依赖的 span。这样做可以让 Sleuth 更改其核心 API,从而减少对用户 code 的影响。
减少了基本 span 操作的表面积。如果没有此 feature,则必须使用 span api,它具有可能无法正确使用的生命周期命令。通过仅公开范围,标记和 log 功能,您可以进行协作,而不会意外地破坏 span 生命周期。
与运行时协作生成 code。使用诸如 Spring Data 和 Feign 之类的 libraries,接口的 implementation 在运行时生成。因此,span 包裹 objects 是乏味的。现在,您可以通过接口和这些接口的 arguments 提供 annotations。
58.2 创造新的 Spans
如果您不想手动创建本地 spans,则可以使用@NewSpan
annotation。此外,我们提供@SpanTag
annotation 以自动方式添加标签。
现在我们可以考虑一些使用示例。
@NewSpan
void testMethod();
在没有任何参数的情况下注释该方法会导致 creating 一个新的 span,其 name 等于带注释的方法 name。
@NewSpan("customNameOnTestMethod4")
void testMethod4();
如果在 annotation 中提供 value(直接或通过设置name
参数),则创建的 span 将提供的 value 作为 name。
// method declaration
@NewSpan(name = "customNameOnTestMethod5")
void testMethod5(@SpanTag("testTag") String param);
// and method execution
this.testBean.testMethod5("test");
您可以将 name 和标记结合使用。让我们关注后者。在这种情况下,带注释的方法的参数 runtime value 的 value 将成为标记的 value。在我们的 sample 中,标签 key 是testTag
,标签 value 是test
。
@NewSpan(name = "customNameOnTestMethod3")
@Override
public void testMethod3() {
}
您可以将@NewSpan
annotation 放在 class 和接口上。如果覆盖接口的方法并为@NewSpan
annotation 提供不同的 value,则最具体的一个获胜(在这种情况下设置为customNameOnTestMethod3
)。
58.3 继续 Spans
如果要向现有的 span 添加标签和 annotations,可以使用@ContinueSpan
annotation,如下面的示例所示:
// method declaration
@ContinueSpan(log = "testMethod11")
void testMethod11(@SpanTag("testTag11") String param);
// method execution
this.testBean.testMethod11("test");
this.testBean.testMethod13();
(注意,与@NewSpan
annotation 相比,您还可以使用log
parameter.)添加日志
这样,span 继续下去:
创建名为
testMethod11.before
和testMethod11.after
的日志条目。如果抛出 exception,则还会创建名为
testMethod11.afterFailure
的 log 条目。创建 key 为
testTag11
且 value 为test
的标记。
58.4 高级标签设置
有三种不同的方法可以向 span 添加标签。所有这些都由SpanTag
annotation 控制。优先顺序如下:
尝试使用
TagValueResolver
类型的 bean 和提供的 name。如果尚未提供 bean name,请尝试计算表达式。我们搜索
TagValueExpressionResolver
bean。默认 implementation 使用 SPEL 表达式解析。 重要您只能从 SPEL 表达式 reference properties。由于安全性限制,不允许执行方法。如果我们找不到要评估的表达式,_return 参数的
toString()
value。
58.4.1 自定义提取器
以下方法的标记的 value 由TagValueResolver
接口的 implementation 计算。它的 class name 必须作为resolver
属性的 value 传递。
请考虑以下带注释的方法:
@NewSpan
public void getAnnotationForTagValueResolver(@SpanTag(key = "test", resolver = TagValueResolver.class) String test) {
}
现在进一步考虑以下TagValueResolver
bean implementation:
@Bean(name = "myCustomTagValueResolver")
public TagValueResolver tagValueResolver() {
return parameter -> "Value from myCustomTagValueResolver";
}
前面两个示例导致将标签 value 设置为等于Value from myCustomTagValueResolver
。
58.4.2 解析 Value 的表达式
请考虑以下带注释的方法:
@NewSpan
public void getAnnotationForTagValueExpression(@SpanTag(key = "test", expression = "'hello' + ' characters'") String test) {
}
没有TagValueExpressionResolver
的自定义_impleration 导致 SPEL 表达式的 evaluation,并且 span 上设置了 value 为4 characters
的标记。如果要使用其他一些表达式解析机制,可以创建自己的 bean 实现 bean。
58.4.3 使用 toString()方法
请考虑以下带注释的方法:
@NewSpan
public void getAnnotationForArgumentToString(@SpanTag("test") Long param) {
}
使用_val运行上述方法会导致设置 String value 为"15"
的标记。