EdgeWorkersで実現するEdge Side Monitoring

## はじめに
　アカマイのモニタリングツール「mPulse」を活用することで、実ユーザーデータを収集・可視化することができます。mPulseはユーザ体感データなどを収集しそれを送信するために、ブラウザ上でJavaScriptコードを実行します。そのため、API通信のようなJavaScriptが実行できない環境からのクライアントのデータはｍPulseサーバーへ送信できません。

本記事では、クライアント環境でJavaScript実行に制約がある場合、代わりにアカマイエッジサーバーで、収集可能なデータをEdgeWorkers上でmPulse APIをCallすることでEdge Side Monitorinigを実現する方法を説明します。

### アカマイCDNプロパティの設定
アカマイCDNのPropertyに以下の3つの設定（ユーザ変数、ｍPulseの設定、及びEdgeWorkersの設定）を有効化します。

1.ユーザ変数の追加
EdgeWorkersから参照するユーザ変数を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820036/c3aa0155-7a83-a619-5bd7-aa6aca5cbe20.png)

2.ｍPulseの設定追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820036/df72aa6f-88ac-22b1-09ce-fccc0e5d2d36.png)
mPulseを利用するためのAPIキーが必要です。mPulseのポータルにログインし、監視対象のWeb Appの設定画面にあるAPI Keyを使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820036/3052647c-d683-cdaf-ed00-34127d02a4cf.png)


3.EdgeWorkers設定追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820036/f2919de0-e3a8-b7ea-e4db-d97c3a58d255.png)

### EdgeWorkersのコード
クライアントとEdge間のラウンドトリップタイム（RTT)及びリクエストのターンアラウンドタイム（TAT）を収集しｍPulseへ送信するサンプルコードです。
　　＜このコードは[Github](https://github.com/akamai/edgeworkers-examples/tree/master/edgecompute/examples/tracking/mpulse-integration)からも参照できます。＞

```javascript
import { httpRequest } from 'http-request';
import { logger } from 'log';

// mPulse App
const API_KEY = 'YOUR API KEY';
const DOMAIN = 'YOUR DOMAIN';
const RTT_INDEX = '0'; // YOUR CUSTOM TIMER INDEX FOR ROUND TRIP TIME
const TAT_INDEX = '1'; // YOUR CUSTOM TIMER INDEX FOR TURNAROUND TIME
const DEVICE_INFO = 'brand'; // YOUR CUSTOM DIMENSION FOR DEVICE INFO
const GEO = 'city'; // YOUR CUSTOM DIMENSION FOR GEO LOCATION
const STATUS = 'status'; // YOUR CUSTOM DIMENSION FOR STATUS CODE
const PAGEGROUP = 'top'; // YOUR PAGE GROUP

export async function onClientRequest(request) {
    // Mark Timer on PM Variable during onClientRequest
    const reqStartTime = Date.now();
    request.setVariable('PMUSER_REQSTART', reqStartTime);
}

export async function onClientResponse(request, response) {
    // Get Device Info, City, and Status Code
    const brand = request.device.brandName;
    const city = request.userLocation.city;
    const responseCode = response.status;

    httpRequest(`https://c.go-mpulse.net/api/config.json?key=${API_KEY}&d=${DOMAIN}`)
        .then((responseConfig) => {
            if (!responseConfig.ok) {
                logger.log("Failed to get config");
                return;
            }

            // Extract mPulse Config
            responseConfig.json().then((configData) => {
                const { beacon_url: beaconFqdn, 'h.t': timestamp, 'h.cr': token } = configData;
                const timestampEnd = Number(timestamp) + 10000;
                // Create mPulse Base Send Beacon URL
                const baseurl = `https:${beaconFqdn}?api=1&api.v=1&h.key=${API_KEY}&h.d=${DOMAIN}&h.pg=${PAGEGROUP}&h.cr=${token}&h.t=${timestamp}&rt.end=${timestampEnd}&rt.start=manual&`;
                // GET PERFORMANCE DATA
                const RTT = request.getVariable('PMUSER_RTT');
                const reqEndTime = Date.now();
                const reqStartTime = request.getVariable('PMUSER_REQSTART');
                const customTAT = reqEndTime - reqStartTime;
                // Construct mPulse Send Beacon URL
                const beaconUrlParams = `${baseurl}t_other=custom${RTT_INDEX}|${RTT},custom${TAT_INDEX}|${customTAT}&t_done=1&cdim.${DEVICE_INFO}=${brand}&cdim.${GEO}=${city}&cdim.${STATUS}=${responseCode}`;
                logger.log(beaconUrlParams);

                // Send Beacon
                send(beaconUrlParams);
            });
        })
        .catch((error) => {
            logger.log(`Error: ${error.message}`);
        });
}

function send(url) {
    httpRequest(url)
        .then((response) => {
            if (!response.ok) {
                logger.log("Failed to send beacon");
            }
        })
        .catch((error) => {
            logger.log(`Error: ${error.message}`);
        });
}
```


収集されたデータはリアルタイムでmPulseのダッシュボードに表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820036/e3fb826d-bfb5-99ce-98de-0a39277e0b2e.png)

### おわりに
今回はEdgeWorkersとｍPulseを利用しEdge Side Monitoringを実現する方法を説明しました。EdgeWorkersを利用することのメリットとして、データの収集から送信までの時間が短縮され、データの可視化が速やかに実現できる利点があります。