InfluxDB と Grafana で可視化して Puppeteer で PDF を生成

はじめに

計測データのグラフや表をまとめたいことが 何度かあったんですがちょうどいいツールを見つけられていませんでした。

エクセルでグラフを作ったりgnuplotでグラフを作ったりもできますが 見た目をかっこよくまとめるのは慣れないと難しそうに感じました。

Grafana は前に目にしたことがあったんですが 常時計測したデータの可視化用でちょっと使いたい用途には合わないかなと思ってました。

ただ docker-compose を使って CLI ツールのようにまとめることで やりたい用途にも使えそうだなと思い試してみました。

実験に使ったリポジトリはここに置いています。

github.com

やり方

InfluxDB, Grafana, Puppeteer のコンテナを docker-compose で連携させるというやり方です。 なんでも docker でやってみたくなっている感じが少しあります。 色々なツールを使っていて全部直接入れるのはちょっと気が引けるし、環境構築も大変なので実際こういう用途では便利だと思います。

InfluxDB

www.influxdata.com

InfluxDB は時系列データを扱うデータベースで Go 言語で書かれているようです。 Grafana とセットでよく使われているのを目にする気がします。 データの有効期限を設定できるようで常時計測しているデータの保存などに使うことが多いようです。

InfluxDB Line Protocol reference | InfluxData Documentation

Writing data with the HTTP API | InfluxData Documentation

Line Protocol の書き方と curl での API 呼び出し方の例を真似してデータを取り込むことができました。

公式のイメージが Docker Hub にありました。

https://hub.docker.com/r/library/influxdb/

Grafana

grafana.com

Grafana はデータの可視化用のウェブサーバーで GUIダッシュボードに色々なグラフを表示したりできます。 InfluxDB 以外にも色々なデータソースを扱うことができるようです。 Grafana もサーバー部分は Go 言語のようです。

Grafana も Docker Hub にイメージがありました。

https://hub.docker.com/r/grafana/grafana/

Puppeteer

github.com

Puppeteer は Chrome の開発用 API を利用できる Node ライブラリです。

ウェブページの PDF を作るのに他のツールも少し使ってみたのですが

表示が終わるのを待つなど細かい制御をするには Puppeteer を使ったほうがうまく行きそうだったので使ってみることにしました。

下のような感じで PDF の保存ができました。

const puppeteer = require('puppeteer');
const url = process.argv[2];
const output_path = process.argv[3];
const width = 1080;
const height = 1920;

(async() => {
    const browser = await puppeteer.launch({
        headless: true,
        executablePath: 'chromium-browser',
        args: ['--no-sandbox', '--disable-setuid-sandbox']
    });

    const page = await browser.newPage();
    await page.setExtraHTTPHeaders({
        Authorization: 'Basic ' + new Buffer('admin:admin').toString('base64')
    });

    await page.setViewport({
        width: width,
        height: height,
        isMobile: false
    });

    await page.goto(url, {waitUntil: 'networkidle2'});

    await page.pdf({
        path: output_path,
        width: width + 'px',
        height: height + 'px',
    });

    await browser.close();
})();

puppeteer/troubleshooting.md at master · GoogleChrome/puppeteer · GitHub

ここの Dockerfile の書き方を参考にイメージを作りました。

docker-compose 設定

docker-compose 設定は下のようになりました。 Grafana のダッシュボードとデータソースの設定は /etc/grafana/provisioning/ 以下に設定ファイルを置くと反映されるので 設定ファイルを置いたディレクトリをマウントするようにしています。

version: "3"
services:
  influxdb:
    image: influxdb:1.6.2
    ports:
      - "8086:8086"
  grafana:
    image: grafana/grafana:5.2.4
    ports:
      - "3000:3000"
    volumes:
      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards
      - ./grafana/datasources:/etc/grafana/provisioning/datasources
    depends_on:
      - influxdb
  puppeteer:
    build:
      context: .
      dockerfile: Dockerfile.puppeteer
    volumes:
      - ./volume:/volume
    entrypoint:
      - ./run-puppeteer.sh
    depends_on:
      - grafana
      - influxdb

生成した PDF

一連の流れを試してみるのが目的だったので見栄えしないグラフ一つしかありませんが下のような感じで生成できました。 Grafana のダッシュボードは kiosk=true の GET パラメーターを付けるとメニューを非表示にできるようです。 やろうと思えば Puppeteer で少し見た目を加工するなどもできるのかなと思います。

f:id:tkaaad97:20180919004337p:plain

まとめ

InfluxDB にデータを取り込み Grafana で表示して Puppeteer で PDF 作成という一連の流れをdocker-compose で CLI 化することができました。 はじめて使うものが多かったので少し時間がかかりましたが今後も使う機会がありそうなので少しは慣れることができてよかったと思います。

Puppeteer で PDF 生成する前に Grafana のサーバーが立ち上がるのを少し待つ必要があるのを今回は10秒スリープするといういい加減な方法で対応しました。 こういう用途には wait-for-it や dockerise が使えるらしいです。

Compose の起動順番を制御 — Docker-docs-ja 17.06.Beta ドキュメント