[Dynatrace] SAP BTP Cloud Foundry にDeployしたJavaアプリで分散トレーシングを実現する（その1）

## 今回のお題は「SAP BTP Cloud Foundry」です
前回のブログから1ヶ月くらい時間が経過してしまいました。2週間に一度投稿するという継続性の難しさを感じております。。。
SAP BTP Cloud Foundry はSAP社（エス・エー・ピー）が運営するManaged型のCloud Foundryプラッフォームです。最近は、K8sに押されてあまり目にすることが無くなった気もしますが、まだまだ日本のテンタープライズでは広く使われていると思います。「SAP BTP Cloud Foundry とはなんぞや？」、「SAP BTP Cloud FoundryにアプリをDeployする方法」などについては Qiita にも沢山記事がありますので、そちらを見て頂くと良いと思います。
私のお題は、SAP BTP Cloud Foundy runtime上に、アプリをDeployしたあとに、Dynatrace上でどうやってObservability（trace, log, metircs）を可視化するかという話です。
まずは「その1」でTrace、metricsを可視化するところまでお話します。その続編の「その2」で SAP BTP Cloud Foundry 上のログをDynatraceに転送して、可視化、検索する方法についてお話します。全編で2つです（少なっ！）

## 前提条件
この記事を読みにあって、準備すべき前提条件は、以下4点です。
1. Dynatraceのテナントを持っている
2. SAP BTPにアカウントを持っていて、Cloud Foundy が使えるようになっている（Orgなどの設定が終わっている）
3. 自身が使う端末 or teminal に cf コマンドがインストールされている
4. Java sample application をローカル環境に clone している（GitHub上の spring-music を使います）

https://github.com/cloudfoundry-samples/spring-music

## Sprig-music をDeployする前に、Dynatraceのセットアップ
SAP BTP Cloud Foundry 上にJavaアプリをDeployする前に、SAP BTP Cloud Foundry 側でDynatraceのOneAgentとJavaアプリを紐付けるための、services を作成しておきます。Serviceの作成方法は、弊社の下記ヘルプに記載があります。

https://docs.dynatrace.com/docs/setup-and-configuration/setup-on-container-platforms/cloud-foundry/deploy-oneagent-on-sap-cloud-platform-for-application-only-monitoring

以下、この手順に従って設定していきます。

### Step-1: User provided-service を作成する
アプリをDeployした際、DynatraceのOneAgentをアプリにBindさせ、可視化するためのServicesを Cloud Foundry の Org 内で作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/8f149ec7-d6c7-29d2-d7f8-8a17f72d8eda.png)
インスタンスに付与する詳細情報を求められるので、それらをJSON形式で貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/9f25e91c-3532-b144-e21e-9acdb4885223.png)
それぞれのパメラータの意味は、このようになります。`tag` は任意ですが、DynatraceでのUI上で表示させる際に、見やすくするために今回は付与しています。
<table>
  <caption>User-defined service</caption>
  <thead>
    <tr>
      <th>パラメータ</th> <th>値</th>
    </tr>
  </thead>
  <tr>
    <td> environmentid </td>
    <td>自身が持っているDynatraceのテナントURL（必須）</td>
  </tr>
  <tr>
    <td> apitoken </td>
    <td>自身が持っているDynatraceのテナントで作成したToken（必須）</td>
  </tr>
  <tr>
    <td> tag </td>
    <td> Dynatrace UI上で対象アプリを表示させた際に付与するタグ（任意）</td>
  </tr>
</table>

### Step-2: Java のアプリとUPS（User-provided service）をバインド（紐付ける）する
冒頭で記述した `spring-music` サンプルアプリの clone フォルダにある `manifest.yaml` を編集し、JavaアプリとStep-1の `dynatraceserve` を紐付けます。
```ruby:manifest.yaml
---
applications:
- name: spring-music
  memory: 1G
  random-route: true
  path: build/libs/spring-music-1.0.jar
  services:
  - dynatraceservice
  env:
    JBP_CONFIG_SPRING_AUTO_RECONFIGURATION: '{enabled: false}'
    SPRING_PROFILES_ACTIVE: http2
    JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 17.+ } }'
```
### Step-3: Java アプリをローカルでBuildする
GitHubの手順に従い、`gradlew clean assemble` コマンドでアプリをBuildし、jar ファイルを作成する

```ruby:gradlew clean assemble
yasusuzu@DT:spring-music$ ./gradlew clean assemble
Downloading https://services.gradle.org/distributions/gradle-7.6.2-bin.zip
...........10%............20%...........30%............40%............50%...........60%............70%............80%...........90%............100%

Welcome to Gradle 7.6.2!

Here are the highlights of this release:
 - Added support for Java 19.
 - Introduced `--rerun` flag for individual task rerun.
 - Improved dependency block for test suites to be strongly typed.
 - Added a pluggable system for Java toolchains provisioning.

For more details see https://docs.gradle.org/7.6.2/release-notes.html

Starting a Gradle Daemon (subsequent builds will be faster)

BUILD SUCCESSFUL in 1m 13s
5 actionable tasks: 4 executed, 1 up-to-date
yasusuzu@DT:spring-music$ ls -la build/libs/spring-music-1.0.jar 
-rwxrwxrwx 1 yasusuzu yasusuzu 69224157 Jun 30 15:17 build/libs/spring-music-1.0.jar
yasusuzu@DT:spring-music$
```

### Step-4: cf push で JavaアプリをSAP BTP Cloud Foundry 上にDeployする
あとは、`cf push` コマンドで、JavaアプリをDeployするだけです。
```ruby:cf push
yasusuzu@DT:spring-music$ cf push
Pushing app spring-music to org <my org> / space Dev as yasuyuki.suzuki@pm.me...
Applying manifest file spring-music/manifest.yml...

Updating with these attributes...
  ---
  applications:
  - name: spring-music
    path: spring-music/build/libs/spring-music-1.0.jar
    memory: 1G
+   random-route: true
    env:
      JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 17.+ } }'
      JBP_CONFIG_SPRING_AUTO_RECONFIGURATION: '{enabled: false}'
      SPRING_PROFILES_ACTIVE: http2
+   services:
+   - dynatraceservice
Manifest applied
Packaging files to upload...
Uploading files...
 819.38 KiB / 819.38 KiB [======================================================================================================] 100.00% 1s

Waiting for API to complete processing files...

Staging app and tracing logs...
   Downloading java_buildpack...
   Downloaded java_buildpack
<...中略...>
===> OneAgent が自身のテナントからダウンロードされるメッセージが表示
   [InternetAvailability]           WARN  Internet availability temporarily set to true: The Dynatrace One Agent download location is always accessible
   -----> Downloading Dynatrace One Agent latest from https://<my tenant>.live.dynatrace.com/api/v1/deployment/installer/agent/unix/paas/latest?include=java&bitness=64&Api-Token=*** (3.9s)
   Expanding Dynatrace OneAgent to .java-buildpack/dynatrace_one_agent (0.6s)
   Exit status 0
   Uploading droplet, build artifacts cache...
   Uploading droplet...
   Uploading build artifacts cache...
   Uploaded build artifacts cache (132B)
```
Deploy終了後、`cf apps` コマンドでアプリの状態を確認し、`cf service dynatraceservice`コマンドでserviceがアプリにBindされているかを確認します。
```ruby:cf apps
yasusuzu@DT:spring-music$ cf apps
Getting apps in org <my org> / space Dev as <login id>...

name           requested state   processes           routes
spring-music   started           web:1/1, task:0/0   <random-route>.cfapps.jp20.hana.ondemand.com
yasusuzu@DT:spring-music$
```
その後、`cf service dynatraceservice` コマンドを実行し、spring-music にBindされているか確認します。下記の通り、`create succeeded`とあるのでちゃんと動いていますね。
```ruby:cf service dynatraceservice
yasusuzu@DT:spring-music$ cf service dynatraceservice
Showing info of service dynatraceservice in org <my org> / space Dev as <login id>...

name:                dynatraceservice
guid:                452c9172-7460-42c6-99b1-d38ceafa7cdc
type:                user-provided
tags:
route service url:
syslog drain url:

Showing status of last operation:
   status:    update succeeded
   message:   Operation succeeded
   started:   2024-03-03T12:20:34Z
   updated:   2024-03-03T12:20:34Z

Showing bound apps:
   name           binding name   status             message
   spring-music                  create succeeded            <<<<< OKな状態

yasusuzu@DT:spring-music$
```
### Step-5: DynatraceのUIで確認
- まずは「ホスト」画面を確認
いいですね。CFのコンテナが、ホストとして見えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/f5ecc95b-1e3b-5147-7699-1ff8a2c74e15.png)
- 次に「プロセス」画面を確認
先ほど user-defined service で指定したタグがちゃんと見ていますね。これで、このアプリがどこのCF環境で動いているか、ぱっと見で分かるようになります。JavaのJVMのメトリクス（Heap, suspensionなど）も全部見えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/d9991e34-cd87-1295-d47d-fbec1fa72d29.png)
- Web ブラウザでアプリにアクセスし「Services」画面を確認
DynatraceのOneAgentが自動的にサービスのEntry Pointを見つけ、可視化してくれています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/b46fd505-ce04-3057-a519-703887ae9590.png)
試しに、Album情報を追加してみると、Updateメッセージが表示されていますね。きちんと、DynatraceのOneAgentがWebリクエストをキャプチャしてくれて、応答時間などを自動的に計測しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/dfa2585f-483c-285a-cb43-b94f1b9bb818.png)
W3C TraceIDをクリックすると、分散トレーシングの画面が表示され、各Spanのタスクの長さが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/aa13aa6d-f948-581c-1e5f-7fd2f8630d93.png)
更に、JavaのAlbumControllerをクリックし、「Code level」タブをクリックすると、code level でどこでどれくらいの時間を要していたかも表示してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/c8f65567-8b64-0af5-e513-5170c9806ab8.png)

## まとめ
いかがでしょうか？今回は、SAP BTP Cloud Foundry 上に、JavaアプリをDeployして、Javaアプリの分散トレーニングの方法についてまとめました。JavaのJVMメトリクス、ホストメトリクスからサービスの応答時間やJavaアプリ内のコードの実行時間に至るまで、いわゆるObservabilityの2本柱（メトリクス、トレース）をDynatraceのOneAgentを使って実現しています。冒頭でお話ししたとおり、Cloud Foundry 自体は Kubernetesと比較するとややマイナーの存在になってしまっている気がしますが、manifest.yaml と アプリのコードだけで、Deployできるという観点では、コンテナの存在をそれほど意識しなくて良いというメリットがあると思います。ただ、簡単にトレースやアプリのRuntime情報を収集、可視化できるツールがないので、いろいろお悩みの方も多いのかな？と勝手に想像しています。
次回は、アプリが出力するログやSAP BTP Cloud FoundryのログをDynatraceに転送、取り込む方法についてお話したいと思います。これができると、Observabilityの3本柱すべてが一つのプラットフォーム上で実現できるので、運用管理がしやすくなると思います。

まだ、Dynatraceを触ったことがない方、このブログを見てやってみたいと思われた方は、下記フリートライアルにてお試し下さい。↓↓↓

Dynatraceフリートライアル → https://www.dynatrace.com/ja/trial/