接入ARMS應用監控以後,ARMS探針對常見的Java架構進行了自動埋點,因此不需要修改任何代碼,就可以實現調用鏈資訊的採集。如果您需要在調用鏈資訊中,體現業務方法的執行情況,可以引入OpenTelemetry Java SDK,在業務代碼中增加自訂埋點。
ARMS探針支援的組件和架構,請參見ARMS應用監控支援的Java組件和架構。
前提條件
引入依賴
請先參考如下Maven代碼引入OpenTelemetry Java SDK。更多資訊,請參見OpenTelemetry官方文檔。
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-trace</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-bom</artifactId>
<version>1.23.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
ARMS對OpenTelemetry埋點的相容
名詞介紹
此處只介紹一些常用的名詞,其他名稱解釋,請參見OpenTelemetry Specification。
Span:一次請求的一個具體操作,比如遠程調用入口或者內部方法調用。
SpanContext:一次請求追蹤的上下文,包含traceId、spanId等資訊。
Attribute:Span的附加屬性欄位,用於記錄關鍵資訊。
Baggae:在整條鏈路上透傳的一些Key、Value資訊。
使用OpenTelemetry Java SDK
通過OpenTelemetry的SDK主要可以實現以下操作:
埋點產生Span。
為Span增加Attributes。
在鏈路上下文透傳Baggage。
擷取當前Trace上下文並列印traceId、spanId等。
此處通過一段範例程式碼示範如何使用OpenTelemetry SDK完成上述操作。
以下程式碼片段需要注意,最終擷取OpenTelemetry執行個體需要通過調用GlobalOpenTelemetry.get()方法擷取,不能直接使用上一步通過OpenTelemetry SDK手動構建的Opentelemetry執行個體。否則會導致在4.x版本探針中無法看到通過SDK埋點產生的Span資料。
@RestController
@RequestMapping("/ot")
public class OpenTelemetryController {
private Tracer tracer;
private ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
@PostConstruct
public void init() {
OpenTelemetrySdk.builder()
.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
.buildAndRegisterGlobal();
tracer = GlobalOpenTelemetry.get().getTracer("manual-sdk", "1.0.0");
ses.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Span span = tracer.spanBuilder("schedule")
.setAttribute("schedule.time", System.currentTimeMillis())
.startSpan();
try (Scope scope = span.makeCurrent()) {
System.out.println("scheduled!");
Thread.sleep(500L);
span.setAttribute("schedule.success", true);
System.out.println(Span.current().getSpanContext().getTraceId()); // 擷取 TraceId
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, t.getMessage());
} finally {
span.end();
}
}
}, 10, 30, TimeUnit.SECONDS);
}
@ResponseBody
@RequestMapping("/parent")
public String parent() {
Span span = tracer.spanBuilder("parent").setSpanKind(SpanKind.SERVER).startSpan();
try (Scope scope = span.makeCurrent()) {
// 使用Baggage透傳業務自訂標籤
Baggage baggage = Baggage.current().toBuilder()
.put("user.id", "1")
.put("user.name", "name")
.build();
try (Scope baggageScope = baggage.storeInContext(Context.current()).makeCurrent()) {
child();
}
span.setAttribute("http.method", "GET");
span.setAttribute("http.uri", "/parent");
} finally {
span.end();
}
return "parent";
}
private void child() {
Span span = tracer.spanBuilder("child").startSpan();
try (Scope scope = span.makeCurrent()) {
System.out.println("current traceId = " + Span.current().getSpanContext().getTraceId());
System.out.println("userId in baggage = " + Baggage.current().getEntryValue("user.id"));
Thread.sleep(1000);
} catch (Throwable e) {
span.setStatus(StatusCode.ERROR, e.getMessage());
} finally {
span.end();
}
}
}
範例程式碼說明:
在
OpenTelemetryController
的init
方法中啟動了一個定時調度任務,並在調度任務開始時建立一個Span,在調度任務結束時關閉該Span。在
OpenTelemetryController
的parent
方法中調用了Opentelemetry SDK的多個方法。每次被調用時建立一個名為
parent
的Span,並在方法結束時關閉該Span。調用Baggage SDK,新加了名為
user.id
和user.name
的兩對Baggage,這兩個Baggage後續會傳遞到下遊應用。為步驟2.1建立的Span新增了兩個Attribute。
在
OpenTelemetryController
的child
方法中會執行以下操作。
不同探針差異點對比
對於上述代碼中的不同操作,ARMS 3.x及以下版本探針和ARMS 4.x探針的支援情況有所區別,詳情可見下方表格。
步驟 | 4.x及以上版本探針 | 3.x及以下版本探針 |
1 | 支援,會產生一個新的Span。 | 支援,會產生一個新的Span。 |
2.1 | 支援 | 支援 |
2.2 | 支援 | 不支援 |
2.3 | 支援 | 支援 |
3.1 | 支援 | 支援,該Span會作為步驟2.1建立出來的Span的方法棧存在。 |
3.2 | 支援,和ARMS中traceId是一個。 | 不支援,列印出的traceId和ARMS探針中的traceId不同。 |
3.2 | 支援 | 支援 |
埋點效果展示
4.x及以上版本
步驟1埋點效果:
可以正常看到通過OpenTelemetry SDK產生的Span。
步驟2.x、3.x埋點效果:
通過OpenTelemetry SDK產生的Span(紅框)和當前探針埋點Tomcat產生的Span(黃框)在一條鏈路上,且通過OpenTelemetry SDK產生的Span的相關Attribute也設定成功(藍框)。
3.x及以上版本探針
步驟1埋點效果:
步驟2.x、3.x埋點效果:
通過OpenTelemetry SDK產生的Span(紅框)和當前探針埋點Tomcat產生的Span(黃框)在一條鏈路上,其中名為
child
的Span會作為名為parent
的Span的方法棧存在,且通過OpenTelemetry SDK產生的Span的相關Attribute也設定成功(藍框)。
相關文檔
您可以在應用的業務日誌中關聯調用鏈的TraceId資訊,從而在應用出現問題時,能夠通過調用鏈的TraceId快速關聯到業務日誌,及時定位、分析解決問題。更多資訊,請參見Java應用業務日誌關聯調用鏈TraceId。