OCI Monitoringのメトリックデータをcsvにして保存する

2019/12/07 新規作成
2019/12/08 誤字や見え方の部分修正
***

この記事は [Oracle Cloud Infrastructure Advent Calendar](https://adventar.org/calendars/4516) 2019 の12/7の記事として書かれています。

# はじめに
## やりたいこと
- Monitoringサービスのメトリックデータをcsvとして出力する

## 前提・検証環境
### 前提
- oci cliが使える状態であること
- jqコマンドが使えること
- computeインスタンスは各メトリックのデータポイントがmonitoringサービスへ送られていること
	- computeインスタンスにmonitoringエージェントがインストールされていること（インスタンス作成時のデフォルト）
	- private subnet内のインスタンスについては、Service GatewayやNAT Gateway経由でmonitoringサービスへアクセスできる状態であること

### 環境
- oci cli実行環境はlinux(OEL 7.7)
- oci cliのversionは2.6.11
- oci cliのoci_cli_rcにて、コンパートメントを指定済み


# コマンド

## 構文

oci cliコマンドでjson形式でメトリックデータを取得した後、jqコマンドでcsv化し、ソートしてCSVファイルとして出力しています。

`oci monitoring metric-data summarize-metrics-data --namespace <namepsace名>  --query-text <MQL文> | jq -r '.data[] | .["aggregated-datapoints"][] | [ .timestamp ,.value] | @csv' | sort -t ',' -k 1 > XXXX.csv`


## サンプル

### 例1）ComputeインスタンスのCPU使用率

#### コマンド例

12/06 13:00 UTC から 12/07 00:00 UTCまでの期間で、指定したComputeインスタンスCPU使用率を、1分間隔で出力[^1]

```
$ oci monitoring metric-data summarize-metrics-data --namespace oci_computeagent --start-time '2019-12-06 13:00' --end-time '2019-12-07 00:00' --query-text "CpuUtilization[1m]{resourceDisplayName = test-instance}.max()" | jq -r '.data[] | .["aggregated-datapoints"][] | [ .timestamp ,.value] | @csv' | sort -t ',' -k 1 > test-instance-CpuUtilization.csv
```

その他のメトリックについてはマニュアルを参照
https://docs.cloud.oracle.com/iaas/Content/Compute/References/computemetrics.htm

[^1]: 正確には1分のうちの最大値（max）を出力させるコマンドですが、1分間隔でしかメトリックは収集されていないため1分間隔を指定している場合はmaxでもsumでも同じです。

※ もちろん環境変数をつかってもOK

```
$ INSTANCE=test-instance
$ STARTTIME='2019-12-06 13:00'
$ ENDTIME='2019-12-07 00:00'
$ oci monitoring metric-data summarize-metrics-data --namespace oci_computeagent --start-time "$STARTTIME" --end-time "$ENDTIME" --query-text "CpuUtilization[1m]{resourceDisplayName = $INSTANCE}.max()" | jq -r '.data[] | .["aggregated-datapoints"][] | [ .timestamp ,.value] | @csv' | sort -t ',' -k 1 > $INSTANCE-CpuUtilization.csv
```

#### 出力例

```test-instance-CpuUtilization.csv
"2019-12-06T13:00:00+00:00",10.1984126984126977
"2019-12-06T13:01:00+00:00",10.44532409698169184
"2019-12-06T13:02:00+00:00",11.49529470034670453
"2019-12-06T13:03:00+00:00",11.3895781637717097
"2019-12-06T13:04:00+00:00",10.19890601690700782
```

### 例2）Blockボリュームの読み込みスループット

#### コマンド例

12/07 14:00 UTC から 12/07 16:00 UTCまでの期間で、指定したBlockボリュームの読み込みバイト数を、1分間隔で出力[^1]

```
$ oci monitoring metric-data summarize-metrics-data --namespace oci_blockstore --start-time '2019-12-07 14:00' --end-time '2019-12-07 16:00' --query-text "VolumeReadOps[1m]{resourceId = "ocid1.volume.oc1.ap-tokyo-1.xxxxxxxxxxxxx"}.max()" | jq -r '.data[] | .["aggregated-datapoints"][] | [ .timestamp ,.value] | @csv' | sort -t ',' -k 1 > blockvolume-readIOPS.csv
```

その他のメトリックについてはマニュアルを参照
https://docs.cloud.oracle.com/iaas/Content/Block/References/volumemetrics.htm

[^1]: 正確には1分のうちの最大値（max）を出力させるコマンドですが、1分間隔でしかメトリックは収集されていないため1分間隔を指定している場合はmaxでもsumでも同じです。

#### 出力例

```blockvolume-readIOPS.csv
"2019-12-07T14:17:00+00:00",14795
"2019-12-07T14:18:00+00:00",20473
"2019-12-07T14:19:00+00:00",16656
"2019-12-07T14:20:00+00:00",16778
"2019-12-07T14:21:00+00:00",7286
```

### 例3）vNICからの送信データ量

#### コマンド例

12/07 14:00 UTC から 12/07 16:00 UTCまでの期間で、指定したvNICから送信されたバイト数を、1分間隔で出力[^1]

```
$ oci monitoring metric-data summarize-metrics-data --namespace oci_vcn --start-time '2019-12-07 14:00' --end-time '2019-12-07 16:00' --query-text "VnicToNetworkBytes[1m]{resourceId = "ocid1.vnic.oc1.ap-tokyo-1.xxxxxxxxx"}.sum()" | jq -r '.data[] | .["aggregated-datapoints"][] | [ .timestamp ,.value] | @csv' | sort -t ',' -k 1 > vnic-toBytes.csv
```

その他のメトリックについてはマニュアルを参照
https://docs.cloud.oracle.com/iaas/Content/Network/Reference/vnicmetrics.htm#metrics-list

[^1]: 正確には1分のうちの最大値（max）を出力させるコマンドですが、1分間隔でしかメトリックは収集されていないため1分間隔を指定している場合はmaxでもsumでも同じです。

#### 出力例

```vnic-toBytes.csv
"2019-12-07T14:00:00+00:00",65337
"2019-12-07T14:01:00+00:00",65204
"2019-12-07T14:02:00+00:00",65400
"2019-12-07T14:03:00+00:00",75213
"2019-12-07T14:04:00+00:00",65666
```


# 補足

## OCI CLIコマンド部分の説明

`oci monitoring metric-data summarize-metrics-data --namespace oci_vcn  --query-text "VnicToNetworkBytes[1m]{resourceId = "ocid1.vnic.oc1.ap-tokyo-1.xxxxxxxxx"}.sum()"`

### oci monitoring metric-data summarize-metrics-data
Monitoringサービスから集約データを取得するコマンド

パラメーター等の説明は以下のマニュアルを参照
https://docs.cloud.oracle.com/iaas/tools/oci-cli/latest/oci_cli_docs/cmdref/monitoring/metric-data/summarize-metrics-data.html

### --namespace
メトリックnamespaceを指定

対象サービスによって異なるため、どのようなnamespaceがあるかはマニュアルを参照します。
残念ながら、一覧にはなっていないので、各サービスのMetricsという項目から確認します。
例）
・[compute](https://docs.cloud.oracle.com/iaas/Content/Compute/References/computemetrics.htm#instance-overview)の場合、"oci_computeagent"、"oci_blockstore"、"oci_vcn"の3つがある
・[database](https://docs.cloud.oracle.com/iaas/Content/Network/Reference/vnicmetrics.htm#metrics-list)は"oci_autonomous_database"のみ（2019/12現在)

## --start-time, --end-time
取得するメトリックデータの期間を指定

指定しなかった場合、コマンドが発行された3時間前の時点がstart timeとなります。

なお、**指定するデータの取得間隔によって、どの時点までさかのぼって取得できるかが決まっています**。
（粒度ごとに保存期間が決まっています）
- 1分間隔：7日
- 5分間隔：30日
- 1時間間隔：90日


### --query-text
メトリックと取得間隔、各種フィルタや集計方法などを指定して、生データポイントからデータを取得する方法を記述するMQLを指定

基本的な構文は以下
`metric[interval]{dimensionname="dimensionvalue"}.groupingfunction.statistic`

詳細は以下のマニュアルを参照
https://docs.cloud.oracle.com/iaas/Content/Monitoring/Reference/mql.htm

ただし、ウェブ管理コンソール画面の「Monitoring」>「Metrics Explorer」で、必要な項目を入力してチャートを更新すると、MQLが自動生成されるため、1から自作しなくてもOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109270/84c00d05-7b06-9cf5-ee5f-22d50e0ca889.png)
※ クエリが長くて見切れている場合は「Close query editor」をクリックすれば、全文が表示されます。

## jq以降の説明

`jq -r '.data[] | .["aggregated-datapoints"][] | [ .timestamp ,.value] | @csv' | sort -t ',' -k 1 > xxxx.csv`

### jq
jsonからデータを取り出したり整形するコマンド

### -r
抽出した値をクォーテーション無しで出力させるためのオプション

### .data[] | .["aggregated-datapoints"][] | [ .timestamp ,.value] 
必要なデータの抜き出し

OCI CLIの出力するjsonの構造に従って、"data"に対する配列の値である"aggregated-datapoints"の、さらに対応する配列の中から、"timestamp"と"value"の値を抜き出します。

参考：oci cliが出力するjson

```
{
  "data": [
    {
      "aggregated-datapoints": [
        {
          "timestamp": "2019-12-07T10:12:00+00:00",
          "value": 45.91058972075785
        },        
          "timestamp": "2019-12-07T11:21:00+00:00",
          "value": 5.008442198672524
        },
        {
（中略）
        {
          "timestamp": "2019-12-07T11:25:00+00:00",
          "value": 1.0136996285751265
        }
      ],
      "compartment-id": "ocid1.compartment.oc1...xxxxxxxxxxxxxxxx",
      "dimensions": {
        "availabilityDomain": "XXXX:AP-TOKYO-1-AD-1",
        "faultDomain": "FAULT-DOMAIN-1",
        "imageId": "ocid1.image.oc1..aaaaaaaa2es7kqqgmmjyymzdaaeqmmehrprg6gdjxs4on5lpzwiv64przksa",
        "instancePoolId": "Default",
        "region": "ap-tokyo-1",
        "resourceDisplayName": "test-instance",
        "resourceId": "ocid1.instance.oc1.ap-tokyo-1.xxxxxxxx",
        "shape": "VM.Standard2.2"
      },
      "metadata": {
        "displayName": "CPU Utilization",
        "maxRange": "100",
        "minRange": "0",
        "unit": "Percent"
      },
      "name": "CpuUtilization",
      "namespace": "oci_computeagent",
      "resolution": null,
      "resource-group": null
```

### @ csv
配列データをCSVデータにして出力

### sort -t ',' -k 1
ソートコマンドで並び替え

-tで区切り文字を指定し、-kでソートのキーとなる項目（1項目目=timestamp）を指定しています。

### > xxxx.csv
出力をリダイレクトしてcsvへ吐き出し

以上