New Relic Insights: ファンネルやヒストグラムなど NRQL でいろいろ試してみよう（応用編）

デジカの宮澤です。Advent Calendar 8日目の[New Relic Insights: NRQL をいろいろ試しみよう（基本編）](http://qiita.com/kumatronik/items/f8c93fdeed7f945b7d32)の続きです。

8日目を見ていない方に説明すると、New Relic Insights の Query 画面にNRQL のチュートリアル (Insights > Query > Analyze) があります。NQRL のサンプルが載っていて、基本(Basic)と応用(Advanced)に別れています。前回は、基本を紹介しました。ここでは、応用と弊社での利用例を紹介していきたいと思います。

NRQL って何？っていう人は、この記事を読む前に [New Relic Insights: NRQL をいろいろ試しみよう（基本編）](http://qiita.com/kumatronik/items/f8c93fdeed7f945b7d32) をご覧ください。

# NRQL の応用編

**サイトのトップから、ログイン、チェックアウトまでのユーザーの行動を見てみたい （Funnel の利用）**

```
SELECT funnel(session, 
  WHERE pageUrl = 'http://www.home.com' AS 'Home', 
  WHERE pageUrl = 'http://www.home.com/signup' AS 'Signup', 
  WHERE pageUrl = 'http://www.home.com/thankyou' AS 'Checkout') 
FROM PageView SINCE 1 week ago
```

上記の例はそのままテストできない（一致するようなパスがあれば別だけど）ので、弊社では Pro スチーマーという EC サイトを運営しているので、そこで、カート > ログイン（またはユーザー登録） > 住所入力画面表示。の流れをファンネルで表示してみたいと思います。

```sql
SELECT funnel(session, 
  WHERE pageUrl = 'https://steam.degica.com/c/cart' AS 'Cart', 
  WHERE pageUrl = 'https://steam.degica.com/c/checkout/registration' AS 'Signup', 
  WHERE pageUrl = 'https://steam.degica.com/c/checkout/address' AS 'Address') 
FROM PageView SINCE 1 week ago
```

![insights_nrql_ad_01.png](https://qiita-image-store.s3.amazonaws.com/0/46003/1721c75a-dd73-3b27-084f-77101b95dca4.png)

ファンネルでは、"A" を満たした人(上の例では Cart 部分)、"A"も"B"も満たしたい人(上の例では Signup 部分)、"A"も"B"も"C"も満たした人(上の例では Address 部分)を示しています。

**全コントローラーのうち名前に "data" が含まれているコントローラー名とスループットのリストは？（ワイルドカード検索）**

NRQL では、`LIKE` または `NOT LIKE` 句が使えます。ここでは、コントローラー名に `data` を含むトランザクションとその数を抽出しています。

```sql
SELECT count(*) FROM Transaction 
  WHERE name LIKE '%data%' FACET name SINCE 1 day ago
```

![insights_nrql_2.png](https://qiita-image-store.s3.amazonaws.com/0/46003/cd53d756-d768-3767-6fa6-09d077283cd3.png)


**曜日ごとのスループットは？（コホート分析）**

コホート分析は、タイムスタンプをベースにグループ化し、日付と時刻の指定した範囲をカバーするバケットにそれらを分離します。

特定のアプリの過去１週間のトランザクションを曜日別にその数を抽出しています。

```sql
SELECT count(*) 
FROM Transaction 
WHERE appName = '<app_name>' 
SINCE 1 week ago 
FACET weekdayOf(timestamp)
```

※ FACET は、SQL の 'GROUP BY' です。
※ &lt;app_name&gt; のところは各自のアプリ名に置き換えてください。

![insights_nrql_03.png](https://qiita-image-store.s3.amazonaws.com/0/46003/fd825bd8-9edc-2916-1775-710c2e5dafa2.png)

円グラフでみた場合

![insights_nrql_3_2_2.png](https://qiita-image-store.s3.amazonaws.com/0/46003/e5850f22-8282-b888-e525-b98857fe931f.png)


棒グラフでみた場合
![insights_nrql_3_3_2.png](https://qiita-image-store.s3.amazonaws.com/0/46003/997a0e85-7ede-a82b-e722-6be66c2e8652.png)

バケットには以下の関数が使えます。意味は、`yearOf` なら年別とかです。

- yearOf()
- quarterOf()
- monthOf()
- weekOf()
- weekdayOf()
- dateOf()
- dayOfMonthOf()
- hourOf()

デフォルトで、"timestamp" 属性で上の関数は使えます。独自のタイムスタンプのカスタム属性を追加していた場合は、それらも使えます。例えば、アカウント作成日時とか購入日時など。


**平均処理時間が1秒以上のアプリにおけるトランザクションの割合は？（percentage の利用）**


特定のアプリの過去１日のトランザクションのうち、処理時間が1秒以上の割合を抽出しています

```sql
SELECT percentage(count(*), WHERE duration > 1) FROM Transaction WHERE appName = '<app_name>' SINCE 1 day ago
```

![insight_nrql_4.png](https://qiita-image-store.s3.amazonaws.com/0/46003/cf32f215-c786-bd6f-41c8-cd87c312ecfc.png)


`percentage` 関数は、条件に一致したデータの割合を返します。文字列のデータに関しても使えます。コントローラー名に `data` が含まれるトランザクションの割合が見たい場合とか。Pageview データを元に特定のブラウザを使用しているユーザーの割合を見たい場合など。

※ &lt;app_name&gt; のところは各自のアプリ名に置き換えてください。

**アプリの処理時間をパーセンタイルで表すとどうなる？(percentile の利用）**

```sql
SELECT percentile(duration, 5, 50, 95) 
FROM Transaction 
WHERE appName = '<app_name>' 
TIMESERIES AUTO
```

※ &lt;app_name&gt; のところは各自のアプリ名に置き換えてください。

![insight_nrql_5.png](https://qiita-image-store.s3.amazonaws.com/0/46003/75529c28-bba1-cc31-105c-e66bff85980a.png)

`percentile` 関数は、指定されたパーセンタイルに含まれる数（ここではトランザクション数）を返します。この関数と一緒に`TIMESERIES`を使うと、時系列グラフでパーセンタイルの推移をみることができます。

`percentile` 関数の仕様は、[ここ](https://docs.newrelic.com/docs/insights/new-relic-insights/using-new-relic-query-language/nrql-reference#func-percentile)。



**アプリにおけるレスポンスタイムの分布はどうなっている？（histogram の利用）**

```sql
SELECT histogram(duration, width: 2, buckets: 20) 
FROM Transaction 
WHERE appName = '<app_name>' 
SINCE 1 day ago
```

※ &lt;app_name&gt; のところは各自のアプリ名に置き換えてください。

※ 引数の `width`と`buckets`というキー名はなくても同じ結果ぽい。`histogram(duration, 2, 20)` でもいいのかな。

![insight_nrql_6.png](https://qiita-image-store.s3.amazonaws.com/0/46003/0f9e95e9-c8db-9a41-7ae2-ca98e5841d1c.png)

`histogram` 関数は、引数としてデータ分割に必要な時間幅とバケット数を取ります。第2引数は、グラフの上限（ここでは、x軸の上限が2.0となっている）。第3引数は、x軸を何分割で表すか（ここでは、20分割している）

`histogram` 関数の仕様は、[ここ](https://docs.newrelic.com/docs/insights/new-relic-insights/using-new-relic-query-language/nrql-reference#func-histogram)。


**処理時間帯別における DB の処理時間の割合は？（buckets の利用）**

```sql
SELECT average(databaseDuration) 
FROM Transaction 
FACET buckets(duration, width: 5, buckets: 10) 
WHERE appName = '<app_name>' 
SINCE 1 day ago
```

※ &lt;app_name&gt; のところは各自のアプリ名に置き換えてください。

![insight_nrql_7.png](https://qiita-image-store.s3.amazonaws.com/0/46003/3f459eef-02bf-98b6-8357-120153427d64.png)

`buckets` 関数は、指定されたデータを条件に従って、分割します。ここでは、全体の処理時間に対するDBの平均処理時間(average (databaseDuration))を抽出しています。平均の処理時間と全体の処理時間に相関関係があるのであれば、全体の処理時間が増えれば増えるほど、DBの処理時間も増えるはずです。

上記の結果をみると、途中(3.5 から 4.5)では(2.5-3.5)より平均処理時間が低いですね。ということは、3.5-4.5に関係する処理では、DB以外（たぶん外部サービス）で時間のかかる処理が多いと判断できそうです。


#弊社での利用例

最後に簡単に、弊社で Insights をどうように利用しているかを紹介させていただきます。

デジカでは、[Komoju](https://komoju.jp/) という決済サービスを提供しています。その決済データを カスタムイベントを使って、Insights で各種データを見れるようにしています。

以下は、デジカで使っている NRQL のサンプルです。

**一日あたりの売上の比較（前日と本日）**

```sql
SELECT sum(total) 
FROM PaymentStatus 
WHERE appName='<app_name>' AND status = 'captured' 
TIMESERIES auto 
SINCE 1 day ago 
COMPARE WITH 1 day ago
```

決済情報は、`PaymentStatus` というイベント名でカスタムイベントを送っているので、そのテーブルを使います。

`COMPARE WITH`を使って、前日との比較を行っています。

**エンドユーザーの Apdex スコア(直近1時間）**

```sql
SELECT apdex(duration, t: 2.0) FROM PageView WHERE appName='<app_name>'
```

apdex の第２引数の `t` は、Apdex Tの閾値です。単位は秒です。

Apdex 関数の説明は、[NRQL リファレンス](https://docs.newrelic.com/docs/insights/new-relic-insights/using-new-relic-query-language/nrql-reference)をご覧ください。


**支払方法別の使用割合（直近1週間）**

```sql
SELECT count(*) from PaymentStatus facet payment_method where appName = '<app_name>' and status = 'captured' since 1 week ago
```

特に説明は必要ないかな。

**コンビニ支払いのコンバージョン（直近1週間）**

```sql
SELECT funnel(uuid, WHERE status='pending' as 'pending', WHERE status = 'authorized' as 'authorized', WHERE status = 'captured' AS 'captured') 
FROM PaymentStatus 
WHERE payment_method='konbini' and appName = '<app_name>' 
SINCE 1 month ago
```

これも特に説明は必要ないかな。

# さいごに

どうでしたでしょうか？実際のビジネスで利用した際のイメージができたかと思います。ここでは、データソースとして、Transaction や Pageview くらいしか使っていませんが、その他にも、APM の TransactionError や Mobile のデータ、Sythetics のデータもあります。外部からも送ることができます。是非、データを横断、多角的に分析するツールとして活用してみてください。

もっと、NQRL について知りたい方は、是非公式ドキュメントをご覧ください。
- [NRQL リファレンス](https://docs.newrelic.com/docs/insights/new-relic-insights/using-new-relic-query-language/nrql-reference#func-buckets)
- [NRQL で数式の利用](https://docs.newrelic.com/docs/insights/new-relic-insights/using-new-relic-query-language/nrql-math)
- [コミュニティ](https://discuss.newrelic.com/c/insights)でも NRQL の例など載っていると思いますので、そちらものぞいてみると面白いかも