Amazon CloudWatch Application Signals 徹底解説

## はじめに
こんにちは、Datadog Japan で Sales Engineer をしている AoTo(@AoTo0330) です。

この投稿は **[<font color="#ee7800">Japan AWS Jr. Champions Advent Calendar 2023</front>](https://qiita.com/advent-calendar/2023/jr-champions) 3日目**の記事です。

AWS re:Invent 2023 で発表された多くの内容から、Observability や APM というキーワードに関連する重要な新機能を今回はご紹介します。その名も **<font color="#ee7800">Amazon CloudWatch Application Signals</front>** です！

https://aws.amazon.com/about-aws/whats-new/2023/11/amazon-cloudwatch-applications-signals-observe-preview/

## AWS X-Ray: AWS 上の Application Performance Monitoring(APM)
### 従来
そもそも、従来の AWS 環境で [APM](https://aws.amazon.com/jp/what-is/application-performance-monitoring/?nc1=h_ls) のような手法を実装するためには、[AWS X-Ray](https://aws.amazon.com/jp/xray/) を利用する方法が挙げられていました。

AWS X-Ray は名前の通り Amazon CloudWatch の機能群には**含まれておらず**、AWS 独自のアプリケーションパフォーマンス測定手法として提供されています。
簡単にそのアーキテクチャを解説すると、X-Ray は X-Ray daemon を中心に、SDK によるアプリケーションコードへの実装やツールやスクリプトを用いたアプリケーションデータを収集します。その後、X-Ray API を介してバッチ形式で AWS 上の X-Ray にアップロードをするという流れです。

![X-ray_ecosystem.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/a7cc7059-e4c5-2cfd-b41a-adec83f26c84.png)

実は、これらのツールは [Amazon CloudWatch ServiceLens](https://docs.aws.amazon.com/ja_jp/xray/latest/devguide/xray-console-servicemap.html)という形で統合することができ、実質的には CloudWatch との連携ができる状況でした。

https://aws.amazon.com/jp/about-aws/whats-new/2019/11/announcing-amazon-cloudwatch-servicelens/

しかし、X-Ray 自体は前述の通り **SDK をアプリケーションコードに実装**し、その上で **X-Ray deamon を用意する**必要があり、既存環境への組み込みは難しいという課題がありました。
これに対し、2023年の8月にはアップデートが行われ、CloudWatch Agent を用いることで **X-Ray と OpenTelemetry** によるトレース情報を収集できるようになっていました。 [^1]
[^1]: CloudWatch Agent のバージョン1.300025.0 以降でサポートされています。

https://aws.amazon.com/jp/about-aws/whats-new/2023/08/amazon-cloudwatch-agent-opentelemetry-traces-x-ray/

### これから
X-Ray と CloudWatch の統合の動きを見てわかる通り、AWS では CloudWatch を中心として[モニタリングとオブザーバビリティ](https://aws.amazon.com/jp/cloudops/monitoring-and-observability/)のエコシステムを築いています。

こうした流れで登場したのが、**<font color="#ee7800">Amazon CloudWatch Application Signals</front>** です！簡単にサービスの概要をまとめると、「OpenTelemetry による自動計装を CloudWatch を介して実装する方法 [^2]」です。　
[^2]:アプリケーションの自動計装と監視エージェントの統合は、Datadog をはじめとするオブザーバビリティベンダーでは先んじてデフォルトの手法となっています。

OpenTelemetry によるアプリケーションの計装は3年前の [**AWS Distro for OpenTelemetry(ADOT)**](https://aws.amazon.com/jp/otel/) が発表された時点から進んでいました。ADOT によるトレースのサポートは、今回のようなオブザーバビリティサービスの提供への布石だったように思います。

https://aws.amazon.com/jp/about-aws/whats-new/2020/10/announcing-aws-distro-for-opentelemetry-in-preview/

https://aws.amazon.com/jp/about-aws/whats-new/2021/09/aws-availability-distro-opentelemetry-tracing-support/

今後は、X-Ray と OpenTelemetry による自動計装・手動計装を組み合わせて APM を実現していく形になりそう、ということです。

<details><summary>解説：自動計装と手動計装</summary>
ここまでの解説で、登場した自動計装・手動計装というキーワードについて、簡単に解説をします。

APM のようにアプリケーションの処理を監視するためには、アプリケーション処理にかかった時間や処理の意味をログと比較して軽量なデータとして記録する必要があります。ここで利用されるのがトレースデータです。
トレースはアプリケーションへのリクエストの開始と終了時点、そしてそのステータスや処理内容を記録します。これを記録するための手法として自動計装・手動計装が必要ということです。

トレース：アプリケーションがリクエストを処理するのにかかった時間と、このリクエストのステータスを追跡するための情報。
スパン：特定の期間における分散システムの論理的な作業単位。複数のスパンでトレースが構成される。
自動計装：リクエストの開始終了時を記録するライブラリを利用して、自動的にトレースを記録する手法。
手動計装：アプリケーションコードに明示的にリクエストの開始終了を記録するよう記載し、トレースを記録する手法。

</details>


## Amazon CloudWatch Application Signals とは
ここからは、改めて **<font color="#ee7800">Amazon CloudWatch Application Signals</front>** について解説していきます。

### 概要
**Application Signals** は2024年6月に GA(一般提供)となりました

~~対応言語は Java のみです。これは、OTel による自動計装のサポート状況に依存するためですが、現在 **OTel** は Java の他に **.NET, Node.js, Python** の自動計装をサポートしており、**ADOT** では **Python** の自動計装が可能です。~~

~~そのため、今後は Python をはじめとする、様々な言語で **CW App Signals** を利用できるようになることが考えられます。~~
現在は、**Java, Pyhthon, .NET, Node.js** に対応言語を広げています。


AWS のインフラストラクチャでは Amazon EKS, Amazon ECS, Amazon EC2 でのサポートが明言されています。

:::note warn
2024年12月時点での情報を元に更新しています。
最新の情報は [AWS の公式ドキュメント](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Application-Monitoring-Sections.html)と [OpenTelemetry のドキュメント](https://opentelemetry.io/docs/what-is-opentelemetry/)をご参照ください。
:::

### 実装
実装方法は使用しているインフラストラクチャで変わります。

共通の前提条件としては、Application Singals を利用するためには、AWS 上で Application Signals による**サービスの検出**を行う必要があります。このロールは自動的に作成されますが、Application Signals に対し X-Ray, CloudWatch, Resource Tag の参照権限を付与する形となります。

#### Amazon EKS
EKS では、**Amazon CloudWatch Observability EKS アドオン**を有効化する必要があります。これは、EKS に CloudWatch Agent を自動的に組み込み、Application Singlas や [Container Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights.html)を利用するための機能です。

上記の2点が有効化されていると、CloudWatch コンソールからワークロードまたはネームスペースの単位でアプリケーションの自動計装を構成することができます。構成方法は、EKS に使用しているマニフェスト YAML ファイルに特定のアノテーション(`annotations: instrumentation.opentelemetry.io/inject-java: "true"`)を追加するだけです。

#### Amazon ECS
ECS では、**ECS タスクロール**と **ECS タスク実行ロール**に特定の権限を付与する必要があります。ここで必要となる権限は、ECS タスクが CloudWatch や X-Ray に対して情報を記録するための書き込み権限と、コンテナが SSM や CloudWatch にアクセスする権限です。

続いて、CloudWatch Agent によるトレース・ログ情報の受け取りを有効化します。これは ECS 上の CloudWatch Agent の構成ファイル(`/tmp/ecs-cwagent.json`)で設定可能です。

これらの前提条件の上で、CloudWatch Agent をサイドカー形式でデプロイすること、アプリケーションコンテナに ADOT を組み込むことを ECS タスク定義に含めることで、Java アプリケーションの自動計装が実現できます。

#### Amazon EC2
EC2 では、ECS と同様に CloudWatch と ADOT を組み込んでいく形式となります。

EC2 インスタンスにおける の IAM ロールには ECS タスクロールと同様に、CloudWatch や X-Ray に対して情報を記録するための書き込み権限を付与する必要があります。

EC2 上の CloudWatch Agent でも構成ファイル(`amazon-cloudwatch-agent.json`)にトレース・ログ情報を受け取る内容を追加します。

最後に、ADOT Java 自動計装エージェントにより、アプリケーションの自動計装を行います。
コンテナ環境では意識していなかった、エージェントの**ダウンロード・トレースのエクスポート・エンドポイントの指定など**を環境変数を使用して定義します。Java アプリケーションの**起動スクリプト**にこれらを指定して、アプリケーションの自動計装が完了します。

### 運用
これらの実装を経て、CloudWatch コンソール上でアプリケーションシグナルが参照できます。これによって今まで AWS ネイティブには監視が難しかった、アプリケーションレベルでのサービス・トポロジの監視が実現可能です。

#### アプリケーションサービスを監視する
[CloudWatch のサービスページ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Services-page.html)ではサービスという単位でアプリケーションの概要が表示されます。この概要は、障害率やレイテンシーをはじめとするアプリケーションの指標を可視化できます

[サービスの詳細ページ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ServiceDetail.html)を参照することで、詳細なメトリクス(処理毎のレイテンシーエラー率)や依存関係が確認できます。

#### アプリケーショントポロジを検査する
[サービスマップ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ServiceMap.html)によりクライアントとサービスの依存関係をマップにより確認できます。サービスマップはサービスの依存関係とともに、サービスのホストされている環境の情報を確認し、どこでなにが起きているかを把握することに役立ちます。

### Application Signals と他サービスの統合
先ほどは運用の面で他サービスについて触れませんでしたが、CloudWatch の他サービスの情報や AppRegistry により運用情報を Application Signals に集積し、サービスの検出と運用状態の監視を可能とします。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Services.html

#### SLOs
Application Signals では取得したアプリケーションメトリクスを サービスレベル指標(SLI)として定義し、これを元にサービスレベル目標(SLO)を　設定し、管理できます。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-ServiceLevelObjectives.html

#### CloudWatch Synthetic Monitoring
Sysnthetic では合成モニタリング・外形監視と呼ばれる手法でサービスの健全性を外部から監視することができます。
Synthetic Canary で X-Ray によるトレースを有効化することで、サービスのリクエストと処理の情報が関連づけられ、[サービスの詳細ページ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ServiceDetail.html)に表示されます。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_tracing.html

#### CloudWatch RUM
RUM はリアルユーザーモニタリングと呼ばれる手法で、Web アプリケーションのパフォーマンスに関するクライアントのデータをリアルタイムに取得できます。
Synthetic と同様に RUM でも X-Ray によるトレースを有効化することで、[サービスの詳細ページ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ServiceDetail.html)に表示をすることができます。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-modify-snippet.html#CloudWatch-RUM-xraytraceheader

#### AppRegistry
AppRegistry により監視対象のアプリケーションのメタデータを追加し、アプリケーションの管理責任や組織を明確にできます。この情報と Application Signals で自動検出された AWS リソースの情報を関連づけ、サービスが実行されているコンピューティングリソースとアプリケーションのメタデータを同様に参照できるようになります。

https://docs.aws.amazon.com/servicecatalog/latest/arguide/overview-appreg.html

## おわりに
**<font color="#ee7800">Amazon CloudWatch Application Signals</front>** は~~現在プレビュー版ですが~~GAしており、既にさまざまな既存の AWS サービスとの統合が提供されています。

今後は .NET, Node.js, Python などの言語へのサポート(サポート済)、AWS Lambda や AWS App Runner などの　AWS サービスへのサポート(追加なし)が追加されていくことで、ますます使いやすくなっていくはずです！


AWS のようなクラウドサービスプロバイダー(CSP)が積極的にオブザーバビリティ関連ソリューションを提供することで、オブザーバビリティがより一般的になればオブザーバビリティ業界に身を置く立場としてはとても嬉しいです:dog: