New RelicのTIMESERIES句について

NewRelicのTIMESERIES句。
自分は最初「なんかグラフにするときにつけるやつ」ぐらいの認識しかありませんでした。ドキュメントと挙動を確認しながらまとめてみます。

![スクリーンショット_2021_12_15_8_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/010f68d9-6c32-ffbc-2305-d79919b754cd.png)

# 結論(わたしの理解)

TIMESERIESを使えばデータを指定した粒度で時系列に分割できる。
時系列データにすることで線グラフなどで表示できるようになる。

## このデータを
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/6bcd32ba-fabf-390d-a142-440bd93f5c14.png)

## 5分間隔で分割する(TIMESERIES 5 minutes)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/241c3173-6c04-92f7-5460-4c21d3044ba9.png)

## 線グラフ表示などもできるようになる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/cd1b78fb-e74f-38b5-16b1-9e2b15f3ef21.png)


# 基本的な動きから確認

[ドキュメント::TIMESERIES句](https://docs.newrelic.com/jp/docs/query-your-data/nrql-new-relic-query-language/get-started/nrql-syntax-clauses-functions/#sel-timeseries)

> TIMESERIES句を使用して、指定期間単位の時系列としてデータを返します。

## [設定した間隔を使用する](https://docs.newrelic.com/jp/docs/query-your-data/nrql-new-relic-query-language/get-started/nrql-syntax-clauses-functions/#set-interval)

>時間範囲を指定するには、integer unitsを使用します。
>例:
>TIMESERIES 1 minute
>TIMESERIES 30 minutes
>TIMESERIES 1 hour
>TIMESERIES 30 seconds

### TIMESERIES 1 minute
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/7afb618a-a77c-2ee4-4732-d5ac3fe06827.png" width=50%>


### TIMESERIES 5 minutes
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/c0b10a50-36eb-2924-5c1f-7625452b7b0b.png" width=50%>

設定間隔にあわせた粒度で表示されます。

## [自動設定した間隔を使用する](https://docs.newrelic.com/jp/docs/query-your-data/nrql-new-relic-query-language/get-started/nrql-syntax-clauses-functions/#timeseries-auto)

> TIMESERIESはAUTOに設定することもでき、これによってグラフが適切な数の区分に分割されます。たとえば、1日のチャートは30分間隔で分割され、1週間のチャートは6時間間隔で分割されます。

グラフの対象期間に合わせて間隔を自動で調整してくれます。

### 60 minutes に対して TIMESERIES AUTO を設定
![スクリーンショット_2021-12-15_8_48_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/95a1c875-767d-378d-3cf1-034dd65bb5c9.png)

キャプチャだとわかりにくいですが1分間隔の粒度でグラフが表示されました。

### 6 hours(=360 minutes) に対して TIMESERIES AUTO を設定
![スクリーンショット_2021-12-15_9_11_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/e21e4999-d120-cae4-199d-5582ea5bcde8.png)


15分間隔の粒度でグラフが表示されました。

## [MAXインターバルを使用する](https://docs.newrelic.com/jp/docs/query-your-data/nrql-new-relic-query-language/get-started/nrql-syntax-clauses-functions/#timeseries-max)

> TIMESERIESをMAXに設定することで時間枠が自動的に調整され、指定された期間に許可された間隔数を最大にできます。これによって、TIMESERIESバケットを手動で更新することなく時間枠を更新でき、認められた最大インターバル数に時間枠を分割できます。返されるTIMESERIESバケットの最大数は366です。

ここで「許可された間隔数」「バケット」という言葉で出てきました。
TIMESERIESは指定した時間間隔でデータを区切ることができます。その１つの区間をバケットと呼び、その分割数(=バケット数)には366個という限界があります。

指定期間のなかで最大の366分割までできるだけ使って細かい粒度にしてくれるのがMAXという指定です。

### 6 hours(=360 minutes) に対して TIMESERIES MAX
![スクリーンショット_2021-12-15_9_13_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/ba79a97b-38b1-bb7f-0e78-a9d7a2b01baf.png)

1分間隔の粒度でグラフが表示されました。360分割なのでMAX近くまでバケットを使って細分化してくれています。
前述の「6 hours(=360 minutes) に対して TIMESERIES AUTO」と比較するとわかりやすいです。

### 367 minutes に対して TIMESERIES MAX

![スクリーンショット_2021-12-15_9_17_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/f912e29c-84bb-8d5e-cb8f-cba7ec7ce34d.png)

2分間隔の粒度でグラフが表示されました。(単独のキャプチャだとわかりにくいので「6 hours(=360 minutes)」のグラフと見比べてもらえれば)

367分を1分間隔で分割しようとすると366を超えてしまうので2分間隔で切ってくれています。



## バケット数不足のケース

では長い対象期間に対してバケット数の限界を超える細かい間隔を指定したらどうなるか？

![Query_builder___New_Relic_Explorer___New_Relic_One.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/96a2c253-68de-bd1f-fb93-09f42aa2203d.png)

「We can't render this query: TIMESERIES supports a maximum of 366 buckets」とエラーが出てくれます。

# 応用してみる

実案件で「とある処理を設計上ベストエフォートで繰り返す」という処理が存在しました。
このサービスのSLI/SLOの１つとして「10分の間に1回以上この処理が実行されている割合が99.9%以上」というものを設定しました。

こういったものもTIMESERIESを使うことで計測/可視化できます。

```sql:
/* 前提条件：とある処理をしたらexmonitor_targetというメトリクス に「1」を記録しているとする */
SELECT average(ok) * 100 as percent FROM (
   SELECT (max(exmonitor_target) or 0) as ok FROM Metric TIMESERIES 10 minutes
) 
```

「(SELECT (max(exmonitor_target) or 0)」としているのはTIMESERIESで分割した10分の間に処理が実行されたかをTrue(1)or False(0)で集計したいので、count(総回数)ではなくmax(値=記録されるのは1のみ)で集計しています。
max(exmonitor_target)は、データがない場合nullを返すのでnullが帰ってきた場合は0にするよう or 0しています。

### 10分の間に1回以上この処理が実行されている割合

![exmonitor_SLI_SLO___exmonitor_SLI_SLO___New_Relic_One.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/52ca0267-faa1-32ca-b380-ccf7e9616616.png)



### 1分の間に1回以上この処理が実行されている割合

![exmonitor_SLI_SLO___exmonitor_SLI_SLO___New_Relic_One.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/803361f7-75cc-e9c4-536f-7804dda5f7c7.png)



# 終わりに

なんとなく使っていたTIMESERIESですが、理解することで「「10分の間に1回以上この処理が実行されている割合」という指標もクエリで可視化することができました。

TIMESERIESを理解するのとき、いつも「Line」表示しているグラフの生データを「Table」で表示してみるとイメージの助けになるかもしれません。

### Line
![Query_builder___New_Relic_Explorer___New_Relic_One.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/12cc5b51-2489-c9f2-5693-87e98011640e.png)

```sql
SELECT count(`aws.lambda.Invocations`) FROM Metric TIMESERIES 5 minutes SINCE 60 minutes ago
```


### Table
![Query_builder___New_Relic_Explorer___New_Relic_One.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/6bd359b7-65cf-446d-7846-f05a769e6ac1.png)

```sql
SELECT * FROM (
  SELECT count(`aws.lambda.Invocations`) FROM Metric TIMESERIES 5 minutes
) SINCE 60 minutes ago
```