MetricbeatでElasticsearchに貯めたCPU使用率をKibanaを使わずにJavaScriptで可視化する

正月休みに勉強しようと思って、[Elasticsearch実践ガイド](https://book.impress.co.jp/books/1117101041)を買いました。
Amazonで買ったけど、インプレスで電子書籍版が半額:scream::scream::scream:(期間限定のようです)
初心者の私にはちょうどいい入門書でした！

前からやりたかった、Kibanaを使わずにKibanaっぽいグラフを作ることができました～！

![スクリーンショット (86).png](https://qiita-image-store.s3.amazonaws.com/0/41574/9a227da9-a43f-747c-62e4-9387c14d1aa6.png)

# 環境構築

OS: Ubuntu 18.04.1 (on VirtualBox)
ホスト名：ubuntu.local

## インストール

https://www.elastic.co/guide/en/elasticsearch/reference/current/deb.html
https://www.elastic.co/guide/en/kibana/current/deb.html
https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-installation.html
を参考に。

### Open JDKのインストール

```
sudo apt update
sudo apt install openjdk-8-jre-headless
```

### PGPキーのインストール

```
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
```

### APT repositoryのインストール

```
sudo apt install apt-transport-https
```

### sources listの追加
OSS版をインストールしたかったのでこちら

```
echo "deb https://artifacts.elastic.co/packages/oss-6.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-6.x.list
```

### Elasticsearch/Kibana/Metricbeatのインストール

```
sudo apt update
sudo apt install elasticsearch-oss kibana-oss metricbeat-oss
```

## 設定ファイルの編集

### Elasticsearchの設定

```yml:/etc/elasticsearch/elasticsearch.yml
# localhost以外からのアクセスを許可する
network.host: 0.0.0.0
http.port: 9200
transport.host: localhost
transport.tcp.port: 9300

# JavaScriptからのCORSアクセスを許可する
http.cors.enabled: true
http.cors.allow-origin: "*"
```

### Kibanaの設定

```yml:/etc/kibana/kibana.yml
# localhost以外からのアクセスを許可する
server.host: "0.0.0.0"
```

### ElasticsearchとKibanaのサービス有効化・開始

```
sudo systemctl enable elasticsearch.service
sudo systemctl enable kibana.service

sudo systemctl start elasticsearch.service
sudo systemctl start kibana.service
```

### 接続確認1

`http://ubuntu.local:9200`にアクセス
レスポンスがかえって来たら成功。

```
{
  "name" : "fXjgLKE",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "WGnyRmUuSZemH70_ABZ3pg",
  "version" : {
    "number" : "6.5.4",
    "build_flavor" : "oss",
    "build_type" : "deb",
    "build_hash" : "d2ef93d",
    "build_date" : "2018-12-17T21:17:40.758843Z",
    "build_snapshot" : false,
    "lucene_version" : "7.5.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}
```

Kibana`http://ubuntu.local:5601`にアクセス。Kibanaの画面が表示されたら成功。

### Metricbeatの設定

Kibanaにダッシュボードを追加

```
metricbeat setup --dashboards
```

### Metricbeatのサービス有効化・開始

```
sudo systemctl enable metricbeat.service

sudo systemctl start metricbeat.service
```

### 接続確認2

Metricbeatのデータが上手くElasticsearchに入れば、Kibanaでこんな画面が見れます

![Screenshot_2019-01-03 [Metricbeat System] Host overview - Kibana.png](https://qiita-image-store.s3.amazonaws.com/0/41574/cfb90d6a-1ee4-6c1a-b5e9-bbdd864d57dc.png)

# JavaScriptで可視化

Google Charts ( https://developers.google.com/chart/?hl=ja ) でグラフ化します。

ElasticsearchのREST APIで検索します。Aggregationでいい感じに平均値を取得します。

POST http://ubuntu.local:9200/metricbeat-*/_search

```json:リクエスト
{
  "size": 0,
  "query": {
    "bool": {
      "filter": {
        "range": {
          "@timestamp": {
            "gte": "now-7d"
          }
        }
      },
      "must": [{
        "match": {
          "metricset.name": "cpu"
        }
      }, {
        "match": {
          "beat.hostname": "ubuntu"
        }
      }]
    }
  },
  "aggs": {
    "date_histogram": {
      "date_histogram": {
        "field": "@timestamp",
        "interval": "10m"
      },
      "aggs": {
        "system_cpu_total_pct": {
          "avg": {
            "field": "system.cpu.total.pct"
          }
        }
      }
    }
  }
}
```

```JSON:レスポンス
{
  "took" : 16,
  "timed_out" : false,
  "_shards" : {
    "total" : 4,
    "successful" : 4,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 9239,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "date_histogram" : {
      "buckets" : [
        {
          "key_as_string" : "2019-01-01T14:50:00.000Z",
          "key" : 1546354200000,
          "doc_count" : 59,
          "system_cpu_total_pct" : {
            "value" : 1.2820169491525424
          }
        },
        {
          "key_as_string" : "2019-01-01T15:00:00.000Z",
          "key" : 1546354800000,
          "doc_count" : 60,
          "system_cpu_total_pct" : {
            "value" : 0.7167333333333333
          }
        },
        {
          "key_as_string" : "2019-01-01T15:10:00.000Z",
          "key" : 1546355400000,
          "doc_count" : 60,
          "system_cpu_total_pct" : {
            "value" : 0.6058666666666668
          }
        },
        {
          "key_as_string" : "2019-01-01T15:20:00.000Z",
          "key" : 1546356000000,
          "doc_count" : 60,
          "system_cpu_total_pct" : {
            "value" : 0.5145166666666667
          }
        },
        {
          "key_as_string" : "2019-01-01T15:30:00.000Z",
          "key" : 1546356600000,
          "doc_count" : 60,
          "system_cpu_total_pct" : {
            "value" : 0.5042166666666666
          }
        },
        {
          "key_as_string" : "2019-01-03T02:10:00.000Z",
          "key" : 1546481400000,
          "doc_count" : 60,
          "system_cpu_total_pct" : {
            "value" : 0.09896666666666668
          }
        },
        {
          "key_as_string" : "2019-01-03T02:20:00.000Z",
          "key" : 1546482000000,
          "doc_count" : 60,
          "system_cpu_total_pct" : {
            "value" : 0.10701666666666668
          }
        },
        {
          "key_as_string" : "2019-01-03T02:30:00.000Z",
          "key" : 1546482600000,
          "doc_count" : 60,
          "system_cpu_total_pct" : {
            "value" : 0.09681666666666668
          }
        },
        {
          "key_as_string" : "2019-01-03T02:40:00.000Z",
          "key" : 1546483200000,
          "doc_count" : 60,
          "system_cpu_total_pct" : {
            "value" : 0.13956666666666667
          }
        },
        {
          "key_as_string" : "2019-01-03T02:50:00.000Z",
          "key" : 1546483800000,
          "doc_count" : 27,
          "system_cpu_total_pct" : {
            "value" : 0.09644444444444444
          }
        }
      ]
    }
  }
}
```

このJSONをいい感じに変換して、Google Chartsで折れ線グラフにしてみます。

![スクリーンショット (86).png](https://qiita-image-store.s3.amazonaws.com/0/41574/9a227da9-a43f-747c-62e4-9387c14d1aa6.png)

できました。

ソースはこんな感じで

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Page Title</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  <script type="text/javascript" src="app.js"></script>

</head>
<body>
  <div id="chart" style="width: 900px; height: 500px"></div>
</body>
</html>
```



```javascript:app.js
google.charts.load('current', {
  'packages': ['corechart']
});
google.charts.setOnLoadCallback(drawChart);

function drawChart() {

  var url = 'http://ubuntu.local:9200/metricbeat-*/_search'
  var data = {
    "size": 0,
    "query": {
      "bool": {
        "filter": {
          "range": {
            "@timestamp": {
              "gte": "now-7d"
            }
          }
        },
        "must": [{
          "match": {
            "metricset.name": "cpu"
          }
        }, {
          "match": {
            "beat.hostname": "ubuntu"
          }
        }]
      }
    },
    "aggs": {
      "date_histogram": {
        "date_histogram": {
          "field": "@timestamp",
          "interval": "10m"
        },
        "aggs": {
          "system_cpu_total_pct": {
            "avg": {
              "field": "system.cpu.total.pct"
            }
          }
        }
      }
    }
  }

  fetch(url, {
    method: 'POST',
    body: JSON.stringify(data),
    headers: {
      'Content-Type': 'application/json'
    }
  }).then(function (response) {
    return response.json()
  }).then(function (response) {
    var data = []
    data.push(['日付', 'CPU使用率'])

    for (const date_histogram of response.aggregations.date_histogram.buckets) {
      var key = date_histogram.key
      var value = date_histogram.system_cpu_total_pct.value
      data.push([new Date(key), value * 100])
    }
    return data
  }).then(function (response) {
    var data = google.visualization.arrayToDataTable(response)

    var options = {
      title: 'CPU使用率',
      hAxis: {
        format: 'M/d H:mm'
      },
      legend: {
        position: 'bottom'
      }
    };

    var chart = new google.visualization.AreaChart(document.getElementById('chart'));

    chart.draw(data, options);
  })
}
```


# 参考サイト

初心者のためのRest APIから覚えるElasticsearch
https://qiita.com/_bsoo/items/d880831e644175782ee0

elasticsearchでlocalhost以外からのアクセスを許可する方法
https://qiita.com/fuku2014/items/c2e2ffc07da5e2d2ba05