OpenTelemetry笔记(6)-AttributesExtractor

概念

AttributesExtractor 是对 Span 的 setAttribute 方法进行业务的一种抽象封装

业务属性跟踪方式

使用 Span 的 setAttribute

1
2
3
4
5
6
7
8
9
10
11
12
private static void doLogic()
{
User user=new User();
user.setId(1L);
user.setName("curryzxh");
user.setPhone("10010");
UserService service=new UserService();
Span.current().setAttribute(AttributeKey.longKey("uid"),user.getId());
Span.current().setAttribute(AttributeKey.stringKey("name"),user.getName());
boolean bSave=service.saveUser(user);
Span.current().setAttribute(AttributeKey.booleanKey("result"),bSave);
}

使用 AttributesExtractor

AttributesExtractor 是 instrumentation 中非常重要的概念,每个组件基本都需要自定义实现 AttributesExtractor

接口定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface AttributesExtractor<REQUEST, RESPONSE> {

void onStart(AttributesBuilder attributes, REQUEST request);


void onEnd(
AttributesBuilder attributes,
REQUEST request,
@Nullable RESPONSE response,
@Nullable Throwable error);

default <T> void set(AttributesBuilder attributes, AttributeKey<T> key, @Nullable T value) {
if (value != null) {
attributes.put(key, value);
}
}

接口实现

1
2
3
4
5
6
7
8
9
10
11
12
13
public class UserAttributesExtractor implements AttributesExtractor<User,Boolean> {

@Override
public void onStart(AttributesBuilder attributes, User user) {
set(attributes, AttributeKey.longKey("uid"),user.getId());
set(attributes, AttributeKey.stringKey("name"),user.getName());
}

@Override
public void onEnd(AttributesBuilder attributes, User user, @Nullable Boolean aBoolean, @Nullable Throwable error) {
set(attributes,AttributeKey.booleanKey("result"),aBoolean);
}
}

调用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class UserService {

UserAttributesExtractor extractor=new UserAttributesExtractor();

public Boolean saveUser(User user) {
AttributesBuilder attributes = Attributes.builder();

extractor.onStart(attributes, user);

Boolean bSave = internalSaveUser(user);
extractor.onEnd(attributes, user, bSave, null);
Span.current().setAllAttributes(attributes.build());
return bSave;
}

private Boolean internalSaveUser(User user)
{
//todo
return true;
}
}

使用 AttributesExtractor 实现 AOP

切面对象定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
final class JoinPointRequest {
private final JoinPoint joinPoint;
private final Method method;
private final WithSpan annotation;

JoinPointRequest(JoinPoint joinPoint) {
this.joinPoint = joinPoint;
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
this.method = methodSignature.getMethod();
this.annotation = this.method.getDeclaredAnnotation(WithSpan.class);
}

Method method() {
return method;
}

WithSpan annotation() {
return annotation;
}

Object[] args() {
return joinPoint.getArgs();
}
}

AttributesExtractor 接口实现

其有 3 个入参

  • MethodExtractor:获取对象要调用的方法
  • ParameterAttributeNamesExtractor:获取方法调用的参数名称
  • MethodArgumentsExtractor:获取方法的参数值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public final class MethodSpanAttributesExtractor<REQUEST, RESPONSE>
implements AttributesExtractor<REQUEST, RESPONSE> {

private final MethodExtractor<REQUEST> methodExtractor;
private final MethodArgumentsExtractor<REQUEST> methodArgumentsExtractor;
private final ParameterAttributeNamesExtractor parameterAttributeNamesExtractor;

public static <REQUEST, RESPONSE> MethodSpanAttributesExtractor<REQUEST, RESPONSE> newInstance(
MethodExtractor<REQUEST> methodExtractor,
ParameterAttributeNamesExtractor parameterAttributeNamesExtractor,
MethodArgumentsExtractor<REQUEST> methodArgumentsExtractor) {

return new MethodSpanAttributesExtractor<>(
methodExtractor,
parameterAttributeNamesExtractor,
methodArgumentsExtractor);
}

@Override
public void onStart(AttributesBuilder attributes, REQUEST request) {
Method method = methodExtractor.extract(request);
AttributeBindings bindings = cache.computeIfAbsent(method, this::bind);
if (!bindings.isEmpty()) {
Object[] args = methodArgumentsExtractor.extract(request);
bindings.apply(attributes::put, args);
}
}

@Override
public void onEnd(
AttributesBuilder attributes,
REQUEST request,
@Nullable RESPONSE response,
@Nullable Throwable error) {}

调用示例

1
2
3
4
MethodSpanAttributesExtractor.newInstance(
JoinPointRequest::method,
new WithSpanAspectParameterAttributeNamesExtractor(),
JoinPointRequest::args))