赞
踩
上一篇博文中,我们了解了Brave框架的基本使用,并且分析了跟Tracer相关的部分源代码。这篇博文我们接着看看Tracing的初始化及相关类的源代码
- public class TraceDemo {
-
- public static void main(String[] args) {
- Sender sender = OkHttpSender.create("http://localhost:9411/api/v2/spans");
- AsyncReporter asyncReporter = AsyncReporter.builder(sender)
- .closeTimeout(500, TimeUnit.MILLISECONDS)
- .build(SpanBytesEncoder.JSON_V2);
-
- Tracing tracing = Tracing.newBuilder()
- .localServiceName("tracer-demo")
- .spanReporter(asyncReporter)
- .propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "user-name"))
- .currentTraceContext(ThreadContextCurrentTraceContext.create())
- .build();
- Tracer tracer = tracing.tracer();
- // ...
- }
- }
Brave中各个组件创建大量使用的builder设计模式,Tacing也不例外,先来看下Tracing.Builder
- public static final class Tracing.Builder {
- String localServiceName;
- Endpoint localEndpoint;
- Reporter<zipkin2.Span> reporter;
- Clock clock;
- Sampler sampler = Sampler.ALWAYS_SAMPLE;
- CurrentTraceContext currentTraceContext = CurrentTraceContext.Default.inheritable();
- boolean traceId128Bit = false;
- boolean supportsJoin = true;
- Propagation.Factory propagationFactory = Propagation.Factory.B3;
-
- public Tracing build() {
- if (clock == null) clock = Platform.get();
- if (localEndpoint == null) {
- localEndpoint = Platform.get().localEndpoint();
- if (localServiceName != null) {
- localEndpoint = localEndpoint.toBuilder().serviceName(localServiceName).build();
- }
- }
- if (reporter == null) reporter = Platform.get();
- return new Default(this);
- }
-
- Builder() {
- }
- }
Tracing中依赖的几个重要类
前面TraceDemo例子中,我们初始化Tracing时设置了localServiceName,spanReporter,propagationFactory,currentTraceContext 其中spanReporter为AsyncReporter我们上一篇已经分析过其源代码了,在build方法中可以看到,其默认实现是Platform,默认会将Span信息用logger进行输出,而不是上报到zipkin中
- @Override public void report(zipkin2.Span span) {
- if (!logger.isLoggable(Level.INFO)) return;
- if (span == null) throw new NullPointerException("span == null");
- logger.info(span.toString());
- }
采样器,根据traceId来判断是否一条trace需要被采样,即上报到zipkin
- public abstract class Sampler {
-
- public static final Sampler ALWAYS_SAMPLE = new Sampler() {
- @Override public boolean isSampled(long traceId) {
- return true;
- }
-
- @Override public String toString() {
- return "AlwaysSample";
- }
- };
-
- public static final Sampler NEVER_SAMPLE = new Sampler() {
- @Override public boolean isSampled(long traceId) {
- return false;
- }
-
- @Override public String toString() {
- return "NeverSample";
- }
- };
-
- /** Returns true if the trace ID should be measured. */
- public abstract boolean isSampled(long traceId);
-
- /**
- * Returns a sampler, given a rate expressed as a percentage.
- *
- * <p>The sampler returned is good for low volumes of traffic (<100K requests), as it is precise.
- * If you have high volumes of traffic, consider {@link BoundarySampler}.
- *
- * @param rate minimum sample rate is 0.01, or 1% of traces
- */
- public static Sampler create(float rate) {
- return CountingSampler.create(rate);
- }
- }
Sampler.ALWAYS_SAMPLE 永远需要被采样 Sampler.NEVER_SAMPLE 永远不采样
Sampler还有一个实现类 CountingSampler可以指定采样率,如CountingSampler.create(0.5f)则对50%的请求数据进行采样,里面用到了一个算法,这里不展开分析了。
包含TraceId,SpanId,是否采样等数据
在Tracer的newRootContext方法中有这样一段代码,通过newBuilder来构建TraceContext对象
- TraceContext newRootContext(SamplingFlags samplingFlags, List<Object> extra) {
- long nextId = Platform.get().randomLong();
- Boolean sampled = samplingFlags.sampled();
- if (sampled == null) sampled = sampler.isSampled(nextId);
- return TraceContext.newBuilder()
- .sampled(sampled)
- .traceIdHigh(traceId128Bit ? Platform.get().nextTraceIdHigh() : 0L).traceId(nextId)
- .spanId(nextId)
- .debug(samplingFlags.debug())
- .extra(extra).build();
- }
TraceContext中有以下一些属性
还有继承自SamplingFlags的两个属性
TraceContext中还定义了两个接口Inj
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。