Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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

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

スクリーンショット (86).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の設定

/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の設定

/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"
}

Kibanahttp://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

JavaScriptで可視化

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

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

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

リクエスト
{
  "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"
          }
        }
      }
    }
  }
}
レスポンス
{
  "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

できました。

ソースはこんな感じで

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>
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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away