[Dynatrace] Synthetic を使ってオークションのBidプライスをメトリクス化する

## 今回のテーマ
前回の投稿から2週間が経過しました、早いですね～。今回のテーマは、DynatraceのSynthetic（外形監視）を使う話です。Syntheticは、オブザーバビリティツールの代表的なものは大体装備されていると思います。24時間365日、自動的にWebサイトやAPIにアクセスし、速度計測や正常性確認を行ってくれる優れものです。Dynatraceにも、当然その機能はあります。が、Synetheticの特長のひとつに、アクションとして、JavaScriptをそのまま記述でき、活用出来るという点があります。「あるページのページロードを発生させる」、「ボタンをクリックする」、「Text入力する」といった組み込まれたユーザアクションの他に、JavaScriptコードを直接使うことができます。そのため、あるページのCSSやJavaScript variableの値を読み込み、それをあるAPI経由でデータをIngestするといった作業が登録できます。今日は、DynatraceのSyntheticが持つ、そのJavaScriptイベントを使ったお話です。

## やろうと思ったきっかけ
QiitaのBlogのテーマを何にするか考えていた際、ユナイテッド航空のキャンペーンメールが届きました。「ユナイテッド航空のマイルを使って、米国シカゴに行って、シカゴ・ホワイトソックスとロサンゼルス・ドジャースの試合を見よう！」という内容のものでした（下図参照）。このキャンペーンでは、ユナイテッド航空のマイルをつかったオークションプログラムで、エノコミークラス、プレミアムプラス（プレミアムエコノミーのこと）、ビジネスクラスの3つが用意されていました。ユナイテッド航空のマイルホルダーの私としては、ぜひ参加したいと思い！ましたが、毎回 bid price をクラス毎にWebサイトへアクセスして調べるのは面倒だなと思い、DynatraceのSyntheticを使って可視化できるようにしようと思い立ったわけです。

:::note info
このユナイテッド航空のキャンペーンは、既に終了しています。
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/6b810100-f7a3-0208-028a-5aeb99480a3c.png)

## でも、どうやってBidプライスをメトリクス化する？
冒頭でお話ししたとおり、DynatraceはSyntheticのアクションにJavaScriptが使えるため、この機能を活用していきます。Bidプライスをメトリクス化（可視化）するまでのステップは、以下の4つです。

1. オークションページにアクセス Synethtic を作成する
2. Webページに表示されている BidプライスのHTMLエレメントを確認し、プライス情報をJavaScriptで抜き取る
3. 一旦、Dynatraceのホームページにアクセスする
4. 抜き取ったBidプライスをメトリクス化するため、DynatraceのMetric Ingest APIにデータをPOSTする
5. DashboardsやNotebooksで、可視化する

以降、順番に詳しく見ていきましょう。

### 1\. オークションサイトにアクセスするSyntheticを作成する
まずは、Syntheticを作成します。今回のキャンペーンでは、3つのフライトクラスが用意されており、そのフライトクラス毎にWebページのアクセス先が異なるため、3つの Synthetic を作成します。エコノミー用、プレミアムクラス用、ビジネスクラス用の3つです。作り方は、こちらの[ヘルプ](https://docs.dynatrace.com/docs/shortlink/id-brower-clickpath-events "Browser clickpath events")をご参照下さい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/1ad096d5-f51e-de9b-63b2-af8d6737a46c.png)

最初のSyntheticイベントは、該当のキャンペーンページにアクセスすることなので、クラス毎に提供されるWebページのURLを「Navigate」アクションのURLに登録するだけで完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/79ce40c7-8627-a262-901f-7f2927c471f4.png)

### 2\. Webページに表示されている BidプライスのHTMLエレメントを確認し、プライス情報をJavaScriptで抜き取る
ここから Dynatrace の Synthetic の特長である、JavaSciptイベントの登場です。Webページに表示される現在のBidプライスをどうやって特定できるか見ていきます。ブログを書いている時点（2024年6月6日）では、すでにオークションサイトがクローズしているので、実際のBidプライスのHTMLがどのように表現されているかここでかくことはできませんが、オークションが実行されている期間に、私が調べると `currentprice.Bidding_Current_Price` という span エレメントで、一意にその情報を特定出来たので、下記のようにしてWebページにアクセスした際に、BidプラスをGrabするJavaScriptを定義します。「￥」記号や、カンマ「,」の表示を取り除く作業も、ここで対処します。

```ruby:Bidプライスの抽出
var bidding_current_price;

bidding_current_price = document.querySelector('span.currentprice.Bidding_Current_Price').textContent;

var price_value = bidding_current_price.split(' ')[0];
var final_value = price_value.replace(/\,/g, '');

api.setValue('final_value', final_value);

api.info(final_value); <<< Bidプライスが取れているかを確認するために使用（Debug目的）
```
### 3\. 一旦、Dynatraceのホームページにアクセスする
ステップ2で抜き取ったBidプライスをDynatraceで可視化できるよう、Metric Ingest APIにそれをPOSTするまえに、ひとつ大切なアクションを追加します。というのは、このステップを介さずに、JavaScriptイベントを追加して、データをPOSTしようとしても、エラーになるためです。

:::note warn
理由は、このJavaScriptはSynthetic上で動作する（ブラウザ上のDev toolのConsoleで実行しているのと同じ）ため、ブラウザがアクセスしているドメイン `united.com` とは異なるドメイン `xxxx.live.dynatrace.com` へ、JavaScriptを実行しようとするため、CORSエラーが発生するためです。
:::

この制約を解除するため、一旦 `www.dynatrace.com` へアクセスします。イベントとしては、Navigateイベントをここに追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/1963e443-0827-61f1-e33d-1f0e4df552ed.png)
なお、`www.dynatrace.com`へアクセスした際、Dev toolで Response-header を見ると、`Content-Security-Policy` に `*.dynatrace.com` が含まれているため、このサイトにアクセすると、`xxx.live.dynatrace.com` にJavaScriptが実行できることが分かります。

### 4\. 抜き取ったBidプライスをメトリクス化するため、DynatraceのMetric Ingest APIにデータをPOSTする
ここもDynatraceの特長のひとつではないでしょうか？DynatraceはいろいろなメトリクスをDynatraceに取り込めるよう [Metric Ingest API](https://docs.dynatrace.com/docs/shortlink/api-metrics-v2-post-datapoints) なる機能を持っています。このAPIにHTTP POSTで、ステップ2で抜き取ったBidプライスをフライトクラス毎に分割（Dimension）し、JavaScriptを使って送信します。以下、実際に使用したパラメータとJavaScriptです。

* Metric Ingest API
    * https://<my_tenant>.live.dynatrace.com/api/v2/metrics/ingest
* 付与するHTTP Header
    * Authorization: Api-Token <my_token>
    * Content-Type: text/plain
* メトリクス名
    * united.bidding_price
* Dimension
    * class=economy
    * class=premium
    * class=business
* Metrics value
    * final_value = step2 で取得しbid price

```ruby: Metric Ingest API call for economy class
var api_token = '<my_token>';

currentPrice = function() {
    url = 'https://<my_tenant>.live.dynatrace.com/api/v2/metrics/ingest';
    pdata = 'united.bidding_price';
    pdata += ',class=economy ';
    pdata += api.getValue('final_value');
    fetch(url, {
        method: 'POST',
        headers: {
            'Authorization': 'Api-Token ' + api_token,
            'Content-Type': 'text/plain'
        },
        body: pdata
    }).then(
        reply => reply.json()).then(obj => {
        api.info('Fetch response: ' + JSON.stringify(obj));
        api.finish();
    }).catch(
        e => {
            api.info('Oops! ' + e);
            api.finish();
        });
};

api.startAsyncSyntheticEvent();

try {
    currentPrice();
} catch (err) {
    api.error('Problem parsing resources: ' + err);
    api.finish();
}
```

DynatraceのJavaScriptイベントの強力なひとつの特長として、同じSynethicのシナリオの中であれば、変数を参照出来ることがあげられます。今回の場合であれば、Bidプラスはステップ2で収集して、`final_value` という変数に格納しました。その変数をステップ4のJavaScript内から呼び出せます。下記の部分が該当します。そのため、やろうと思えば何でもできる拡張性を備えています。

```
pdata += api.getValue('final_value');
```
### 5\.DashboardsやNotebooksで、可視化する
Syntheticで取れたBidプライスが、無事にDynatraceに取り込まれているか確認してみましょう。今回はNotebooksを使いました。DQL（Dynatrace Query Language）で、timeseries コマンドから united.bidding_price メトリクスを呼び出し、表示してみましょう。いいですね、いい感じで可視化できました！パチパチパチ👏👏👏

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/1f849026-7437-a589-50da-15c17a34a71d.png)

## まとめ
いかがでしたか？今回は、私の個人的な一通のメールをきっかけに Syntehtic + Metrics Ingest を実際に使ったブログを紹介しました。この記事でも何度も触れていますが、DynatraceのSyntheticの大きな特長として、JavaScriptのコードをイベントとして登録できるので、やりたいことの幅が大きく広がるのではないでしょうか？
最後のグラフを見ると分かりますが、結局このオークションではどのクラスもBidプライスが高騰し、エコノミープラスでも40万マイル以上必要になりました（ビジネスクラスに至っては、80万マイルまで高騰😭😭）。大谷翔平君の人気はすごいのと、みんなそんなユナイテッド航空のマイルを持っているんだという、2つの事実を改めて学んだ瞬間でした。

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

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