Zipkin Jedis 链路追踪采集器

589 阅读1分钟

简介

Zipkin 的 brave 库为 Java 开发者提供了各种常用组件链路追踪采集器 GitHub - openzipkin/brave: Java distributed tracing implementation compatible with Zipkin backend services.

但是在 instrumentation 中没有 Jedis 相关的采集器,因此我们得自己开发。

实践

废话不多说,直接开始,首先基于 brave 开发,版本如下:

brave:5.13.2

首先我们使用 Jedis 库时都是通过 Jedis 类操作,因此我们可以从 Jedis 类这个入口进行增强,因此选择装饰器模式,我们以 2.6.3 版本的 jedis 为例。部分代码如下:

public class TraceableJedis263 extends Jedis {

    private final Jedis delegate;
    private final JedisTracerHelper helper;

    @Override
    public Long append(byte[] key, byte[] value) {
		// 开启一个跨度
        Span span = helper.startNextJedisSpan("append", key);
        span.tag("value", Arrays.toString(value));
		// 委托给原先的 Jedis 类处理,处理在过程是在独立作用域内的
        return helper.executeInScope(span, () -> delegate.append(key, value));
    }

		...  ...
}

下面来看 startNextJedisSpan 和 executeInScope 这两个关键方法

public Span startNextJedisSpan(String command, byte[] key) {
	// 根据当前上下文生成新的 span
	Span span = tracer.nextSpan();
	span.kind(Span.Kind.CLIENT);  
	// span 名称为 jedis 方法名
	span.name(command);  
	span.remoteServiceName("reids");
	span.tag(KEY, Arrays.toString(key));
	return span;
}

public <T> T executeInScope(Span span, Supplier<T> supplier) {
	try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
		return supplier.get();
	} catch (RuntimeException | Error e) {
		span.error(e);
		throw e;
	} finally {
		span.finish();
	}
}

是不是很简单,一个 jedis 的链路采集库就制作好了,下面让我们看看如何使用。

// tracer 构造比较复杂,一般作为单例,例如 Spring Bean 注入
Jedis jedis = new TraceableJedis263(new Jedis("localhost"), new JedisTracerHelper(tracer));
jedis.get("key");

如果使用 spring 进行开发,可以通过例如 BeanPostProcessor 对 Jedis 进行包装,从而做到业务透明。

上述代码现维护到了 github,目前代码还比较简单,欢迎大家一起扩展维护,提供更多开箱即用的采集库。

GitHub - freshchen/zipkin-instrumentation: openzipkin 官方 instrumentation 的补充。目前包含 jedis、redisson