Zipkin Brave源碼解讀-Tracer(全鏈路跟蹤埋點(diǎn))(二)

Tracer 這個(gè)類主要用于做 Span 的相關(guān)操作。
核心方法有一下幾個(gè):
public Span newChild(TraceContext parent);//新建一個(gè)子跨度黑竞,有parent
public Span newTrace();//新建一個(gè)跨度捕发,無(wú)parent
public Span nextSpan();//新建一個(gè)跨度,根據(jù)當(dāng)前作用域判斷是新建自跨度還是新建無(wú)關(guān)聯(lián)的跨度
public final Span joinSpan(TraceContext context);//加入一個(gè)跨度很魂,這種情況一般是用于 Client -> Server 訪問(wèn)時(shí)出現(xiàn)的扎酷,在客戶端有一條trace記錄,在服務(wù)端進(jìn)行trace記錄時(shí)候莫换,使用了該方法,服務(wù)端會(huì)生成一條有同樣trace ID的記錄骤铃,合并客戶端與服務(wù)端這兩條trace信息可以則可以得到一條完整的trace日志拉岁。
public SpanInScope withSpanInScope(@Nullable Span span);//定義一個(gè)跨度的作用域,就是TreadLocal的原理惰爬,在該作用域下喊暖,你可以隨時(shí)獲得當(dāng)前 TraceContext

接下來(lái)一個(gè)個(gè)看:

public Span nextSpan() {
//獲取當(dāng)前 TraceContext
    TraceContext parent = currentTraceContext.get();
//若存在則新建一個(gè)自跨度,否則新建一個(gè)無(wú)關(guān)聯(lián)跨度
    return parent != null ? newChild(parent) : newTrace();
  }
public Span newTrace() {
    return _toSpan(newRootContext());//直接新建一個(gè)TraceContext撕瞧,新建一個(gè)span
  }

Span _toSpan(TraceContext decorated) {
    if (isNoop(decorated)) return new NoopSpan(decorated);
    // 獲取或者創(chuàng)建一個(gè)掛起的跨度
    //這里多了一個(gè)新建的對(duì)象叫 PendingSpan 陵叽,用于收集一條trace上暫時(shí)被掛起的未完成的span
    PendingSpan pendingSpan = pendingSpans.getOrCreate(decorated, false);
    //新建一個(gè)跨度(RealSpan是Span的一個(gè)實(shí)現(xiàn))
    return new RealSpan(decorated, pendingSpans, pendingSpan.state(), pendingSpan.clock(),
        finishedSpanHandler);
  }
//可看出 nextSpan 就是調(diào)用 newChild 或者 newTrace而已
public Span nextSpan() {
    TraceContext parent = currentTraceContext.get();
    return parent != null ? newChild(parent) : newTrace();
  }
//這個(gè)方法注解足夠,直接看就行了
  public final Span joinSpan(TraceContext context) {
    if (context == null) throw new NullPointerException("context == null");
    if (!supportsJoin) return newChild(context);
    int flags = InternalPropagation.instance.flags(context);
    if (alwaysSampleLocal && (flags & FLAG_SAMPLED_LOCAL) != FLAG_SAMPLED_LOCAL) {
      flags |= FLAG_SAMPLED_LOCAL;
    }
    // If we are joining a trace, we are sharing IDs with the caller
    // If the sampled flag was left unset, we need to make the decision here
    if ((flags & FLAG_SAMPLED_SET) != FLAG_SAMPLED_SET) { // cheap check for not yet sampled
      // then the caller didn't contribute data
      flags = InternalPropagation.sampled(sampler.isSampled(context.traceId()), flags);
    } else if ((flags & FLAG_SAMPLED) == FLAG_SAMPLED) {
      // we are recording and contributing to the same span ID
      flags = flags | FLAG_SHARED;
    }
    context = InternalPropagation.instance.newTraceContext(
        flags | FLAG_LOCAL_ROOT,
        context.traceIdHigh(),
        context.traceId(),
        context.spanId(), // local root
        context.parentIdAsLong(),
        context.spanId(),
        context.extra()
    );
   //返回一個(gè)跨度丛版,使用 propagationFactory.decorate() 裝飾一個(gè)跨度巩掺,實(shí)際上該出的代碼什么也沒(méi)裝飾,直接返回 context
    return _toSpan(propagationFactory.decorate(context));
  }
//新建作用域就一句代碼页畦,返回一個(gè) SpanInScope對(duì)象胖替,該對(duì)象用于定義一個(gè)作用域,調(diào)用它的 close 方法即可結(jié)束作用域
public SpanInScope withSpanInScope(@Nullable Span span) {
    return new SpanInScope(currentTraceContext.newScope(span != null ? span.context() : null));
  }

//看看currentTraceContext.newScope 做了什么
//首先它擁有一個(gè)內(nèi)部對(duì)象, local独令,就是一個(gè) TreadLocal 對(duì)象端朵,所以可以解釋作用域?yàn)槭裁纯梢噪S時(shí)獲取到所需的 TraceContext
final ThreadLocal<TraceContext> local;

public Scope newScope(@Nullable TraceContext currentSpan) {
//獲取之前作用域的 context
    final TraceContext previous = local.get();
//設(shè)置當(dāng)前作用域的 context
    local.set(currentSpan);
//接下來(lái)定義一個(gè)作用域的內(nèi)部類,它的close方法將之前作用域的 context 設(shè)置為當(dāng)前的
//也就是當(dāng)結(jié)束一個(gè)作用域的時(shí)候燃箭,將上一個(gè)作用域還原回來(lái)冲呢,如此控制
    class ThreadLocalScope implements Scope {
      @Override public void close() {
        local.set(previous);
      }
    }
//新建一個(gè)作用域
    Scope result = new ThreadLocalScope();
//調(diào)用方法裝飾這個(gè)作用域并返回(利用已設(shè)置好的裝飾器)
    return decorateScope(currentSpan, result);
  }


protected Scope decorateScope(@Nullable TraceContext currentSpan, Scope scope) {
    int length = scopeDecorators.size();
//遍歷裝飾器,對(duì)作用域進(jìn)行裝飾包裝招狸,可忽略這部分拓展敬拓,一般使用并不會(huì)用上裝飾器,有興趣的同學(xué)可以研究下該部分
    for (int i = 0; i < length; i++) {
      scope = scopeDecorators.get(i).decorateScope(currentSpan, scope);
    }
    return scope;
  }

到此為止瓢颅,Tracer的基本工作已經(jīng)大體清楚恩尾。

下一章將解讀跨度( Span )的內(nèi)容。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挽懦,一起剝皮案震驚了整個(gè)濱河市翰意,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌信柿,老刑警劉巖冀偶,帶你破解...
    沈念sama閱讀 221,406評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異渔嚷,居然都是意外死亡进鸠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門形病,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)客年,“玉大人,你說(shuō)我怎么就攤上這事漠吻×抗希” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 167,815評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵途乃,是天一觀的道長(zhǎng)绍傲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)耍共,這世上最難降的妖魔是什么烫饼? 我笑而不...
    開(kāi)封第一講書人閱讀 59,537評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮试读,結(jié)果婚禮上杠纵,老公的妹妹穿的比我還像新娘。我一直安慰自己钩骇,他們只是感情好淡诗,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布骇塘。 她就那樣靜靜地躺著,像睡著了一般韩容。 火紅的嫁衣襯著肌膚如雪款违。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 52,184評(píng)論 1 308
  • 那天群凶,我揣著相機(jī)與錄音插爹,去河邊找鬼。 笑死请梢,一個(gè)胖子當(dāng)著我的面吹牛赠尾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播毅弧,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼气嫁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了够坐?” 一聲冷哼從身側(cè)響起寸宵,我...
    開(kāi)封第一講書人閱讀 39,668評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎元咙,沒(méi)想到半個(gè)月后梯影,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,212評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡庶香,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評(píng)論 3 340
  • 正文 我和宋清朗相戀三年甲棍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赶掖。...
    茶點(diǎn)故事閱讀 40,438評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡感猛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出奢赂,到底是詐尸還是另有隱情陪白,我是刑警寧澤,帶...
    沈念sama閱讀 36,128評(píng)論 5 349
  • 正文 年R本政府宣布呈驶,位于F島的核電站拷泽,受9級(jí)特大地震影響疫鹊,放射性物質(zhì)發(fā)生泄漏袖瞻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評(píng)論 3 333
  • 文/蒙蒙 一拆吆、第九天 我趴在偏房一處隱蔽的房頂上張望聋迎。 院中可真熱鬧,春花似錦枣耀、人聲如沸霉晕。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,279評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)牺堰。三九已至拄轻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間伟葫,已是汗流浹背恨搓。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,395評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留筏养,地道東北人斧抱。 一個(gè)月前我還...
    沈念sama閱讀 48,827評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像渐溶,于是被迫代替她去往敵國(guó)和親辉浦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評(píng)論 2 359