CLOVER馃崁

That was when it all began.

WildFly銇甅icroProfile Telemetry銈点儢銈枫偣銉嗐儬銈掍娇銇c仸銆併儓銉兗銈广倰瑭︺仚

銇撱倢銇併仾銇倰銇椼仧銇忋仸鏇搞亜銇熴倐銇紵

WildFly銇penTelemetry銈掕│銇椼仸銇裤仧銇勩仺銇勩亞銇撱仺銇с併伨銇氥伅MicroProfile Telemetry銈点儢銈枫偣銉嗐儬銈掕│銇椼仸銇裤仧銇勩仺鎬濄亜銇俱仚銆

MicroProfile Telemetry锛圡icroProfile Telemetry Tracing锛

MicroProfile Telemetry銇従鍦ㄣ儛銉笺偢銉с兂1.0銇с丮icroProfile 6.0銇惈銇俱倢銇︺亜銇俱仚銆

MicroProfile 6.0 Release - MicroProfile

MicroProfile 5.0銇俱仹銇疢icroProfile OpenTracing銇犮仯銇熴伄銇с仚銇屻併亾銈屻亴缃亶鎻涖亪銈夈倢銇俱仐銇熴

浠曟銇亾銇°倝銆

MicroProfile Telemetry Tracing

GitHub銉儩銈搞儓銉銉笺伅銇撱仭銈夈

GitHub - eclipse/microprofile-telemetry: microprofile telemetry

姝g⒑銇伅銆丮icroProfile Telemetry Tracing銇с仚銇

銇撱仭銈夈倰瑕嬨仸銇裤倠銇ㄣ丮icroProfile Telemetry Tracing銇疧penTelemetry銇倛銈嬪垎鏁c儓銉兗銈枫兂銈般亴鏈夊姽銇仾銇c仸銇勩倠鐠板銇
MicroProfile銈€儣銉偙銉笺偡銉с兂銇岀啊鍗樸伀鍙傚姞銇с亶銈嬨倛銇嗐伀銇欍倠浠曟銇倛銇嗐仹銇欍

This specification defines the behaviors that allow MicroProfile applications to easily participate in an environment where distributed tracing is enabled via OpenTelemetry (a merger between OpenTracing and OpenCensus).

MicroProfile Telemetry Tracing / Architecture

MicroProfile Telemetry Tracing銇儔銈儱銉°兂銉堛亰銈堛伋瀹熻銇丱penTelemetry 1.13銇簴鎷犮仚銈嬪繀瑕併亴銇傘倞銇俱仚銆

This document and implementations MUST comply with the following OpenTelemetry 1.13 specifications:

MicroProfile Telemetry Tracing / Architecture

https://github.com/open-telemetry/opentelemetry-specification/blob/v1.13.0/specification/overview.md

銇俱仧銆丱penTelemetry銇亞銇icroProfile Telemetry Tracing銇屽璞°仺銇欍倠銇伅銉堛儸銉笺偡銉炽偘銇伩銇с併儭銉堛儶銈偣銇ㄣ儹銈兂銈般伅瀵捐薄澶栥仹銇欍

銇濄倢銇嬨倝銆併亾銇偍銉炽儓銉兗銈掓浉銇勩仸銇勩倠鏅傜偣銇с伄OpenTelemetry浠曟銇1.25.0銇с仚銆

OpenTelemetry Specification 1.25.0 | OpenTelemetry

浠婂洖銇併亾銇偣銇皸銇仜銇氶层倎銇俱仐銈囥亞銆

MicroProfile Telemetry Tracing銇с伅銆佽嚜鍕旾nstrumentation銇ㄦ墜鍕旾nstrumentation銆併偍銉笺偢銈с兂銉堛伀銈堛倠Instrumentation銇3銇ゃ亴
瑷樿級銇曘倢銇︺亜銇俱仚銆

鑷嫊Instrumentation銇Jakarta RESTful Web Services锛JAX-RS锛夈伄銈点兗銉愩兗锛忋偗銉┿偆銈€兂銉堛併仢銇椼仸MicroProfile REST Client銇
銈姐兗銈广偝銉笺儔銈掑鏇淬仚銈嬨亾銇ㄣ仾銇忓垎鏁c儓銉兗銈枫兂銈般伀鍙傚姞銇с亶銈嬨倛銇嗐伀銇倠銈傘伄銇с仚銆

Jakarta RESTful Web Services (server and client), and MicroProfile REST Clients are automatically enlisted to participate in distributed tracing without code modification as specified in the Tracing API.

鎵嬪嫊Instrumentation銇CDI绠$悊Bean銇銇椼仸@WithSpan銈€儙銉嗐兗銈枫儳銉銈掍粯涓庛仚銈嬨併倐銇椼亸銇SpanBuilderCDI绠$悊銇曘倢銇︺亜銈Span
浣裤仯銇nstrumentation銈掓槑绀虹殑銇銇嗐倐銇仹銇欍

銈ㄣ兗銈搞偋銉炽儓銇倛銈婭nstrumentation銇丱penTelemetry銇瓵utomatic Instrumentation銈掍娇鐢ㄣ仚銈嬨倐銇仹銇欍

Automatic Instrumentation | OpenTelemetry

Agent Configuration | OpenTelemetry

銇俱仧MicroProfile Telemetry Tracing銇с伅銆佷互涓嬨伄OpenTelemetry銇APICDI绠$悊Bean銇ㄣ仐銇︽彁渚涖仚銈嬪繀瑕併亴銇傘倠銇撱仺銇仾銇c仸銇勩伨銇欍

  • io.opentelemetry.api.OpenTelemetry
  • io.opentelemetry.api.trace.Tracer
  • io.opentelemetry.api.trace.Span
  • io.opentelemetry.api.baggage.Baggage

OpenTelemetry銇API銈掔洿鎺ュ懠銇冲嚭銇Span#currentBaggage#current銇疅琛岀祼鏋溿伅銆CDI绠$悊Bean銇ㄣ仐銇﹀彇寰椼仚銈嬨倐銇仺鍚屻仒銇с亗銈
蹇呰銇屻亗銈娿伨銇欍

鏈寰屻伀閲嶈銇儩銈ゃ兂銉堛仺銇椼仸銆併儑銉曘偐銉儓銇с伅MicroProfile Telemetry Tracing銇劇鍔广伀銇仯銇︺亰銈娿丮icroProfile Config绲岀敱銇
otel.sdk.disabled=false銈掓寚瀹氥仚銈嬪繀瑕併亴銇傘倞銇俱仚銆

MicroProfile Telemetry Tracing / Tracing Enablement

銇俱仛銇亾銈撱仾銇ㄣ亾銈嶃仹銇欍伃銆

WildFly銇甅icroProfile Telemetry銈点儢銈枫偣銉嗐儬

娆°伀WildFly銇┍銈掔Щ銇椼伨銇欍亴銆丮icroProfile Telemetry鍚戙亼銇偟銉栥偡銈广儐銉犮亴銇傘倞銇俱仚銆

WildFly Admin Guide / Subsystem configuration / MicroProfile Telemetry Subsystem Configuration

銇撱仭銈夈伅WildFly 28銇ц拷鍔犮仌銈屻仧銈堛亞銇с仚銆

WildFly 28 Beta1 is released!

銇撱伄涓鏂广仹銆丱penTelemetry銈点儢銈枫偣銉嗐儬銈傘亗銈娿伨銇欍

WildFly Admin Guide / Subsystem configuration / OpenTelemetry Subsystem Configuration

銇撱仭銈夈伅WildFly 25銇с丮icroProfile OpenTracing銈点儢銈枫偣銉嗐儬銈掔疆銇嶆彌銇堛倠褰€仹銉儶銉笺偣銇曘倢銇熴倛銇嗐仹銇欍

WildFly 25 Beta1 is released!

鏈鍒濄併亾銇儔銈儱銉°兂銉堛亱銈夊叆銇c仧銇仹MicroProfile Telemetry銈点儢銈枫偣銉嗐儬銇∣penTelemetry銈点儢銈枫偣銉嗐儬銇綅缃仴銇戙伄閬曘亜銇
銈忋亱銈夈仾銇嬨仯銇熴伄銇с仚銇屻

  • MicroProfile Telemetry銈点儢銈枫偣銉嗐儬銇疢icroProfile Telemetry Tracing銈掍娇銇堛倠銈堛亞銇仚銈嬨倐銇
  • OpenTelemetry銈点儢銈枫偣銉嗐儬銇丱penTelemetry銉┿偆銉栥儵銉兗銇ō瀹氾紙Exporter銆丼pan Processor銆丼ampler锛夈倰琛屻亞銈傘伄

銇ㄣ亜銇嗐倐銇仹銆佷浮鑰呫伀銇緷瀛橀枹淇傘亴銇傘倞MicroProfile Telemetry銈点儢銈枫偣銉嗐儬銇疧penTelemetry銈点儢銈枫偣銉嗐儬銇屼娇銇堛倠銇撱仺銇屽墠鎻愩伀
銇仯銇︺亜銇俱仚銇

瀹熼殯銇仺銇撱倣銆丮icroProfile Telemetry銇儸銈ゃ儰銉煎畾缇┿倰瑕嬨倠銇∣penTelemetry銉偆銉ゃ兗銇緷瀛樸仐銇︺亜銈嬨亾銇ㄣ亴銈忋亱銈娿伨銇欍

<?xml version="1.0" ?>
<layer-spec xmlns="urn:jboss:galleon:layer-spec:2.0" name="microprofile-telemetry">
    <props>
        <prop name="org.wildfly.rule.annotations" value="io.opentelemetry.instrumentation.annotations"/>
        <prop name="org.wildfly.rule.class" value="io.opentelemetry.api.*"/>
        <prop name="org.wildfly.rule.add-on-depends-on" value="only:cdi"/>
        <prop name="org.wildfly.rule.add-on" value="observability,microprofile-telemetry"/>
    </props>
    <dependencies>
        <layer name="cdi"/>
        <layer name="opentelemetry"/>
        <layer name="microprofile-config"/>
    </dependencies>
    <feature spec="subsystem.microprofile-telemetry"/>
</layer-spec>

https://github.com/wildfly/wildfly/blob/29.0.1.Final/galleon-pack/galleon-shared/src/main/resources/layers/standalone/microprofile-telemetry/layer-spec.xml

OpenTelemetry銉偆銉ゃ兗銇亾銇°倝銆

https://github.com/wildfly/wildfly/blob/29.0.1.Final/galleon-pack/galleon-shared/src/main/resources/layers/standalone/opentelemetry/layer-spec.xml

銈姐兗銈广偝銉笺儔銇併仢銈屻仦銈屻亾銇亗銇熴倞銆

SmallRye OpenTelemetry

銇撱亾銇俱仹銇icroProfile Telemetry Tracing銇WildFly銇偟銉栥偡銈广儐銉犮倰瑕嬨仸銇嶃伨銇椼仧銇屻WildFly銇甅icroProfile Telemetry Tracing銇疅瑁呫伅
銇伀銇嬶紵銇ㄣ亜銇嗐仺銇撱倣銇屾皸銇仾銈娿伨銇欍伃銆

SmallRye OpenTelemetry銇倛銇嗐仹銇欍

GitHub - smallrye/smallrye-opentelemetry: SmallRye OpenTelemetry - A CDI and Jakarta REST implementation of OpenTelemetry Tracing

WildFly 29.0.1.Final銇伅銆丼mallRye OpenTelemetry 2.3.2銇屽惈銇俱倢銇︺亜銇俱仚銆

瑾槑銇亾銈屻亸銈夈亜銇仐銇︺佸疅闅涖伀瑭︺仐銇︺亜銇c仸銇裤仧銇勩仺鎬濄亜銇俱仚銆

銇婇

浠婂洖銇亰椤屻伅銆佷互涓嬨伄銈堛亞銇仐銇俱仐銈囥亞銆

flowchart LR
    銈儵銈ゃ偄銉炽儓 --> |curl/HTTP| A
    subgraph WildFly
    A[JAX-RS Server/API-A] --> |JAX-RS Client/HTTP| B[API-B]
    A --> |MicroProfile REST Client/HTTP| B[JAX-RS Server/API-B]
    end
    B --> |JDBC| D[(MySQL)]
    WildFly --> |銉嗐儸銉°儓銉兗銉囥兗銈縷 J[Jaeger]

Web銈€儣銉偙銉笺偡銉с兂銈2銇ょ敤鎰忋仐銇︺併仢銈屻仦銈WildFly銇儑銉椼儹銈ゃ仐銇俱仚锛堝崢绱斿寲銇椼仸銆併伈銇ㄣ仱銇WildFly銇2銇ゃ伄Web銈€儣銉偙銉笺偡銉с兂銈
銉囥儣銉偆銇椼伨銇欙級銆

銇撱亾銇JAX-RS銈凪icroProfile REST Client銇銇椼仸銉堛儸銉笺偡銉炽偘銇屾湁鍔广伀銇倠銇撱仺銈掔⒑瑾嶃仐銇俱仚銆

銇倱銇ㄣ仾銇MySQL銇搞伄銈€偗銈汇偣銈傜疆銇勩仸銇勩伨銇欍亴銆併亾銇°倝銇疢icroProfile Telemetry Tracing銇璞″銇伄銇с偄銈偦銈广仩銇CDI绠$悊Bean銇
銉堛儸銉笺偣銇椼仧銇勩仺鎬濄亜銇俱仚銆

銉嗐儸銉°儓銉兗銉囥兗銈裤伅銆丣aeger銇у弾闆嗐仐銇俱仚銆

2銇ゃ伄銈€儣銉偙銉笺偡銉с兂銇ㄣ儑銉笺偪銉欍兗銈广倰浣裤亞銇ㄣ亜銇嗐亾銇ㄣ仹銆併儐銉笺儢銉伄銇婇銇浉绫嶃伀銇椼伨銇欍

create table book(
    isbn varchar(15),
    title varchar(100),
    price int,
    primary key(isbn)
);

寰岃堪銇椼伨銇欍亴銆併儑銉笺偪銉欍兗銈广伀銇MySQL銈掍娇銇勩伨銇欍

2銇ょ洰銇偄銉椼儶銈便兗銈枫儳銉筹紙api-b锛夈亴MySQL銇偄銈偦銈广仐銇俱仚銇屻併伈銇ㄣ仱鐩伄銈€儣銉偙銉笺偡銉с兂锛api-a锛夈伅鍗樼磾銇儣銉偔銈枫仺銇椼仸
鎸倠鑸炪亞妲嬫垚銇仐銇俱仚銆

鐠板

浠婂洖銇挵澧冦伅銇撱仭銈夈

$ java --version
openjdk 17.0.8.1 2023-08-24
OpenJDK Runtime Environment (build 17.0.8.1+1-Ubuntu-0ubuntu122.04)
OpenJDK 64-Bit Server VM (build 17.0.8.1+1-Ubuntu-0ubuntu122.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.9.4 (dfbb324ad4a7c8fb0bf182e6d91b0ae20e3d2dd9)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 17.0.8.1, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.15.0-84-generic", arch: "amd64", family: "unix"

WildFly銇29.0.1.Final銈掍娇銇勩172.17.0.2銇у嫊浣溿仐銇︺亜銈嬨倐銇仺銇椼伨銇欍

$ bin/standalone.sh --version
=========================================================================

  JBoss Bootstrap Environment

  JBOSS_HOME: /opt/wildfly

  JAVA: /opt/java/openjdk/bin/java

  JAVA_OPTS:  -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true  --add-exports=java.desktop/sun.awt=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.url.ldap=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.url.ldaps=ALL-UNNAMED --add-exports=jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED -Djava.security.manager=allow

=========================================================================

14:21:30,338 INFO  [org.jboss.modules] (main) JBoss Modules version 2.1.0.Final
WildFly Full 29.0.1.Final (WildFly Core 21.1.1.Final)

璧峰嫊銈炽優銉炽儔銆

$ bin/standalone.sh \
    -Djboss.bind.address=0.0.0.0 \
    -Djboss.bind.address.management=0.0.0.0 \

JDBC銉夈儵銈ゃ儛銇儑銉椼儹銈ゃ仺銆丏ataSource銇綔鎴愩伅娓堛倱銇с亜銈嬨倐銇仺銇椼伨銇欍

MySQL銇172.17.0.3銇у嫊浣溿仐銇︺亜銈嬨倐銇仺銇椼伨銇欍

 MySQL  localhost:3306 ssl  practice  SQL > select version();
+-----------+
| version() |
+-----------+
| 8.0.34    |
+-----------+
1 row in set (0.0007 sec)

Jaeger銇172.17.0.4銇у嫊浣溿仐銇︺亜銈嬨倐銇仺銇椼伨銇欍

$ ./jaeger-all-in-one version
2023/09/27 14:23:14 maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
2023/09/27 14:23:14 application version: git-commit=2d351c3f30072cae7f5755be20e34c2697b9e3b5, git-version=v1.49.0, build-date=2023-09-07T13:13:08Z
{"gitCommit":"2d351c3f30072cae7f5755be20e34c2697b9e3b5","gitVersion":"v1.49.0","buildDate":"2023-09-07T13:13:08Z"}

璧峰嫊銈炽優銉炽儔銆

$ ./jaeger-all-in-one

WildFly銇icroProfile Telemetry銈点儢銈枫偣銉嗐儬銈掓湁鍔广伀銇欍倠

銇俱仛銇WildFly銇甅icroProfile Telemetry銈点儢銈枫偣銉嗐儬銈掓湁鍔广伀銇椼伨銇椼倗銇嗐

銇伄銇с仚銇屻丮icroProfile Telemetry銈点儢銈枫偣銉嗐儬銇疧penTelemetry銈点儢銈枫偣銉嗐儬銇屼娇銇堛倠銇撱仺銇屽墠鎻愩伀銇仯銇︺亜銈嬨伄銇с佹渶鍒濄伀
OpenTelemetry銈点儢銈枫偣銉嗐儬銈掓湁鍔广伀銇椼仸銆併仢銈屻亱銈塎icroProfile Telemetry銈点儢銈枫偣銉嗐儬銈掓湁鍔广伀銇欍倠蹇呰銇屻亗銈娿伨銇欍

WildFly Admin Guide / Subsystem configuration / MicroProfile Telemetry Subsystem Configuration

绠$悊CLI銇ф帴缍氥

$ bin/jboss-cli.sh -c

OpenTelemetry銇偍銈偣銉嗐兂銈枫儳銉炽亰銈堛伋銈点儢銈枫偣銉嗐儬銈掕拷鍔犮

[standalone@localhost:9990 /] /extension=org.wildfly.extension.opentelemetry:add()
[standalone@localhost:9990 /] /subsystem=opentelemetry:add()

OpenTelemetry銈点儢銈枫偣銉嗐儬銇ō瀹氥

[standalone@localhost:9990 /] /subsystem=opentelemetry:write-attribute(name=exporter-type,value=otlp)
[standalone@localhost:9990 /] /subsystem=opentelemetry:write-attribute(name=endpoint,value=http://172.17.0.4:4317)

浠婂洖銇丣aeger銇玂TLP銉椼儹銉堛偝銉銉嗐儸銉°儓銉兗銉囥兗銈裤倰閫併倠銈堛亞銇仐銇俱仚銆

WildFly Admin Guide / Subsystem configuration / OpenTelemetry Subsystem Configuration / Configuration

缍氥亜銇︺丮icroProfile Telemetry銇偍銈偣銉嗐兂銈枫儳銉炽仺銈点儢銈枫偣銉嗐儬銈掕拷鍔犮

[standalone@localhost:9990 /] /extension=org.wildfly.extension.microprofile.telemetry:add()
[standalone@localhost:9990 /] /subsystem=microprofile-telemetry:add()

銇撱亾銇俱仹銈勩仯銇熴倝銆WildFly銈掑啀璧峰嫊銇椼伨銇欍

[standalone@localhost:9990 /] reload

銇°倗銇c仺銉忋優銇c仧銇伅銆佷互涓嬨仹銇椼仧銇

[standalone@localhost:9990 /] /subsystem=opentelemetry:write-attribute(name=endpoint,value=http://172.17.0.4:4317)

銉椼儹銉堛偝銉銇疛aeger銇∣TLP銇仼銇°倝銇嬨倰閬搞伓銇撱仺銇仾銈嬨伄銇с仚銇屻otlp锛圤penTelemetry protocol锛夈倰閬搞倱銇с倐銆丣aeger銇
gRPC銇儩銉笺儓銈掗伕銇跺繀瑕併亴銇傘倞銇俱仚锛坓RPC銇4317銆丠TTP銇4318锛

endpoint: The URL via which OpenTelemetry will push traces. The default is Jaeger鈥檚 gRPC-based endpoint, http://localhost:14250

14250銇丣aeger銈ㄣ兗銈搞偋銉炽儓銇屼娇銇唃RPC銇с伄銉濄兗銉堛仹銇欍

鏈鍒濄伅HTTP銉濄兗銉堛倰鎸囧畾銇椼仸銇勩仧銈夈併亗銇ㄣ仹銇撱倱銇偍銉┿兗銇偐銇俱仌銈屻倠銇撱仺銇仾銈娿伨銇椼仧鈥︺

22:51:53,695 SEVERE [io.opentelemetry.exporter.internal.grpc.OkHttpGrpcExporter] (OkHttp http://172.17.0.4:4318/...) Failed to export spans. The request could not be executed. Full error message: FRAME_SIZE_ERROR: 4740180

銇俱仧銆佷粖鍥炪伅銉囥儠銈┿儷銉堛伄standalone.xml銈掍娇銇c仸銇勩倠銇仹OpenTelemetry銈点儢銈枫偣銉嗐儬銈凪icroProfile Telemetry銈点儢銈枫偣銉嗐儬銈
銇濄倢銇炪倢鏈夊姽鍖栥仐銇︺亜銇俱仚銇屻standalone-microprofile.xml銈掍娇銇c仸WildFly銈掑疅琛屻仚銈屻伆鏈鍒濄亱銈夋湁鍔广伀銇仯銇︺亜銈嬨伩銇熴亜銇с仚銆
銈傘仯銇ㄣ倐銆銉嗐儸銉°儓銉兗銉囥兗銈裤伄閫佷俊鍏銇ō瀹氥仾銇┿伅蹇呰銇с仚銇屻

銈€儣銉偙銉笺偡銉с兂銈掍綔鎴愩仚銈

銇濄倢銇с伅銆併偄銉椼儶銈便兗銈枫儳銉炽倰浣滄垚銇椼仸銇勩亶銇俱仚銆

api-b銈掍綔鎴愩仚銈

鏈鍒濄伀銆api-a銇銇亜銈api-b銇嬨倝浣滄垚銇椼仸銇勩亶銇俱仚銆

Maven渚濆瓨闁總銇仼銆

    <groupId>org.littlewings</groupId>
    <artifactId>api-b</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.opentelemetry</groupId>
                <artifactId>opentelemetry-bom</artifactId>
                <version>1.20.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>io.opentelemetry.instrumentation</groupId>
                <artifactId>opentelemetry-instrumentation-bom</artifactId>
                <version>1.20.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.eclipse.microprofile</groupId>
                <artifactId>microprofile</artifactId>
                <version>6.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-web-api</artifactId>
            <version>10.0.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>io.opentelemetry</groupId>
            <artifactId>opentelemetry-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>io.opentelemetry.instrumentation</groupId>
            <artifactId>opentelemetry-instrumentation-annotations</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.eclipse.microprofile.config</groupId>
            <artifactId>microprofile-config-api</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>api-b</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.4.0</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>

OpenTelemetry SDK銇娿倛銇矼icroProfile Config銇搞伄渚濆瓨闁總銇屽叆銇c仸銇勩倠銇ㄣ亾銈嶃亴銉濄偆銉炽儓銇с仚銆api-b銇枹銇椼仸銇佹槑绀虹殑銇
MicroProfile Config銈掕拷鍔犮仐銇亸銇︺倐銈堛亜銇仹銇欍亴銆

Jakarta Persistence锛JPA锛夈伄銈ㄣ兂銉嗐偅銉嗐偅銆

src/main/java/org/littlewings/wildfly/telemetry/b/Book.java

package org.littlewings.wildfly.telemetry.b;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "book")
public class Book {
    @Id
    private String isbn;
    private String title;
    private Integer price;

    // getter锛弒etter銇渷鐣
}

JPAEntityManager銈掍娇銇c仸銉囥兗銈裤儥銉笺偣銇偄銈偦銈广倰琛屻亞銈儵銈广

src/main/java/org/littlewings/wildfly/telemetry/b/BookRepository.java

package org.littlewings.wildfly.telemetry.b;

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.annotations.WithSpan;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;

import java.util.List;

@ApplicationScoped
public class BookRepository {
    @PersistenceContext
    private EntityManager entityManager;

    @Inject
    private Tracer tracer;

    @WithSpan
    public Book findByIsbn(String isbn) {
        return entityManager.find(Book.class, isbn);
    }

    @WithSpan
    public List<Book> findAll() {
        return entityManager
                .createQuery("select b from Book b order by b.price desc", Book.class)
                .getResultList();
    }

    public Book save(Book book) {
        Span span = tracer.spanBuilder("BookRepository.save")
                .setSpanKind(SpanKind.INTERNAL)
                .setParent(Context.current().with(Span.current()))
                .startSpan();

        try {
            if (entityManager.find(Book.class, book.getIsbn()) != null) {
                entityManager.merge(book);
            } else {
                entityManager.persist(book);
            }

            return book;
        } finally {
            span.end();
        }
    }
}

銇撱伄銈儵銈广仹銇丱penTelemetry Instrumentation銇API銈掓槑绀虹殑銇娇銇c仸銇勩伨銇欍

CDI绠$悊Bean銇с伅銆@WithSpan銈€儙銉嗐兗銈枫儳銉銈掍粯涓庛仚銈嬨仩銇戙仹銇撱伄銉°偨銉冦儔銇儓銉兗銈广倰瑷橀尣銇椼仸銇忋倢銇俱仚銆

銇俱仧銆佹墜鍕曘仹瑷橀尣銇欍倠鍫村悎銇嚜鍒嗐仹Span銈掗枊濮嬨仚銈屻伆OK銇с仚銆

    public Book save(Book book) {
        Span span = tracer.spanBuilder("BookRepository.save")
                .setSpanKind(SpanKind.INTERNAL)
                .setParent(Context.current().with(Span.current()))
                .startSpan();

        try {
            if (entityManager.find(Book.class, book.getIsbn()) != null) {
                entityManager.merge(book);
            } else {
                entityManager.persist(book);
            }

            return book;
        } finally {
            span.end();
        }

MicroProfile Telemetry銈点儢銈枫偣銉嗐儬銈掓湁鍔广伀銇椼仸銇勩倠銇仹銆丱penTelemetry闁總銇偗銉┿偣銇偆銉炽偢銈с偗銈枫儳銉炽亴銇с亶銇俱仚銆

    @Inject
    private Tracer tracer;

姘哥稓鍖栥儲銉嬨儍銉堛伄瑷畾銆

src/main/resources/META-INF/persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
             version="3.0">
    <persistence-unit name="main.pu" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>java:jboss/datasources/MySqlDs</jta-data-source>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

Jakarta RESTful Web Services锛JAX-RS锛夈伨銈忋倞銇偗銉┿偣銆

src/main/java/org/littlewings/wildfly/telemetry/b/JaxrsActivator.java

package org.littlewings.wildfly.telemetry.b;

import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;

@ApplicationPath("")
public class JaxrsActivator extends Application {
}

銉偗銈ㄣ偣銉堛仺銉偣銉濄兂銈广伅銉偝銉笺儔銇ㄣ仐銇﹀畾缇┿仐銇俱仐銇熴

src/main/java/org/littlewings/wildfly/telemetry/b/BookRequest.java

package org.littlewings.wildfly.telemetry.b;

public record BookRequest(String title, Integer price) {
}

src/main/java/org/littlewings/wildfly/telemetry/b/BookResponse.java

package org.littlewings.wildfly.telemetry.b;

public record BookResponse(String isbn, String title, Integer price) {
}

JAX-RS銉偨銉笺偣銈儵銈广

src/main/java/org/littlewings/wildfly/telemetry/b/BookResource.java

package org.littlewings.wildfly.telemetry.b;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;

import java.util.List;

@Transactional
@ApplicationScoped
@Path("books")
public class BookResource {
    @Inject
    private BookRepository bookRepository;

    @GET
    @Path("{isbn}")
    @Produces(MediaType.APPLICATION_JSON)
    public BookResponse findByIsbn(@PathParam("isbn") String isbn) {
        Book book = bookRepository.findByIsbn(isbn);

        if (book == null) {
            throw new NotFoundException(String.format("book[%s] not found", isbn));
        }

        return new BookResponse(book.getIsbn(), book.getTitle(), book.getPrice());
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<BookResponse> findAll() {
        return bookRepository
                .findAll()
                .stream()
                .map(book -> new BookResponse(book.getIsbn(), book.getTitle(), book.getPrice()))
                .toList();
    }

    @PUT
    @Path("{isbn}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public void register(@PathParam("isbn") String isbn, BookRequest bookRequest) {
        Book book = new Book();
        book.setIsbn(isbn);
        book.setTitle(bookRequest.title());
        book.setPrice(bookRequest.price());

        bookRepository.save(book);
    }
}

鏈寰屻伀銆丮icroProfile Config銇ф壉銇嗐儣銉儜銉嗐偅銉曘偂銈ゃ儷銈掔敤鎰忋

src/main/resources/META-INF/microprofile-config.properties

## OpenTelemetry SDK Configuration
otel.sdk.disabled=false
otel.service.name=api-b

otel.sdk.disabled銇岄噸瑕併仹銇欍

銉囥儠銈┿儷銉堛仹銇疢icroProfile Telemetry Tracing銇劇鍔广伀銇仯銇︺亰銈娿丮icroProfile Config绲岀敱銇otel.sdk.disabled=false銈掓寚瀹氥仚銈嬪繀瑕併亴銇傘倠
銇ㄣ亜銇嗚┍銇с仐銇熴

MicroProfile Telemetry Tracing / Tracing Enablement

銇撱倢銈掋仚銇c亱銈婂繕銈屻仸銇勩仸銆併倎銇°們銇忋仭銈冦儚銉炪倞銇俱仐銇熲︺

銇ㄣ亾銈嶃仹銆併亾銇otel.sdk.disabled銇仾銈撱伄瑷畾銇犮倣銇嗭紵銇ㄦ濄仯銇熴伄銇с仚銇屻併亾銈屻伅銇熴伓銈揙penTelemetry SDK銇ō瀹氥仹銇欍伃銆

Environment Variable Specification | OpenTelemetry

Java鍚戙亼銇甇penTelemetry SDK銇с伅銆鐠板澶夋暟銇犮亼銇с伅銇亸銇銈枫偣銉嗐儬銉椼儹銉戙儐銈c仹銈傝ō瀹氥亴鍙兘銇с仚銆
鈥籓penTelemetry銇粫妲樸仺銇椼仸銇鐠板澶夋暟銇ㄣ儠銈°偆銉仹銇寚瀹氥亴鍙兘銇с仚

Agent Configuration / Configuring the agent

銈堛仯銇︺otel.service.name銇ㄣ亜銇嗐伄銈侽penTelemetry SDK銇儣銉儜銉嗐偅銇с仚銆

https://github.com/smallrye/smallrye-opentelemetry/blob/2.3.2/implementation/config/src/main/java/io/smallrye/opentelemetry/implementation/config/OpenTelemetryConfigProducer.java#L27-L30

銇傘仺銇儜銉冦偙銉笺偢銉炽偘銇椼仸

$ mvn package

WildFly銇儑銉椼儹銈ゃ仐銇︺亰銇嶃伨銇欍

api-a銈掍綔鎴愩仚銈

娆°伅銆api-b銇墠娈点伀銇傘倠api-a銈掍綔鎴愩仐銇俱仚銆

Maven渚濆瓨闁總銇仼銆

    <groupId>org.littlewings</groupId>
    <artifactId>api-a</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.opentelemetry</groupId>
                <artifactId>opentelemetry-bom</artifactId>
                <version>1.20.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>io.opentelemetry.instrumentation</groupId>
                <artifactId>opentelemetry-instrumentation-bom</artifactId>
                <version>1.20.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.eclipse.microprofile</groupId>
                <artifactId>microprofile</artifactId>
                <version>6.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-web-api</artifactId>
            <version>10.0.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>io.opentelemetry</groupId>
            <artifactId>opentelemetry-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>io.opentelemetry.instrumentation</groupId>
            <artifactId>opentelemetry-instrumentation-annotations</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.eclipse.microprofile.rest.client</groupId>
            <artifactId>microprofile-rest-client-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.microprofile.config</groupId>
            <artifactId>microprofile-config-api</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>api-a</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.4.0</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>

api-b銇ㄥ皯銇楅仌銇嗐伄銇丮icroProfile Rest Client銈掍緷瀛橀枹淇傘伀鍔犮亪銇︺亜銈嬨亾銇ㄣ仹銇欍伃銆

        <dependency>
            <groupId>org.eclipse.microprofile.rest.client</groupId>
            <artifactId>microprofile-rest-client-api</artifactId>
            <scope>provided</scope>
        </dependency>

api-a銇嬨倝api-b銇搞伅銆丮icroProfile Rest Client銇娿倛銇JAX-RS銇偗銉┿偆銈€兂銉堛亱銈夈偄銈偦銈广仐銇俱仚銆

api-b銇銇欍倠銆併儶銈銈ㄣ偣銉堛亰銈堛伋銉偣銉濄兂銈广

src/main/java/org/littlewings/wildfly/telemetry/b/BookRequest.java

package org.littlewings.wildfly.telemetry.b;

public record BookRequest(String title, Integer price) {
}

src/main/java/org/littlewings/wildfly/telemetry/b/BookResponse.java

package org.littlewings.wildfly.telemetry.b;

public record BookResponse(String isbn, String title, Integer price) {
}

銇撱仭銈夈伅銆佸厛銇汇仼銇api-b銇畾缇┿仺鍚屻仒銇с仚銆

娆°伀銆丮icroProfile Rest Client銇т娇銇嗐偆銉炽偪銉笺儠銈с兗銈广倰瀹氱京銇椼伨銇欍api-b銇儶銈姐兗銈广偗銉┿偣銇畾缇┿倰銇仦銇c仧銈傘伄銇с仚銆

src/main/java/org/littlewings/wildfly/telemetry/b/BookResourceClient.java

package org.littlewings.wildfly.telemetry.b;

import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import java.util.List;

@Path("books")
@RegisterRestClient
public interface BookResourceClient {
    @GET
    @Path("{isbn}")
    @Produces(MediaType.APPLICATION_JSON)
    BookResponse findByIsbn(@PathParam("isbn") String isbn);

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    List<BookResponse> findAll();

    @PUT
    @Path("{isbn}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    void register(@PathParam("isbn") String isbn, BookRequest bookRequest);
}

銇撱仭銈夈伄銈ゃ兂銈裤兗銉曘偋銉笺偣瀹氱京銇ㄣ@RegisterRestClient銈€儙銉嗐兗銈枫儳銉銇粯涓庛仹BookResourceClient銇嬨倝浣滄垚銇曘倢銇
MicroProfile Rest Client銇疅浣撱亴銈ゃ兂銈搞偋銈偡銉с兂銇с亶銈嬨倛銇嗐伀銇倞銇俱仚銆

@Path("books")
@RegisterRestClient
public interface BookResourceClient {

銇撱亾銇俱仹銇api-b銇偄銈偦銈广仚銈嬨仧銈併伄銈姐兗銈广偝銉笺儔銇с仐銇熴

缍氥亜銇︺伅銆api-a鑷韩銇屽畾缇┿仚銈JAX-RS銉偨銉笺偣銇с仚銆

JAX-RS銇湁鍔瑰寲銆

src/main/java/org/littlewings/wildfly/telemetry/a/JaxrsActivator.java

package org.littlewings.wildfly.telemetry.a;

import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;

@ApplicationPath("")
public class JaxrsActivator extends Application {
}

api-a銇搞伄銈€偗銈汇偣銈掋儣銉偔銈枫仚銈JAX-RS銉偨銉笺偣銆

src/main/java/org/littlewings/wildfly/telemetry/a/ProxyResource.java

package org.littlewings.wildfly.telemetry.a;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.UriBuilder;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.littlewings.wildfly.telemetry.b.BookRequest;
import org.littlewings.wildfly.telemetry.b.BookResourceClient;
import org.littlewings.wildfly.telemetry.b.BookResponse;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@Path("proxy")
@ApplicationScoped
public class ProxyResource {
    @Inject
    @ConfigProperty(name = "api_b.endpoint.base")
    private String endpointBase;

    @Inject
    private BookResourceClient bookResourceClient;

    @GET
    @Path("{isbn}")
    @Produces(MediaType.APPLICATION_JSON)
    public Map<String, Object> findByIsbn(@PathParam("isbn") String isbn) {
        try (Client client = ClientBuilder.newClient()) {
            BookResponse bookResponse =
                    client
                            .target(UriBuilder.fromUri(endpointBase + "/books/{isbn}").build(isbn))
                            .request()
                            .get(BookResponse.class);

            return Map.of(
                    "isbn", bookResponse.isbn(),
                    "title", bookResponse.title(),
                    "price", bookResponse.price()
            );
        }
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<Map<String, Object>> findAll() {
        try (Client client = ClientBuilder.newClient()) {
            List<BookResponse> bookResponses =
                    client
                            .target(UriBuilder.fromUri(endpointBase + "/books"))
                            .request()
                            .get(new GenericType<List<BookResponse>>() {
                            });

            return bookResponses
                    .stream()
                    .map(bookResponse ->
                            Map.<String, Object>of(
                                    "isbn", bookResponse.isbn(),
                                    "title", bookResponse.title(),
                                    "price", bookResponse.price()
                            )
                    )
                    .toList();
        }
    }

    @PUT
    @Path("{isbn}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public void register(@PathParam("isbn") String isbn, Map<String, Object> request) {
        bookResourceClient.register(
                isbn,
                new BookRequest((String) request.get("title"), ((BigDecimal) request.get("price")).intValue())
        );
    }
}

MicroProfile Telemetry銇JAX-RS銈儵銈ゃ偄銉炽儓銇∕icroProfile Rest Client銇浮鏂广伀浣滅敤銇椼仸銇勩倠銇撱仺銇岀⒑瑾嶃仹銇嶃倠銈堛亞銇佸弬鐓х郴銇
瀹氱京銇JAX-RS銈儵銈ゃ偄銉炽儓銇с

    @GET
    @Path("{isbn}")
    @Produces(MediaType.APPLICATION_JSON)
    public Map<String, Object> findByIsbn(@PathParam("isbn") String isbn) {
        try (Client client = ClientBuilder.newClient()) {
            BookResponse bookResponse =
                    client
                            .target(UriBuilder.fromUri(endpointBase + "/books/{isbn}").build(isbn))
                            .request()
                            .get(BookResponse.class);

            return Map.of(
                    "isbn", bookResponse.isbn(),
                    "title", bookResponse.title(),
                    "price", bookResponse.price()
            );
        }
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<Map<String, Object>> findAll() {
        try (Client client = ClientBuilder.newClient()) {
            List<BookResponse> bookResponses =
                    client
                            .target(UriBuilder.fromUri(endpointBase + "/books"))
                            .request()
                            .get(new GenericType<List<BookResponse>>() {
                            });

            return bookResponses
                    .stream()
                    .map(bookResponse ->
                            Map.<String, Object>of(
                                    "isbn", bookResponse.isbn(),
                                    "title", bookResponse.title(),
                                    "price", bookResponse.price()
                            )
                    )
                    .toList();
        }
    }

鏇存柊鍑︾悊銇疢icroProfile Rest Client銇ц銇嗐亾銇ㄣ伀銇椼伨銇椼仧銆

    @PUT
    @Path("{isbn}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public void register(@PathParam("isbn") String isbn, Map<String, Object> request) {
        bookResourceClient.register(
                isbn,
                new BookRequest((String) request.get("title"), ((BigDecimal) request.get("price")).intValue())
        );
    }

鍏堛伝銇╁畾缇┿仐銇api-b銇搞偄銈偦銈广仚銈嬨仧銈併伄銈ゃ兂銈裤兗銉曘偋銉笺偣銇枹銇椼仸鐢熸垚銇曘倢銈銈ゃ兂銈广偪銉炽偣銇@Inject銇с偆銉炽偢銈с偗銈枫儳銉炽仐銇俱仚銆

    @Inject
    private BookResourceClient bookResourceClient;

銇傘仺銇ō瀹氥仹銇欍

src/main/resources/META-INF/microprofile-config.properties

## OpenTelemetry SDK Configuration
otel.sdk.disabled=false
otel.service.name=api-a

api_b.endpoint.base=http://localhost:8080/api-b
org.littlewings.wildfly.telemetry.b.BookResourceClient/mp-rest/url=${api_b.endpoint.base}

銇撱仭銈夈倐otel.sdk.disabled=false銇屽繀瑕併仹銇欍otel.service.nameapi-a銇с仚銇

銇俱仧銆併亾銇°倝銇疢icroProfile Rest Client銇т娇銇嗐佸懠銇冲嚭銇楀厛銇Web銈点兗銉撱偣銇儥銉笺偣銇甎RL銇с仚銆

org.littlewings.wildfly.telemetry.b.BookResourceClient/mp-rest/url=${api_b.endpoint.base}

銇撱亾銈堛倞鍏堛伅銆併偆銉炽偪銉笺儠銈с兗銈瑰畾缇┿伄@Path銇緭銇勩伨銇欍

銇俱仧銆JAX-RS銈儵銈ゃ偄銉炽儓銇т娇銇嗐偄銈偦銈瑰厛銇畾缇┿仺銈傚叡閫氬寲銇椼伨銇椼仧銆

api_b.endpoint.base=http://localhost:8080/api-b
org.littlewings.wildfly.telemetry.b.BookResourceClient/mp-rest/url=${api_b.endpoint.base}

浠婂洖銇併亾銇儥銉笺偣銇ゃ倰MicroProfile Config銇@ConfigProperty銇у彇寰椼仐銆

    @Inject
    @ConfigProperty(name = "api_b.endpoint.base")
    private String endpointBase;

JAX-RS銈儵銈ゃ偄銉炽儓銇帴缍氬厛銈掓焙瀹氥仚銈嬪嚘鐞嗐仹浣裤仯銇︺亜銇俱仚銆

    @GET
    @Path("{isbn}")
    @Produces(MediaType.APPLICATION_JSON)
    public Map<String, Object> findByIsbn(@PathParam("isbn") String isbn) {
        try (Client client = ClientBuilder.newClient()) {
            BookResponse bookResponse =
                    client
                            .target(UriBuilder.fromUri(endpointBase + "/books/{isbn}").build(isbn))
                            .request()
                            .get(BookResponse.class);

            return Map.of(
                    "isbn", bookResponse.isbn(),
                    "title", bookResponse.title(),
                    "price", bookResponse.price()
            );
        }
    }

銇撱倢銇ф簴鍌欍伅銇с亶銇俱仐銇熴

銇撱倢銇с併儜銉冦偙銉笺偢銉炽偘銇椼仸

$ mvn package

WildFly銇儑銉椼儹銈ゃ仐銇︺亰銇嶃伨銇欍

銇ㄣ亾銈嶃仹銆併亾銇偄銉椼儶銈便兗銈枫儳銉炽倰銉撱儷銉夈仚銈嬨仺銆佷互涓嬨伄銈堛亞銇鍛娿亴琛ㄧず銇曘倢銇俱仚銆

[WARNING] 涓嶆槑銇垪鎸欏瀷瀹氭暟銇с仚org.osgi.annotation.bundle.Requirement.Resolution.OPTIONAL
  鐞嗙敱: org.osgi.annotation.bundle.Requirement$Resolution銇偗銉┿偣銉汇儠銈°偆銉亴瑕嬨仱銇嬨倞銇俱仜銈

銇撱倢銇丮icroProfile Config銇晱椤屻伄銈堛亞銇伄銇с佷粖鍥炪伅缃亜銇︺亰銇嶃伨銇欍

Remove OSGi annotations from the API · Issue #716 · eclipse/microprofile-config · GitHub

纰鸿獚銇欍倠

銇с伅銆佸嫊浣滅⒑瑾嶃仐銇︺伩銇俱仐銈囥亞銆

銇俱仛銇儑銉笺偪銇櫥閷层2銇ょ櫥閷层仐銇︺伩銇俱仚銆

$ curl -XPOST -H 'Content-Type: application/json' 172.17.0.2:8080/api-a/proxy/978-1484280782 -d '{ "title": "Java EE to Jakarta EE 10 Recipes: A Problem-Solution Approach for Enterprise Java", "price": 7163 }'


$ curl -XPUT -H 'Content-Type: application/json' 172.17.0.2:8080/api-a/proxy/978-1484282137 -d '{ "title": "Pro Jakarta EE 10: Open Source Enterprise Java-based Cloud-native Applications Development", "price": 8373 }'

銇撱伄鏅傜偣銇сhttp://[Jaeger銇屽嫊浣溿仐銇︺亜銈嬨儧銈广儓]:16686/銇偄銈偦銈广仐銇︺乄eb UI銈掔⒑瑾嶃仐銇︺伩銇俱仚銆

銉堛儸銉笺偣銇岃閷层仌銈屻仸銇勩伨銇欍伃銆

涓倰瑕嬨仸銇裤倠銇ㄣJAX-RS銈点兗銉愩兗銆丮icroProfile Rest Client銆CDI绠$悊Bean銇儓銉兗銈广亴纰鸿獚銇с亶銇俱仚銆

銈裤偘銇span.kind銈掕銈嬨仺銆併偟銉笺儛銉笺倓銈儵銈ゃ偄銉炽儓銆

銇濄倢浠ュ銇仼銆併仼銇ó椤炪伄銈炽兂銉濄兗銉嶃兂銉銇с儓銉兗銈广亴瑷橀尣銇曘倢銇熴伄銇嬨倰纰鸿獚銇с亶銇俱仚銆

CDI绠$悊Bean銇ц閷层仐銇熴倐銇伅銆併亾銇祵璺仩銇ㄦ墜鍕昳nstrumentation銇椼仧銈傘伄銇с仚銇

    public Book save(Book book) {
        Span span = tracer.spanBuilder("BookRepository.save")
                .setSpanKind(SpanKind.INTERNAL)
                .setParent(Context.current().with(Span.current()))
                .startSpan();

        try {
            if (entityManager.find(Book.class, book.getIsbn()) != null) {
                entityManager.merge(book);
            } else {
                entityManager.persist(book);
            }

            return book;
        } finally {
            span.end();
        }
    }

JAX-RS銈点兗銉愩兗銈凪icroProfile Rest Client銇柟銇佺壒銇銈姐兗銈广偝銉笺儔涓娿仹OpenTelemetry Instrumentation銇API銇娇銇c仸銇勩伨銇涖倱銆

娆°伅銆佸弬鐓х郴銈傝銇︺伩銇俱仐銈囥亞銆

$ curl 172.17.0.2:8080/api-a/proxy
[{"price":8373,"isbn":"978-1484282137","title":"Pro Jakarta EE 10: Open Source Enterprise Java-based Cloud-native Applications Development"},{"price":7163,"isbn":"978-1484280782","title":"Java EE to Jakarta EE 10 Recipes: A Problem-Solution Approach for Enterprise Java"}]


$ curl 172.17.0.2:8080/api-a/proxy/978-1484282137
{"price":8373,"isbn":"978-1484282137","title":"Pro Jakarta EE 10: Open Source Enterprise Java-based Cloud-native Applications Development"}

鍙傜収绯汇伄銉堛儸銉笺偣銈傝閷层仌銈屻伨銇椼仧銆

銇撱仭銈夈倐銆JAX-RS銈点兗銉愩兗銆JAX-RS銈儵銈ゃ偄銉炽儓銆CDI绠$悊Bean銇俱仹瑷橀尣銇曘倢銇︺亜銇俱仚銆

銇撱仭銈夈伄CDI绠$悊Bean銇儭銈姐儍銉夈伅銆@WithSpan銈€儙銉嗐兗銈枫儳銉銇ц閷层仐銇熴倐銇仹銇椼仧銆

    @WithSpan
    public Book findByIsbn(String isbn) {
        return entityManager.find(Book.class, isbn);
    }

銇倱銇ㄣ亱閫氥仐銇︾⒑瑾嶃仹銇嶃伨銇椼仧銆備粖鍥炪伅銇撱倱銇仺銇撱倣銇с仐銈囥亞銇嬨

JDBC銇紵

銇ㄣ亾銈嶃仹銆佸垎鏁c儓銉兗銈枫兂銈般倰銈勩仯銇︺亜銇︺佹鎴愯绱犮伀銉囥兗銈裤儥銉笺偣銇屽叆銇c仸銈嬪壊銇伅銉囥兗銈裤儥銉笺偣銈€偗銈汇偣銇屻儓銉兗銈广伀鍏ャ仯銇︺亜銇亜銇亴
銈勩仯銇便倞姘椼伀銇倞銇俱仚銆

OpenTelemetry Instrumentation銇JDBC銇唴瀹广倰瑕嬨倠銇ㄣ佺祫銇胯炯銇挎柟銇互涓嬨伄2绋銇屻亗銈嬨倛銇嗐仹銇欍

  • OpenTelemetryDataSource銈掍娇銇c仸銆併偑銉偢銉娿儷銇DataSource銈掋儵銉冦儣銇欍倠鏂规硶
  • OpenTelemetryDriverJDBC URL锛jdbc:otel:锛夈倰浣裤仯銇︺JDBCConnection銈掋儵銉冦儣銇欍倠鏂规硶

https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/v1.20.0/instrumentation/jdbc/library

WildFly銇ц銇嗗牬鍚堛伅銆併仼銇嗐仐銇熴倝銇勩亜銈撱仹銇椼倗銇嗐伃鈥︼紵

銇俱仧鍒ャ伄姗熶細銇銇︺伩銇俱仐銈囥亞銇嬧︺

銇娿倧銈娿伀

WildFly銇甅icroProfile Telemetry銈点儢銈枫偣銉嗐儬銈掍娇銇c仸銆併偄銉椼儶銈便兗銈枫儳銉炽伄銉堛儸銉笺偣銈掕銇c仸銇裤伨銇椼仧銆

OpenTelemetry銈点儢銈枫偣銉嗐儬銇↗aeger銇祫銇垮悎銈忋仜銇儚銉炪仯銇熴倞銆丮icroProfile Telemetry銇penTelemetry SDK銈掓湁鍔瑰寲銇欍倠銇倰
蹇樸倢銇熴倞銇ㄣ仩銇勩伓銉忋優銈娿伨銇椼仧銇屻佹渶绲傜殑銇伅銇倱銇ㄣ亱閫氥仜銇俱仐銇熲︺

銇傘仺銇JDBC銇笍銇胯炯銈併倠銇ㄣ併儓銉兗銈广仺銇椼仸銇伨銇ㄣ伨銈嬨亱銇仺鎬濄亞銇仹銆併伨銇熺⒑瑾嶃仐銇熴亜銇с仚銇