New Relicのクエリ言語でJOINを使ってみた

# 概要
New Relicに取り込んだデータを詳細に分析することができるクエリ言語のNRQLですが、より細かい分析をする際に2つのデータを結合して分析したいと感じたことは無いでしょうか？
この度、New Relic アップデート(2023年5月)の中で、遂にNew Relicのクエリ言語にJOINが追加されたので試してみます！

:::note info
このアップデートの詳細はこちら。[New Relic アップデート(2023年5月)](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202305 "New Relic アップデート(2023年5月)")
:::

# JOINの構文
JOINは次の構文で指定します。基本的にはSQLのJOINと同じなのでイメージしやすいと思います。
詳細は[こちら](https://docs.newrelic.com/jp/docs/query-your-data/nrql-new-relic-query-language/nrql-query-tutorials/subquery-joins/ "NRQL サブクエリ結合")を参照ください。

```markdown:JOINの構文
FROM Event [INNER|LEFT] JOIN (subquery) ON [key =] key SELECT ...
```

JOINを活用するいくつかユースケースを紹介します。

## 1. パフォーマンスが悪いアプリのCPU使用率を確認
バックエンドのアプリケーションの応答時間であるレスポンスの情報は、**Transactionイベント**に**duration**という属性で含まれていますが、アプリケーションが動いているサーバーのCPU使用率は**Transactionイベント**には含まれていないため、**Transactionイベント**だけでは、レスポンスとCPU使用率の相関関係を一つにして表すことができませんでした。

そこで、今回追加されたJOINを使ってアプリケーションの応答時間を含む**Transactionイベント**と、CPU使用率の情報を含む**ProcessSampleイベント**を**ホスト名**を使ってJOINで結合して、アプリケーションの応答速度が良くない場合に、ホストのCPU使用率がどのようになっているか一覧で確認できるようにしたいと思います。

まずはJOINする前にそれぞれのデータをNRQLで呼び出してみます。

```markdown:Transactionイベントからレスポンスの平均時間を取得
FROM Transaction SELECT average(duration) FACET host 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/8eac066e-ffcf-c353-fbd6-427273b4ebfb.png)


```markdown:SystemSampleイベントからCPU使用率の平均時間を取得
FROM SystemSample SELECT average(cpuPercent) FACET hostname
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/88e365f6-f265-67cd-d8d2-792d49bbf8e1.png)

では、JOINの構文に従って**Transactionイベント**の**host**と**SystemSampleイベント**の**hostname**をキーとして結合します。

:::note warn
サブクエリの**cpuPercent**はそのままでは結合後の**SELECT**で呼び出せないので、**AS**でエイリアス名**cpu**をつけて、`average(cpu)`で使用しています。
:::

```markdown:TransactionイベントにSystemSampleイベントを結合
FROM Transaction
  JOIN (FROM SystemSample SELECT average(cpuPercent) AS cpu
  FACET hostname) ON host = hostname
SELECT average(duration), average(cpu)
FACET appName, host
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/7ef45b7f-a436-39a1-6d0b-ece5c3f4c832.png)

このように、TransactionイベントにSystemSampleイベントを結合することで、アプリケーションのレスポンスが遅い場合に、ホストのCPU使用率がどのくらい高くなっているか一覧で確認できるようになりました。

## 2. アプリが呼び出す処理がブラウザ操作の時間に与える影響
ユーザーがブラウザを操作したときに、そのブラウザの処理の中で必要となる時間の中には、バックエンドのアプリケーションが使用するデータベースや外部サービスへのアクセスなどの時間が含まれていますが、ブラウザセッションの処理に関する**BrowserInteractionイベント**ではバックエンドのアプリケーションのデータベース処理や外部アクセスの時間などは把握することができません。

そこで、今回追加されたJOINを使ってアプリケーションの外部アクセスの時間を含む**Transactionイベント**と、ブラウザセッションの処理にかかった時間を持っている**BrowserInteractionイベント**を**Transactionの名前**を使ってJOINで結合していきたいと思います。

まずはJOINする前にそれぞれのデータをNRQLで呼び出してみます。

```markdown:Transactionイベントからトランザクション名と外部アクセスの時間を取得
FROM Transaction SELECT name, externalDuration WHERE externalDuration IS NOT NULL
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/edfb751d-6585-c87c-d9fb-b62abdd4ea44.png)

```markdown:BrowserInteractionイベントからトランザクション名とブラウザインタラクションの時間を取得
FROM BrowserInteraction SELECT backendTransactionName, duration　AS 'session duration'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/da549591-2152-71c5-8163-01133fc63cce.png)

では、JOINの構文に従って**Transactionイベント**の**name**と**BrowserInteractionイベント**の**backendTransactionName**をキーとして結合します。

```markdown:TransactionイベントにBrowserInteractionイベントを結合
FROM Transaction 
　　JOIN(FROM BrowserInteraction SELECT backendTransactionName,
　　duration AS total )　ON name=backendTransactionName
SELECT name, total AS 'session duration', externalDuration
WHERE　externalDuration IS NOT NULL
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/b1e6028f-7aa0-88d2-7931-99db3c50f95f.png)

このように、TransactionイベントにBrowserInteractionイベントを結合することで、ブラザセッションの処理時間とアプリケーションの外部アクセスの時間を一覧で確認できるようになり、ブラウザセッションのパフォーマンスにアプリケーションの外部アクセスがどの程度影響を与えているか把握しやすくなります。

## 3. 例外スローされたTransactionのログだけを一覧表示
構造化されたログを表形式で表示することで、どの時間帯にどんなメッセージがでているか確認することができますが、例外がスローされたTransactionのログだけを一覧で表示するには情報が足りないことがあります。

そこで、今回追加されたJOINを使ってログに関する**Logイベント**と、例外がスローされたTransactionを表す**TransactionErrorイベント**を**トレースID**を使ってJOINで結合していきたいと思います。

まずはJOINする前にそれぞれのデータをNRQLで呼び出してみます。

```markdown:Logイベントからアプリ名とトレースIDとメッセージを取得
FROM Log SELECT appName, trace.id, message
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/56756bd3-6355-1c50-e8ae-4c768acede39.png)

```markdown:traceId毎にTransactionErrorイベントの発生回数を取得
FROM TransactionError SELECT count(*) FACET traceId
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/3e3f8b37-1b22-9b41-1e4e-c3cca0aa5b65.png)

では、JOINの構文に従って**Logイベント**の**trace.id**と**TransactionErrorイベント**の**traceId**をキーとして結合します。

```markdown:LogイベントにTransactionErrorイベントを結合
FROM Log
  JOIN (FROM TransactionError SELECT count(*) 
  facet traceId as 'trace.id', appName) ON trace.id
SELECT appName, trace.id, message
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/bfc8eed1-30de-defd-28b6-3b8de87a1db8.png)

このように、LogイベントにTransactionErrorイベントを結合することで、例外がスローされたTransactionのログだけを一覧で表示することができました。

# まとめ
New Relic アップデート(2023年5月)に記載されているJOINを試してみました。
New Relicに取り込んだ2つのデータを結合して分析することができる強力な機能なのでぜひお試しください。

:::note info
このアップデートの詳細はこちら。[New Relic アップデート(2023年5月)](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202305 "New Relic アップデート(2023年5月)")
:::