Akamai DataStream 2のログをElasticsearchとKibanaで可視化する

# Akamai DataStream 2とは
Akamai DataStream 2とは、Akamaiのエッジプラットフォームのアクセスログを指定した宛先へ準リアルタイムにストリーミングする無償の機能です。2023年11月現在、以下の宛先にアクセスログを配信できます。

- Amazon S3
- Azure Storage
- Custom HTTPS endpoint
- Datadog
- Elasticsearch
- Google Cloud Storage
- Loggly
- New Relic
- Oracle Cloud
- S3-compatible destinations (Linode Object Storage対応可)
- Splunk
- Sumo Logic

**参考: [DataStream 2 - Stream logs to a destination](https://techdocs.akamai.com/datastream2/docs/stream-logs)**

# Elasticsearch / Kibanaとは
ElasticsearchとはElastic社の開発する全文検索エンジンです。ソースコードが公開されており、Server Side Public LicenseとElastic Licenseというデュアルライセンスで提供されています。KibanaはElasticsearch用のデータ可視化ソフトウェアで、Elasticsearchと同等の条件で提供されています。この2つのソフトウェアにLogstashと呼ばれるデータ収集パイプラインソフトウェアを組み合わせたものはELK Stackと呼ばれ、元々の用途である全文検索エンジンから発展して現在ではログ分析、データ可視化基盤としても人気があります。

# この記事の目的
この記事では、Akamai DataStream 2のデータをLinode上にセットアップしたElasticsearchへ準リアルタイムに配信し、Kibanaによってこれを可視化します。この記事の手順によって最終的には以下のようなダッシュボードが完成し、[DataStream 2に含まれる45個のフィールド](https://techdocs.akamai.com/datastream2/docs/data-set-parameters)のうち、代表的なものがグラフ化されます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/2b1c1846-62cb-eafe-826c-9299eea7606c.png)
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/e5849c1c-aa3b-26eb-795d-c4de9b6e5cf1.png)

また、この記事では環境構築先としてAkamaiが2022年2月に買収したIaaS (Infrastructure as a Service)プロバイダーである[Linode](https://www.linode.com/)を使用します。LinodeにはStackScriptsという独自のデプロイメント自動化機能があり、アクセスログを受信するElasticsearch+Kibanaの準備を10分程度で完了させることができます (DataStream 2の初回設定時、ログの配信が開始されるまでに別途約1時間半程度の待ち時間が発生します)。

**参考: [Linode StackScriptsとは何か](https://qiita.com/isss802/items/d6e59063d3473659983d#stackscripts%E3%81%A8%E3%81%AF)**

なお、この記事ではElasticsearchとKibanaの環境を一から構築する方法を説明していますが、すでにこれらの環境を運用していて、Akamai DataStream 2用のElasticsearchのIndex Mapping、KibanaのData View、Visualization、Dashboardの定義ファイルだけが必要な方向けに、これらをGitHubでも公開しているのでダウンロードしてお使いください。

**[ElasticsearchとKibanaの定義ファイル](https://github.com/hokamoto/stackscripts/tree/main/elasticsearch-kibana)**

# LinodeにElasticsearchとKibanaをインストールする

まずは以下のリンクから事前に準備しておいたStackScriptを開きます。このStackScriptがElasticsearch、Kibanaを自動的にインストールします。(リンク先にアクセスするにはLinodeのアカウントにログインしておく必要があります)

**elasticsearch-kibana-for-akamai-datastream2**
https://cloud.linode.com/stackscripts/1059555

※もし何らかの理由でこのStackScriptを開くことができなければ、このStackScriptの中身を[GitHubにもアップロードしている](https://github.com/hokamoto/stackscripts/blob/main/elasticsearch-kibana.sh)のでご使用ください。

「Deploy New Linode」をクリックします
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/390e83a4-9c6e-75a1-d42a-afd05695b3cb.png)
StackScriptにはUDF(ユーザー定義フィールド)という、デプロイメントにあたって必要なパラメータを自動的にWebの入力フォームにする機能があります。このStackScriptでは、仮想マシンにSSHログインできる非rootのユーザーのログイン情報や、ElasticsearchやKibanaの管理ユーザーのパスワード、DataStream 2がログをElasticsearchにフィードするための認証情報を仮想マシンのデプロイメント時に指定できるようになっています。以下のテキストボックスに必要事項を入力しておきます。ここで入力した値は後ほど使用するので内容を控えておきます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/b5fd9a29-4386-8868-fe46-9f2840697123.png)
仮想マシンを作成するリージョンと、仮想マシンの種類を選択します。ここでは日本の東京リージョンでDedicated 8 GBのLinodeを選択しています。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/e9bdc2cb-7f75-4fef-5f69-d911815a6bd2.png)
仮想マシンの名前、rootパスワードを指定して「Create Linode」をクリックします
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/67f29cde-0666-880c-d4fd-222d2a2b20a5.png)
仮想マシンの管理ダッシュボードに画面が遷移するので、仮想マシンの状態がPROVISIONINGからRUNNINGになるまで数分待ちます。同じ画面に今作成した仮想マシンのIPアドレスが表示されているので控えておきます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/ae0078d6-fd35-e279-356e-f87f68c860d7.png)
また、後のDataStream 2の設定手順で必要になるので仮想マシンのNetworkタブから仮想マシンのReverse DNSの値を調べて控えておきます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/b890cafa-01a3-456f-4dfc-6458fabc6bef.png)
これで仮想マシンが起動しました。起動した後はStackScriptに沿って必要なソフトウェアのインストールがバックグラウンドで自動的に進みます。インストールが終わるまで10分ほど待ってから次の「Kibanaにログインする」に進みます。

## Kibanaにログインする
それではKibanaにログインできることを確認します。Webブラウザーから`http://[仮想マシンのIPアドレス]:5601/`にアクセスします。ログインユーザーは`elastic`、パスワードは仮想マシンのデプロイメント時に指定したものを入力します。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/cf4be4b8-03bd-523b-7698-ae1bd01f960f.png)
左上のハンバーガーボタンでメニューを表示し、Analytics → Dashboardをクリックします。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/f3383de2-a145-a8af-b707-0f277faed8af.png)
StackScriptによって「Akamai」という名前のダッシュボードが自動作成されているので、それを開きます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/efdaa612-bde7-1188-3558-f229957f00e6.png)
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/f5ba5b9c-ebd6-9c0f-29c6-12d59e5c12f4.png)
上記のようにダッシュボードが表示されれば成功です。この時点ではまだDataStream 2のセットアップをしていないため何もデータがありませんが正常です。

# DataStream 2をセットアップする
Akamaiの管理コンソールAkamai Control CenterからDataStream 2のセットアップをしていきます。左上のハンバーガーボタンでメニューを表示し、COMMON SERVICES → DataStreamをクリックし、以下の流れでCreate streamします。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/cc83e114-4143-9795-2bac-fcf6a0ec86e9.png)
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/dc05839c-fb7a-b9db-2729-3430ad6404f9.png)
DataStream 2に名前をつけて、ログの配信を有効化したい配信プロパティにチェックを入れます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/6469ec4b-5374-49ba-e62d-8ed7ce993336.png)
送信するアクセスログのフィールドを選択する画面が表示されるので、ここでは例として全てのカテゴリで「Include all」にチェックを入れます。2022年9月時点で合計45個のフィールドが選択されます。また設定画面の最下部でログのフォーマットとして「JSON」を選択します。

:::note warn
個人情報保護法等の関連法令を考慮して収集するログの内容を選択してください
:::
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/9729ec38-893b-40b9-acca-3c04db80c13a.png)
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/9280c2a6-6a92-83ad-29ed-d8267f381fab.png)
次にDataStream 2の宛先を設定します。Destinationは`Elasticsearch`、Display nameには任意の名前、Endpointには仮想マシン作成時に控えておいたReverse DNSのホスト名を用いて `http://[Reverse DNSのホスト名]:9200/_bulk`、Index nameに`datastream2`、UsernameとPasswordには仮想マシンのデプロイ時に入力した「Akamai DataStream 2がElasticsearchにログをフィードする際に使用するユーザー」のユーザー名とパスワードを入力します。Send compressed dataにもチェックを入れ、右下の「Validate & Save」ボタンをクリックしてください。全ての設定値が正しいと右下に「Destination details are valid」という文字列が表示され画面が切り替わります。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/6e644c15-4e02-05f5-0c4a-465ab94c0a76.png)
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/9bf23db2-049a-3832-558e-ee8abbc049e0.png)
最後に設定のサマリーが表示されるので期待通りの設定になっているか確認します。「Activate stream upon saving」にチェックを入れておきます。また、DataStream 2によるログの配信開始まで約1時間半かかります。ログの配信開始通知をメールで受け取りたい場合は「Receive an email once activation is complete.」にチェックを入れてメールアドレスを入力します。全て問題なければ右下の「Save stream」をクリックします。DataStream 2の有効化処理がはじまると、プロパティマネージャー側でもDataStream 2の設定が必要であることを示すメッセージが表示されるので、今設定したDataStream 2の名前を控えた上で「Proceed to Property Manager」をクリックします。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/cf2cccd9-5c48-948d-7b73-2c5faf229f16.png)

# プロパティでDataStream 2を有効化する
_※この節の解説は、Akamaiプロパティマネージャーの基本的な操作方法を理解しているという前提で書かれています。_

DataStream 2によるログの配信は、プロパティ側でもDataStream 2のBehavior(動作)を追加し、プロパティをActivation(有効化)する必要があります。上述の手順でDataStream 2のセットアップが完了したら、プロパティの新しいバージョンを作成して、デフォルトルールに「DataStream」「Log Request Details」の Behaviorを追加し、以下の設定例を参考に設定をします。この作業はDataStream 2が有効化されるまでの待ち時間に並行して実施できます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/a9b77761-25c0-d35b-2804-316cb2e98bbd.png)

<table>
  <tr>
    <th>Stream version</th><td>DataStream 2</td>
  </tr>
  <tr>
    <th>Stream names</th><td>DataSteam 2のセットアップ時に指定した名前</td>
  </tr>
  <tr>
    <th>Sampling rate</th><td>ログを送信する割合 (100で全てのログを送信)</td>
  </tr>
  <tr>
    <th>Log *** Header</th><td>リクエストに含まれる当該ヘッダーを収集するかどうか</td>
  </tr>
  <tr>
    <th>Cookie Mode</th><td>リクエストに含まれるCookieを収集するかどうか</td>
  </tr>
  <tr>
    <th>Include Custom Log Field</th><td>カスタムのログフィールドを追加するかどうか</td>
  </tr>
  <tr>
    <th>Custom Log Field</th><td>カスタムのログフィールドに入れる値 (ここでは例として通信に使用しているTLSのCipher Suiteの名前を含めていますが、空欄でも構いません)</td>
  </tr>
  <tr>
    <th>Log Akamai Edge Server IP Address</th><td>リクエストを処理したエッジサーバーのIPアドレスを収集するかどうか (これは必ずOnにしてください)</td>
  </tr>
</table>

:::note warn
個人情報保護法等の関連法令を考慮して収集するログの内容を選択してください
:::

設定が終わったらプロパティを保存してActivationします。DataStream 2とプロパティの両方が有効化されると、アクセスログがKibanaに表示されはじめます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/2b1c1846-62cb-eafe-826c-9299eea7606c.png)

**お疲れさまでした! これでAkamaiのアクセスログを準リアルタイムに見られるようになりました**

今回使用したStackScriptはアクセスログに含まれる代表的な値を可視化するダッシュボードを作成しますが、DataStream 2がフィードするアクセスログには他にもさまざまなフィールドが含まれています。これをベースにKibanaのGUI上でダッシュボードをカスタマイズするのも良いでしょう。

# 発展的な使い方

## 条件付きのアクセスログ送信
全てのアクセスログをDataStream 2でログの分析基盤にフィードし、ログの分析基盤側で必要性に応じた条件で絞り込んでいくことが一般的な使い方ですが、一定の条件を満たしたログのみをDataStream 2でフィードするということも可能です。これはログの量が膨大でログの分析基盤側の負荷を軽減したい場合や、正常系の通信のログにあまり興味がなく異常系のログのみを見たいという場合に有用です。実装例として、たとえばAkamaiのプロパティのデフォルトルールからDataStream 2のBehaviorを削除し、以下のような条件でDataStream 2を有効化するように実装すると、リクエスト先が`/foo/bar/`配下でレスポンスコードが`200` `206` `304` 以外のときのみログをDataStream 2で飛ばすということができます。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/02eea9b0-b930-21fd-eaec-4ef3b99617f6.png)

## カスタムフィールドの活用
DataStream 2がフィードするアクセスログには、カスタムフィールドと呼ばれるフィールドが存在します。ここには1000バイトまで任意の文字列を追加できるので、エッジサーバーが持つビルトイン変数やプロパティのユーザー変数を含めることができます。

**参考: [プロパティマネージャーのビルトイン変数一覧](https://techdocs.akamai.com/property-mgr/docs/built-vars)**

たとえば以下の例ではカスタムフィールドに「エッジからクライアントにレスポンスを全て返すまでにかかった転送時間」を含めています。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/f4d9c16c-73b1-61af-74a7-3f27443af218.png)
この値をKibanaのData ViewでRuntime fieldとしてパースすることで、新しいフィールドにすることができます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/4d8cb8d2-4ce8-0056-85ac-c14cacf7bf40.png)
```
String ctt=dissect('ctt:%{ctt_val}').extract(doc["customField"].value)?.ctt_val;
if (ctt != null) emit(Integer.parseInt(ctt)); 
```
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/16380936-e61b-f3b1-e52d-fd8a7211bfcf.png)

また、Akamaiのエッジ上で動作するエッジ・コンピューティング・プラットフォームである[EdgeWorkers](https://techdocs.akamai.com/edgeworkers/docs)を使うと、JavaScript ベースのコードで、任意のユーザー変数をセットできます。それをカスタムフィールドに含めることで、EdgeWorkersアプリケーションのデバッグ情報やビジネスロジック上興味のある値などをログの分析基盤で集計することができるようになります。2023年6月現在、カスタムフィールドの長さは1000バイトまでという制約があることに注意してください。

**参考: [Request Object setVariable()](https://techdocs.akamai.com/edgeworkers/docs/request-object#setvariable)**

## EdgeWorkersのデバッグ
EdgeWorkersでは各種の制約(CPU時間、メモリ使用量、実行時間など)を超えると動作が途中で打ち切られます。これを踏まえて実際に運用してみると、リクエストの内容に依存した特定条件下でのみ正しく動作しないという状況に遭遇することがあります。エラーの統計情報はAkamaiのポータルサイトであるAkamai Control Centerから確認できますが、エラー発生時のリクエスト情報の詳細は見られません。DataStream 2を使えば、エラーが発生した際のリクエスト情報のみならず、EdgeWorkersランタイムの詳しい動作状況が`ewExecutionInfo`と`ewUsageInfo`というフィールドに載るため、トラブルシューティングに役立ちます。

**参考: [DataStream 2 log details](https://techdocs.akamai.com/edgeworkers/docs/datastream2-reports)**
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/084fdce6-2fb1-8fa1-1340-010dbc91f533.png)

## Web Application Firewallの検知状況の監視
AkamaiのWeb Application Firewall (WAF)には、Web Security Analytics (WSA)と呼ばれる高度なログ分析機能がついているため、サイバー攻撃の分析はほとんどの場合WSAだけで完結します。その一方で、DataStream 2にもWAFの検知状況の概要がログのフィールドに含まれているので、DataStream 2でしか見られないフィールドを活用して補完的な分析をしたり、ログのフィード先である分析ツールに含まれる機械学習などの高度な機能を活用することができたりします。以下の画面は、ディレクトリ・トラバーサル攻撃をWAFが検知し、その情報がDataStream 2のデータから確認できる様子です。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/34b36e43-46fc-e832-6606-192482d783a5.png)

## Common Media Client Data (CMCD)の可視化

Common Media Client Data (CMCD)は、動画プレーヤーが収集した様々なメトリクスをCDNのエッジサーバーやオリジンサーバーに送信するための標準化されたデータフォーマットです。CTA WAVEプロジェクトは2020年9月にCMCDの仕様を公開しました。

[Web Application Video Ecosystem - Common Media Client Data (英語)](https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf)

CMCDをサポートする動画プレーヤーは、HTTPのリクエストヘッダーやクエリパラメーターを通じて様々な情報をサーバーに送信します。Akamai Adaptive Media Delivery (AMD)を使っている場合、DataStream 2のログにCMCDのフィールドを追加することができ、この記事で構築したElasticsearch + Kibanaで動画の再生品質や各種情報を可視化することができます。これにより、既存の動画QoS/QoE測定ツールから得られる情報に加えて、Akamaiのログと品質メトリクスを相関させることが可能になります。CMCDの使用の利点についての詳しい情報は、以下の記事も参照してください。

[Get More from Your Player Analytics and CDN Logs with CMCD (英語)](https://www.akamai.com/blog/cloud/get-your-player-analytics-with-cmcd)

多くの動画プレーヤーはCMCDをクエリパラメーターとしてサーバーに送信する実装になっていますが、リクエストヘッダー経由でCMCDデータを送信したい場合は、AMDでCORSヘッダー設定を追加する必要があります。CORSヘッダーを変更するには以下のガイドを参照してください。

[Common Media Client Data (英語)](https://techdocs.akamai.com/adaptive-media-delivery/docs/common-media-client-data-amd)

※2023年4月19日に、この記事で参照されているStackScriptを更新しました。この日付以降にStackScriptを使用してElasticsearch + Kibanaをインストールすると、CMCDをサポートするインデックステンプレート、データビュー、ダッシュボードも作成されます。

![CMCDダッシュボード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/01401e26-3188-96d9-a9c4-be8119736a25.png)
![CMCDのフィールド](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19811/572d193f-05c1-1692-84b3-c07ea68d25d8.png)

# 実運用に向けての考慮点
この記事では説明をシンプルにするために実運用においては配慮すべき点をいくつかカバーできていません。実運用に際してはたとえば以下の点を考慮する必要があります。

- [DataStream 2のログ転送エラーアラートの有効化](https://techdocs.akamai.com/datastream2/docs/set-up-alerts)
- ElasticsearchのAPIエンドポイントのHTTPS化
- Elasticsearchノードの冗長化
- Linode Block Storageを使った仮想マシンの追加ストレージの確保
- アクセスログのライフサイクル管理

この記事ではSSL証明書の取得手順を省略するためにElasticsearchのHTTPSを無効化しています。実運用に向けては正式なSSL証明書を取得してDataStream 2からElasticsearchへの通信をHTTPS化することを推奨します。DataStream 2は自己署名証明書を受け入れないので、Elasticsearchに正規の認証局が発行したSSL証明書をデプロイする必要があります。「Elasticsearch Let's Encrypt」などのキーワードでインターネットを検索すると関連情報が見つかります。

また、HTTPSを無効化するためにStackScriptがElasticsearchの設定ファイルを書き換えているので、再びHTTPS対応にするためにはSSL証明書のデプロイと併せて`/etc/elasticsearch/elasticsearch.yml`にある`xpack.security.http.ssl`の`enabled`フラグを`true`にする必要があります。その後DataStream 2の設定を変えて、アクセスログをフィードする宛先のエンドポイントを`http://`から`https://`にします。

# 補足情報
- [DataStream 2の`errorCode`フィールドの値一覧](https://techdocs.akamai.com/edge-diagnostics/docs/error-codes)
- [プロパティマネージャーのビルトイン変数一覧](https://techdocs.akamai.com/property-mgr/docs/built-vars)

# 関連記事
アカマイ・テクノロジーズ合同会社のQiitaではLinode関連など開発者向けの記事を記載しております。

https://qiita.com/organizations/Akamai