圖片
我們的需求是這樣的:
圖片
假設現(xiàn)在有三個服務:ServiceA、ServiceB、ServiceC。
ServiceA 對外提供了一個 http 接口 request,在這個接口會調用 ServiceB 的 order 訂單接口創(chuàng)建訂單,同時 serviceB 調用 serviceC 的 pay 接口。
圖片
整個調用關系如上圖所示。
默認情況下 span 中的 attribute 會記錄當前 span 的一些信息,比如:
圖片
這些都是當前一些當前 span 內(nèi)置的信息,比如當前 gRPC 接口的一些基本數(shù)據(jù):服務名、ip、端口等信息。
但這里并沒有上游的一些信息,雖然我們可以通過 Jaeger 的樹狀圖得知上游是哪個應用調用過來的,但是一旦某個 span 下有多個子 span 的調用,就沒辦法很直觀知道這個子 span 的上游是由誰發(fā)起的調用。
比如如下這個鏈路:
圖片
當一個調用鏈非常長,同時也非常復雜時,沒辦法第一時間知道某一個 span 的上游到底是誰發(fā)起的,需要手動一層層的去折疊,或者全靠眼睛去找。
圖片
為此我們希望的效果是可以通過給每一個子 span 中加入兩個 attribute,來標明它的父調用來源。
比如在 serviceB 中的所有 span 中都會加上兩個標簽:來源是 serviceA,同時是 serviceA 的 request 接口發(fā)起的請求。
而在 serviceC 中同樣可以知道來源是 serviceB 的 Order 接口發(fā)起的調用。
我啟動了三個 demo 應用,分別是 create1,create2,create3.
create1 中會提供一個 request 接口,在這里面調用 create2 的 create2 接口,create2 的接口里接著調用 create3 的 create3 接口。
create1:
@RequestMapping("/request") public String request(@RequestParam String name) { HelloRequest request = HelloRequest.newBuilder() .setName(name) .build(); log.info("request: {}", request); String message = myServiceStub.create2(request).getMessage(); Executors.newFixedThreadPool(1).execute(() -> { myServiceStub.create2(request).getMessage(); }); return message; }
create2:
@Override public void create2(HelloRequest request, StreamObserver<HelloReply> responseObserver) { HelloReply reply = HelloReply.newBuilder() .setMessage("Create2 ==> " + request.getName()) .build(); log.info("Create2: {}", reply.getMessage()); myMethod(request.getName()); myServiceStub.create3(request); responseObserver.onNext(reply); responseObserver.onCompleted(); }
create3:
@Override public void create3(HelloRequest request, StreamObserver<HelloReply> responseObserver) { HelloReply reply = HelloReply.newBuilder() .setMessage("Create3 ==> " + request.getName()) .build(); log.info("Create3: {}", reply.getMessage()); myMethod(request.getName()); responseObserver.onNext(reply); responseObserver.onCompleted(); }
java -javaagent:opentelemetry-javaagent-2.4.0-SNAPSHOT.jar /-Dotel.javaagent.extensinotallow=otel-extensions-custom-context-1.0-SNAPSHOT.jar /-Dotel.traces.exporter=otlp /-Dotel.logs.exporter=none /-Dotel.service.name=create2 /-Dotel.exporter.otlp.protocol=grpc /-Dotel.propagators=tracecontext,baggage,demo /-Dotel.exporter.otlp.endpoint=http://127.0.0.1:5317 / -jar target/demo-0.0.1-SNAPSHOT.jar --spring.application.name=create2 --server.port=9191 --grpc.server.port=9292 --grpc.client.myService.address=static://127.0.0.1:9393
只是每個應用都需要使用我這邊單獨打的 agent 包以及一個 extension(tel-extensions-custom-context-1.0-SNAPSHOT.jar) 才能生效。
最終的效果如下:
圖片
在講具體的實現(xiàn)之前需要先了解幾個 Trace 中的概念,在這里主要用到的是一個稱為 Baggage 的對象。
在之前的文章中其實提到過它的原理以及使用場景:從 Dapper 到 OpenTelemetry:分布式追蹤的演進之旅
圖片
Baggage 的中文翻譯是:包裹
本文鏈接:http://www.tebozhan.com/showinfo-26-96995-0.htmlOpenTelemetry 深度定制:跨服務追蹤的實戰(zhàn)技巧
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com