Grafana+InfluxDBでデータを可視化してみよう
まえがき
とある研究室での一幕
Grafanaのページを見せながら
教授「…というわけで、GrafanaとInfluxDBを使って情報を可視化するとよさそうじゃないですか?」
少し考えてから
私 「いいと思います」(なお一度も触ったことはない)
というわけでGrafanaを使ったデータの可視化をやることになりました。どうもウグイスです。
前のブログからは2か月くらいですかね?お久しぶりです。
空白の2ヶ月の間は、授業のプロジェクトがデスマーチ状態になったりしてました。それも解消されたのでブログの投稿は増えると思います。
単純に使うので勉強したかった&ブログが書きやすそうなので、この題材でブログを書くことにしました。
ちなみに前半後半の2部構成になると思います。どっちも見ていってください。
GrafanaとInfluxDBとは
Grafana
Grafanaはデータの可視化ツールです。
具体的にはデータベースとかに接続して、クエリを定期的に投げることで、リアルタイムにデータを取得します。
そしてそれをいい感じにグラフとかに表示できるツールです。
GUIで設定できるので、プログラム弱者でも割と簡単に設定できると思います。
ちなみに対応しているデータベース等は公式のページから確認できます。
結構主要なのには対応していて、RDBだとMySQL,PostgreSQLとかですね。
InfluxDB
InfluxDBは時系列データベースです。
時系列データベースはRDB(リレーショナルデータベース)と比べると高速に読み書きができて、データの更新頻度が高いもののデータを扱うのに向いているらしい
クライアントライブラリがいくつかの言語で用意されている。
Swift,scala,ruby,r,python,php,kotlin,javascript,java
そもそもHTTP APIがあるので、通信さえできれば割となんとかなる?(知らんけど)
やりたいこと
説明とかはここら辺にして、本題に入ります。
やりたいこととしては、ESP32に温湿度計を付けてそのデータをGrafanaで表示したいって感じです。
とりあえずやりたいことをざっくりと図にしてみました。
前半のこのブログではラズパイの部分を作っていこうかなと思います。ESP32とかの部分は後半に回します。
GrafanaとInfluxDBについて
メイン部分はラズパイ400ですね。最近勉強用に買ったので、せっかくだし使ってみようって感じです。(自宅にlinuxPCがないという事情もある)
メインのGrafanaとInfluxDBですが、Dockerで動かします。
データ受付Serverについて
ESP32からの通信を受け取って、InfluxDBにデータを渡すサーバを、間に挟んでいます。言語がkotlinなのは趣味
InfluxDBはHTTP APIを使ってデータを書き込むことができる。今回の場合だとサーバプログラムいらないですね。(ESP32側からInfluxDBに直接送信すればいい)
研究室では間にプログラムが必要だと思うので、勉強用に入れています。
残りの要素について
ユーザはGrafanaのURLにブラウザからアクセスして設定をしたりグラフを見たりします。
ESP32はデータを送信するだけですね。(やったことないからできるかわからんけど)
環境を整える
Raspberry Pi 400
ラズパイ400に必要なものをインストールします。
とりあえずいつものおまじない
sudo apt update
sudo apt upgrade
kotlinでサーバを作るのでjavaの環境が必要です。(2個目のコマンドのversionは自分のほしいバージョンを選ぶ)
sudo apt search openjdk
sudo apt install openjdk-{version}-jdk
dockerのインストール
sudo apt install docker.io
dockerを使用しているユーザで使えるようにする(userはユーザ名)(Dockerはデフォではrootユーザしか使えない)
sudo usermod -aG docker {user}
sudo reboot
docker-composeのインストール
sudo apt install docker-compose
自分のWindowsPC
サーバプログラム作成は自分のパソコンでやるので
- IntelliJ IDEA 2021.3.3のインストール
Ktorプラグインの導入
(7/17加筆)
Ktorプラグインは廃止されて推奨じゃない?みたいなので見なかったことにしてください。
よってIntelliJ IDEAに関しては好きなバージョンを選んでください。
情報を確認せずに書いて申し訳ない。
IntelliJ IDEAが最新バージョンじゃないのはKtorプラグインが対応していないからです。
もし読んでいる段階で変わっていたら最新のものを使えばいいと思います。
以前からインストールしているので、細かい説明はしないです。
とりあえず動かしてみる
とりあえずディレクトリ構造はこんな感じ(grafanaより親の情報はいらないので省略してます)
grafana/
├docker-compose.yml
├grafana/
├influxdb/
docker-compose.ymlの中身はこんな感じ
version: "2"
services:
influxdb:
image: influxdb
hostname: influxdb
ports:
- 8086:8086
volumes:
- ./influxdb:/var/lib/influxdb
grafana:
image: grafana/grafana
ports:
- 8085:3000
user: "472"
volumes:
- ./grafana:/var/lib/grafana
depends_on:
- influxdb
この状態で実行すると、書き込みできません的なエラーが出るので
grafana/grafanaの所有者を変える必要があります。
カレントディレクトリが親の方のgrafanaであることを確認して
sudo chown 472:472 grafana
これで準備は整いましたので起動します。
docker-compose up -d
これでGrafanaとInfluxDBが起動します。
起動確認
ラズパイから確認
まずコンテナがあるかの確認ですね。
docker ps
正常ならgrafana/grafanaとinfluxdbというImage名のコンテナがあると思います。
ブラウザから確認
Grafana
ラズパイにもchroniumというブラウザがデフォで入ってますが、今回は同じLAN内の別のパソコンから確認しました。(スクショがしやすい)(ラズパイから確認する人はipアドレス部分を127.0.0.1にするかlocalhostとかでアクセスできると思います)
ラズパイのIPアドレスを確認します。
ip addr
これでwlan0の欄に私の場合だと192.168.50.222ですが、それぞれのipアドレスが表示されていると思います。
固定IPにしていない場合、本体の再起動などでIPアドレスが変わる場合があります。IPが変わると困る人は設定しましょう。私はこの段階では必要ないのであとでやります
適当なブラウザ(私はChrome)を開いて。リンクを入力します
ラズパイのIPアドレス:8085
うまくいっていればGrafanaのログイン画面が出てると思います。(スクショするの忘れた)
デフォルトではユーザ名もパスワードもadminです。
入力すると、パスワード変更画面が出ます(下図)
パスワードを適当に決め、入力して次に進みます。
以下のようなホーム画面が出てくると思います。
これでGrafanaが起動して正常に動作していることが確認できました。
InfluxDB
まずはデータベースの方から準備していきます。
ブラウザから以下のアドレスにアクセス
ラズパイのIPアドレス:8086
初めてのアクセスだとこんな画面になるはず。
GET STARTEDを押すと以下の画面になるはず。
ユーザネームとパスワードは適当に決めてください。忘れないようにメモっておくといいかも
Initial Organization Nameは組織名ですね。適当でいいと思います。
Initial Bucket Nameはバケットの名前ですね。バケットはRDBのデータベースにあたるものです。これも適当で大丈夫です。あとで追加もできますし
全部入力して、continueを押せば以下の画面になるはず。
QUICK STARTを押せば以下の画面になるはず。
完了です。
これでGrafanaとInfluxDBがどちらも動いていることが確認できました。
ついでに最低限のアカウントの設定も終わりました。
InfluxDBとGrafanaの接続
ここからはこまごまとした設定をやっていきます。もうひと踏ん張りです。
InfluxDB
左のバーから上矢印的なマークをクリックして、API Tokensをクリック。
以下のような画面になると思います。(画像はTokenを追加した後のもの)
デフォルトでは{user名}’s Tokenみたいなのがあると思います。これはすべての操作を受け付けてしまう最強トークンです。私は別にトークンを作りました。(気にならない人なら最強トークンを使って大丈夫です)
CREATE API TOKENからトークンを作れます。あとでデータベースにプログラム等からデータを入れるときと、Grafanaとの接続で必要になります。
それぞれのAPIをクリックするとAPIトークンがコピーできるようになってます。あとで使います。
Grafana
左のバーから設定ボタンみたいなのをクリック。(画像のようにその中からDataSourceの部分をクリックしてもいい)
以下の画面になるので、Add data sourceをクリック
以下の画面になるので、InfluxDBを選択(写真の赤枠部分)
いろいろ設定できると思います。とりあえず必要な部分を設定します。
まずQuery LanguageはFlux
HTTP > URLはhttp://influxdb:8086 (画像はミスなので気にしないでください)
Organizationは自分で設定したものを、Tokenは使うAPIキーをコピって貼り付け。バケット名は作ったものを入力してください。
全部入力して、Save & testを押す。うまくいくと以下のようにバケットが何個あるか表示される。(私の場合、使うバケット以外は許可してないので1つ)
これで完了です
試しにデータを入れて表示する
InfluxDBにデータを入れる
ここまででInfluxDBとGrafanaの接続は出来ました。
ここでいきなりサーバープログラムを書いてもいいのですが、一度グラフ表示を見た方がモチベが上がるので適当なデータを入れて可視化します。
InfluxDBのサイトから上矢印からBucketsをクリック
以下の画面になるので、データを追加したバケットのADD DATAをクリック
Line Protocolを選択
以下の画面になる
ENTER MANUALLYを選んで、Precision: Secondsに設定し、以下の3列を書きWriteをクリック
test,tagKey=test percent=64.23 1657872005
test,tagKey=test percent=72.01 1657872010
test,tagKey=test percent=62.61 1657872015
Successfullyとか表示されたら成功
Grafanaで表示する
Grafanaの画面から、左のバーからnew dashboardとかを選ぶ。
Add new panelを選択する。以下の編集画面になる。
下のいかにもコードが打てそうなところに以下のプログラムを入力(bashとなってますが、実際はFluxというものです)
from(bucket: "room_sensors")
|> range(start: v.timeRangeStart, stop:v.timeRangeStop)
|> filter(fn: (r) =>
r._measurement == "test" and
r._field == "percent"
)
1行目のbucket名は自分のものに合わせてください。
多分、以下のような感じでデータが表示されると思います。(表示されない場合は画像の赤枠がタイムレンジなので、それをいじくって2022/7/15のデータが表示されるようにしてください)
マウスのドラッグで選んだ範囲を拡大表示できるので。緑色の部分を拡大します。
これで入力したデータが表示できることが確認できました。
あとは、右上のApplyを押して、そのあとダッシュボードを保存すれば完了です。
InfluxDBのクライアントライブラリ(Kotlin)を使う
ブログが長くなってきたので、サーバープログラムは次のパートに分けるとします。
じゃあここでは何するかといえば、InfluxDBのクライアントライブラリを使って、データを1秒ごとに送り、それをGrafanaでリアルタイム監視するということをやろうと思います。
というわけでプログラミングのターンです。ここまでずっと設定ばかりなので、やっとできるといったところですね。
環境作り
適当にコンソールアプリケーションを作ります。以下の画像のようにKotlin > Console Applicationを選び名前とかいろいろ決めます。
そのまま作成すれば以下の画面になると思います。
build.gradle.ktsを開き、以下の1行をdependenciesブロック内に追記します。
implementation("com.influxdb:influxdb-client-kotlin:6.3.0")
多分、dependenciesブロックは下みたいな感じになるはず。(kotlinなのですが訳あってjavaになってます)
dependencies {
testImplementation(kotlin("test"))
implementation("com.influxdb:influxdb-client-kotlin:6.3.0")
}
これで、必要なライブラリを入れれました。早速プログラムを作りましょう。
プログラミング
とりあえず、1秒に一回、60~80の間の数をランダムに送信するプログラムを作ろうと思います。
コマンドライン引数で回数を指定できるように作ろうと思います。
Main.ktと同じディレクトリにデータクラスTestDataを作成します。
TestData.kt
import com.influxdb.annotations.Column
import com.influxdb.annotations.Measurement
import java.time.Instant
@Measurement(name = "test")
data class TestData(
@Column(tag = true) val tagKey: String,
@Column val percent: Double,
@Column(timestamp = true) val time: Instant
)
メインはこんな感じ
Main.kt
import com.influxdb.client.domain.WritePrecision
import com.influxdb.client.kotlin.InfluxDBClientKotlinFactory
import kotlinx.coroutines.runBlocking
import java.time.Instant
fun main(args: Array<String>) {
//各種設定,各自で変わるのでそれに合わせて書き換える
val org = "yourOrganization"
val bucket = "room_sensors"
val url = "yourURL"
val token = "yourToken"
val times = args[0].toInt()
if(times <= 0) return
val client = InfluxDBClientKotlinFactory
.create(url,token.toCharArray(),org,bucket)
val writeApi = client.getWriteKotlinApi()
for(i in 0..times){
val testData = TestData("test",(60..80).random().toDouble(),Instant.now())
println("{testData}を送信します")
runBlocking {
writeApi.writeMeasurement(testData,WritePrecision.NS)
}
Thread.sleep(1000)
}
client.close()
println("{times}回送信しました")
}
ここから実行できます。最初は実行構成の変更からコマンドライン引数を設定する必要があります。
Grafanaから確認
さっきのダッシュボードから確認します。
成功です。
次回予告
Ktorを使ったサーバープログラムを作成します。
出来れば完成させたいですが、分量によってはさらにブログを分割するかもしれないです。
あとがき
ここまでで、ラズパイへのDockerのインストール、Docker上でのInfluxDBとGrafanaの実行。
Docker上の、InfluxDBとGrafanaの連携。
InfluxDBにKotlinのクライアントライブラリを使ったデータ送信までやりました。
ブログでは簡単にしてるように見えますが、情報をかき集めてやってるんで意外と時間がかかりました。
11/25追記
Grafana+InfluxDBのPart2を書きました。一応作りたいものは完成させました。時間のある時に読んでもらえると幸いです。
コメント入力