このエントリは2025/07/23現在の情報に基づいています。将来の機能追加や変更に伴い、記載事項からの乖離が発生する可能性があります。
このエントリは、以下のエントリに関連するもので、前段や背景はこちらを参照のこと。
準備するもの
利用したツールは以下。
- Maven: 3.9.10
- JDK: 21
- Micronaut: 4.9.1
参考にしたチュートリアルは以下。
OpenTelemetry Tracing with Oracle Cloud and the Micronaut Framework
https://guides.micronaut.io/latest/micronaut-cloud-trace-oci-maven-java.html
Archetypeの作成
MicronautのCLI (mn) もしくはMicronaut Launch(Webサイト)でarchetypeを作成する。今回はアプリケーション設定でapplication.propertiesではなく、application.ymlを使う。そのため、yamlを使うための依存関係を取り込めるよう、featureとしてyamlを明示的に指定する必要がある。
Micronaut Launch
https://micronaut.io/launch/
$ mn create-app \
--build=maven \
--jdk=21 \
--lang=java \
--test=junit \
--features=tracing-opentelemetry-http,validation,graalvm,azure-tracing,http-client,yaml \
dev.logicojp.micronaut.azuremonitor-metric
Micronaut Launchを使う場合、【FEATURES】をクリックして、
- tracing-opentelemetry-http
- validation
- graalvm
- azure-tracing
- http-client
- yaml
を選択した後、【GENERATE PROJECT】をクリックして【Download Zip】を選択すると、Zip形式でarchetypeを取得できる。
実装
実装コードはMicronaut Guidesのコードをそのまま利用できるが、以下の点を変更している。
a) Application Insightsへのtracing送信のために
(Metricについては前回の記事に記載したので省略)Traceについては、Micronaut 4.9.0から、micronaut-azure-tracingという機能パッケージが追加され、Application Insightsにtraceを送信するための機能が追加された。
<dependency>
<groupId>io.micronaut.azure</groupId>
<artifactId>micronaut-azure-tracing</artifactId>
</dependency>
ただこれは、Application Insightsに送信するための依存関係であり、この依存関係を入れ、Application Insightsの接続文字列を指定するだけでtraceを飛ばすことはできない。この依存関係が推移的に依存するものが以下の3個なのだが、これを見ると、trace収集・作成のための依存関係が必要であることがわかる。
com.azure:azure-monitor-opentelemetry-autoconfigureio.micronaut:micronaut-injectio.micronaut.tracing:micronaut-tracing-opentelemetry
今回はHTTPのtraceを取得したいので、HTTPのトレースを生成するための依存関係を追加しておく。
<dependency>
<groupId>io.micronaut.tracing</groupId>
<artifactId>micronaut-tracing-opentelemetry-http</artifactId>
<scope>compile</scope>
</dependency>
接続文字列はmetricの場合と異なり、azure.tracing.connection-stringに設定する(metric、traceを両方取得する場合には設定箇所が違うので、なんともあれな感じ)。もちろん環境変数での指定も可能。
azure.tracing.connection-string="InstrumentationKey=...."
azure:
tracing:
connection-string: InstrumentationKey=....
b) pom.xmlの変更
GraalVM Reachability Metadata Repositoryを利用できるよう、以下の依存関係を追加する。2025/07/23現在の最新は0.11.0。
<dependency>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>graalvm-reachability-metadata</artifactId>
<version>0.11.0</version>
<classifier>repository</classifier>
<type>zip</type>
</dependency>
GraalVM maven pluginを追加し、上記依存関係で取得したGraalVM Reachability Metadataを利用できるようにしておく。このpluginでは、buildArgを使って最適化レベルなども設定できる(この例では最適化レベルを指定)。もちろん、native-image.propertiesに追加すれば、native-imageツール(Maven/Gradle pluginも同じ)が読み取ってくれる。
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<metadataRepository>
<enabled>true</enabled>
</metadataRepository>
<buildArgs combine.children="append">
<buildArg>-Ob</buildArg>
</buildArgs>
<quickBuild>true</quickBuild>
</configuration>
</plugin>
c) Azure SDKで使っている依存関係とのバージョン衝突を避けるために
これは特にNettyやJacksonで発生することが多い。Native Image生成時のバージョン衝突を可能な限り避けたいのであれば、Micronautの場合、代替のコンポーネントを利用できることがあるので、その中から選択する。例えばNettyのバージョン衝突を回避したいのであれば、undertowなどを利用できる。
| Netty | undertow jetty Tomcat |
| Jackson | JSON-P / JSON-B BSON |
| HTTP Client | JDK HTTP Client |
これでひとまずJavaアプリケーションとしてビルドしておく。
mvn clean package
Javaアプリケーションとしての動作確認
問題なくアプリケーションが動作し、Application Insightsにtraceが送信されていることを確認する。このタイミングで、Tracing Agentを使ってアプリケーションを実行し、必要な構成ファイルを生成しておく。
# (1) reflect-config.jsonなどを取得
$JAVA_HOME/bin/java -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/{groupId}/{artifactId}/ -jar ./target/{artifactId}-{version}.jar
# (2)-a trace fileを生成
$JAVA_HOME/bin/java -agentlib:native-image-agent=trace-output=/path/to/trace-file.json -jar ./target/{artifactId}-{version}.jar
# (2)-b 作成したtrace fileからartifact固有のreachability metadataを生成
native-image-configure generate --trace-input=/path/to/trace-file.json --output-dir=/path/to/config-dir/
Configure Native Image with the Tracing Agent
https://www.graalvm.org/latest/reference-manual/native-image/guides/configure-with-tracing-agent/
Collecting Metadata with the Tracing Agent
https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/
以下のファイルを所定のディレクトリに作成する。
| ファイル | jni-config.jsonreflect-config.jsonproxy-config.jsonresource-config.jsonreachability-metadata.json |
| 場所 | src/main/resources/META-INF/native-imagenative-imageツールは、上記ディレクトリ以下にある構成ファイルを拾い出すが、以下のようにgroupId、artifactIdでディレクトリを切ったサブディレクトリにファイルを配置してビルドすることが推奨されている。 src/main/resources/META-INF/native-image/{groupId}/{artifactId} |
native-image.properties
mvn package -Dpackaging=native-image
でNative Imageを作成するが、クラスの初期化タイミング(ビルド時、実行時)やnative-imageツール(Maven plugin)へのコマンドラインオプション、JVM引数をnative-image.propertiesに設定する。pom.xml内にも記載できるが、こうした設定は外部化しておくことを推奨。このあたりはmetricのエントリでも記載しているので、詳細は省略する。
Native Imageのビルド
ビルドには時間を要するので、開発環境かつテストであれば、Quick Buildを有効にして、最適化レベルを-Obにすることを推奨する(それでも時間はかかる)。
Native Image Options
https://graalvm.github.io/native-build-tools/latest/maven-plugin.html#native-image-options
https://graalvm.github.io/native-build-tools/latest/gradle-plugin.html#native-image-options
Optimization Levels
https://www.graalvm.org/latest/reference-manual/native-image/optimizations-and-performance/#optimization-levels
Native Imageとしての動作確認
動作確認してみる。desktopの在庫を確認するために、以下の呼び出しを実行すると、
$ curl http://localhost:8080/store/inventory/desktop
{"warehouse":7,"item":"desktop","store":2}
Azure Monitor (Application Insights) のApplication Mapではこの通り。

Traceはこの通り。画面右側でカスタムプロパティも確認できる。

Orderを追加する。例えばdesktop5個の注文が入った場合、202 (Accepted) が返るので、さらにdesktopのOrderを確認するために、再度GETを呼び出すと、確かに5個増えてdesktopのOrderが7個に変わっていることがわかる。
$ curl -X "POST" "http://localhost:8080/store/order" \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{"item":"desktop", "count":5}'
$ curl http://localhost:8080/store/inventory/desktop
{"warehouse":5,"item":"desktop","store":7}
azuremonitor-trace内では、内部でHTTP Clientを使って POST /warehouse/order を実行している。Azure Monitor (Application Insights) のApplication Mapを見ると、azuremonitor-trace自身に対しての呼び出しが発生していることを確認できる。

Order登録時のTraceは以下の通り。

各Traceの詳細は赤枠で囲んだView allをクリックすると確認できる。
