11. 使用注解管理跨度
您可以使用各种注释来管理跨度。
11.1. 背景
使用注解管理跨度有诸多优点,包括:
-
API-agnostic 表示可以与一个 span 协作。使用注解可以让用户在不依赖 span API 的情况下向 span 添加信息。 这样做让 Sleuth 能够将其核心 API 进行调整,从而对用户代码造成更小的影响。
-
减少基本跨度操作的表面区域。如果没有此功能,必须使用跨度api,该api具有可能被误用的生命周期命令。 通过仅公开范围、标记和日志功能,您可以在不意外破坏跨度生命周期的情况下进行协作。
-
与运行时生成的代码进行协作。使用Spring Data和Feign等库,在接口的实现是在运行时生成的。 因此,对象的跨度包装很繁琐。 现在,您可以在接口及其参数上提供注释。
11.2.创建新的跨度
如果不想手动创建本地跨度,可以使用@NewSpan注释。
另外,我们提供了@SpanTag注释,可以自动添加标记。
现在我们可以考虑一些用法示例。
@NewSpan
void testMethod();
使用没有任何参数的方法注释可创建新的跨度,其名称等于注释方法名。
@NewSpan("customNameOnTestMethod4")
void testMethod4();
如果您在注释中提供值(直接或通过设置name参数),则创建的跨度具有提供的值作为名称。
// method declaration
@NewSpan(name = "customNameOnTestMethod5")
void testMethod5(@SpanTag("testTag") String param);
// and method execution
this.testBean.testMethod5("test");
你可以结合名称和一个标签。让我们重点在后者。
在这种情况下,注解方法参数的运行时值将成为标签的值。在我们的示例中,标签键是testTag,标签值是test。
@NewSpan(name = "customNameOnTestMethod3")
@Override
public void testMethod3() {
}
你可以在类和接口上放置@NewSpan注解。
如果你重写接口的方法并为@NewSpan注解提供不同的值,那么最具体的值获胜(在这种情况下customNameOnTestMethod3被设置)。
11.3。继续跨度
如果您想为现有跨度添加标签和注释,可以使用@ContinueSpan注释,如以下示例所示:
// method declaration
@ContinueSpan(log = "testMethod11")
void testMethod11(@SpanTag("testTag11") String param);
// method execution
this.testBean.testMethod11("test");
this.testBean.testMethod13();
(练传时,可以通过接发“120”参数,导入日志)
That way, the span gets continued and:
-
日志条目被命名为
testMethod11.before和testMethod11.after创建。 -
如果抛出异常,还会创建一个名为
testMethod11.afterFailure的日志条目。 -
创建了一个键为
testTag11,值为test的标签。
<h3>11.4. 高级标签设置</h3>
有3种不同的方式可以为span添加标签。所有的这些都由SpanTag注解控制。
优先级如下:
-
使用类型为
TagValueResolver且提供了名称的Bean尝试一下。 -
如果bean名称没有提供,尝试计算一个表达式。我们搜索
TagValueExpressionResolverbean。默认实现使用SPEL表达式解析。重要您只能从SPEL表达式引用属性。由于安全约束,不允许执行方法调用。 -
如果找不到要计算的表达式,那么就返回参数的
toString()值。
(自定义提取器) 11.4.1. 自定义提取器
The value of the tag for the following method is computed by an implementation of TagValueResolver interface.
Its class name has to be passed as the value of the resolver attribute.
请考虑以下注释方法:
@NewSpan
public void getAnnotationForTagValueResolver(
@SpanTag(key = "test", resolver = TagValueResolver.class) String test) {
}
现在进一步考虑以下TagValueResolverbean实现:
@Bean(name = "myCustomTagValueResolver")
public TagValueResolver tagValueResolver() {
return parameter -> "Value from myCustomTagValueResolver";
}
前面的两个示例会导致设置一个标签值等于 Value from myCustomTagValueResolver。
11.4.2. 解析值的表达式
请考虑以下注释方法:
@NewSpan
public void getAnnotationForTagValueExpression(@SpanTag(key = "test",
expression = "'hello' + ' characters'") String test) {
}
如果没有对TagValueExpressionResolver提供自定义实现,则会评估SPEL表达式,且在span上将值为4 characters的标记被设置。
如果你想要使用其他表达式解析机制,可以创建你自己的bean实现。
11.4.3. 使用 toString() 方法
请考虑以下注释方法:
@NewSpan
public void getAnnotationForArgumentToString(@SpanTag("test") Long param) {
}
使用值为 15 的前一方法将设置一个值为 "15" 的标签属性。