ELK Stackでシステム監視 kibanaのTimelion,Timeseriesでグラフ作成

今回はTimelion, VisualizeのTimeseriesを使ってグラフを作る第一歩。
例として挙げるのはcollectdで収集したネットワーク通信量RX(受信)とTX(送信)。このRXとTXはネットワークインターフェースがOSで利用可能になってからの通信総量なので単純にグラフにすると(通信が行われているなら)常に右肩上がりになる。クルマでいえば走行距離のメーターのようなの。(ただし、クルマはエンジンを停めてもメーターが0に巻き戻らないけど通信量はOSの再起動などで0に巻き戻る)
で、通信量の数値は増えたからといって「それが何なの?」的な。これを通信速度のような形に変えてやるとわかりやすいものになる筈。

VisualizeのTimeseriesの方がテキストボックスが複数行あって編集しやすいので個人的には好きだが、とりあえずTimelionでグラフを作ることにする。

Timelion, VisualizeのTimeseriesを使って自在にグラフを作る 1
画面1:
先ずは、今回作成するグラフのデータRXとTXがどのようなものか確認する。
取り敢えずホスト名で絞り込む。それとcollectd_typeをif_octetsで絞る。if_octetsはバイト単位。if_packetsはパケット単位なので今回は使わない。if_errorsも使わない。さらに本来であればplugin_instanceでネットワークインターフェースを絞るのだが、今回はネットワークインターフェースが1つしかないということにしてこれは絞らないことにする。
なお、今回はTimelion, Timeseriesなのでこの絞り込み条件でSearchオブジェクトを作成保存する必要は無い。

Timelion, VisualizeのTimeseriesを使って自在にグラフを作る 2
画面2:
左列のメニューからライオンのアイコン(Timelion)を選択する。
上部のテキストボックスには .es(*) が入っている筈。(初期値)
とりあえずは、 .es(hoge) が1つのグラフになると考える。hogeの部分はこれから。

Timelion, VisualizeのTimeseriesを使って自在にグラフを作る 3
画面3:
.es( hoge ) のhogeの部分だが、本来はインデックスとタイムフィールドを書く。collectdで収集したデータをlogstashで受けているならそれぞれindexはlogstash-*、タイムフィールドは@timestamp決め打ちで良いかと。ただし、この記事ではこの2つは(ゴチャゴチャするのが嫌なので)省略する。

.es(index='logstash-*', timefield='@timestamp', q='hoge', metric='hage')

データを条件で絞るのにはキューを使う。今回は画面1で見たようにホスト名をhoge、collectd_typeをif_octetsで絞るので q='host:hoge AND collectd_type:if_octets' となる。
使用する値として(まずは)RXの最大値を指定する。 metric='max:rx' となる。
Timelionでグラフを作るときはグラフの凡例(ラベル)を分かりやすく付けてやるのをクセ付ける方が良いかも。なのでラベル指定を追加する。形式は.es(hoge).label('文字列')のように後付けする。

.es(q='host:hoge AND collectd_type:if_octets', metric='max:rx').label('RX: 通信総量(bytes)')

これで上の画像のようになる。

Timelion, VisualizeのTimeseriesを使って自在にグラフを作る 4
画面4:
通信総量は監視する対象としてはあまり適さないのでこれを通信速度に変えたい。
画面3で作った総量のグラフの他に1分遅れのグラフを作成する。1秒遅れでも良いんだけど、1秒ごとにcollectdでデータを取って送信してlogstashで受信してelasticsearchに溜めるというのはそれに割くCPUパワー等が勿体無いかつデータが溜まり過ぎるのでcollectdで1分のインターバルを指定して1分ずつデータを送るようにしている。Timelionで1分遅れのグラフにするには offset='ずらしたい時間' のように指定する。 また、グラフを複数表示するのは .es(1つめ), .es(2つめ) のようにする。

.es(q='host:hoge AND collectd_type:if_octets', metric='max:rx').label('最新の値'), 
.es(q='host:hoge AND collectd_type:if_octets', metric='max:rx', offset='-1m').label('1分前の値')

見やすいように2行にした。

時間軸方向にずらすとその差分がずらした時間の通信量になるので、その時間で割れば速度になる。
つまり一定時間で分割して差分を取れば良いわけ。

Timelion, VisualizeのTimeseriesを使って自在にグラフを作る 5
画面5:
差分のグラフを作成する。作り方は .es(最新).subtract(.es(1分遅れ)) となる。これで1つのグラフ。やはり最後にラベルを指定する。

.es(q='host:hoge AND collectd_type:if_octets', metric='max:rx').subtract(.es(q='host:hoge AND collectd_type:if_octets', metric='max:rx', offset='-1m')).label('RX: 1分間の通信量(bytes)')

Timelion, VisualizeのTimeseriesを使って自在にグラフを作る 6
画面6:
ここまでRX(受信)だけなのでTX(送信)も追加する。単純にここまで作ったRXのグラフのrxの部分をtxに変えたのがTXのグラフ。それを並べて , を挟む。

.es(q='host:hoge AND collectd_type:if_octets', metric='max:rx').subtract(.es(q='host:hoge AND collectd_type:if_octets', metric='max:rx',offset='-1m')).label('RX: bytes/分'), 
.es(q='host:hoge AND collectd_type:if_octets', metric='max:tx').subtract(.es(q='host:hoge AND collectd_type:if_octets', metric='max:tx',offset='-1m')).label('TX: bytes/分')

見やすいように2行にした。

Timelion, VisualizeのTimeseriesを使って自在にグラフを作る 7
画面7:
これで通信量から速度になったが、bytes/分という単位は慣れないかもしれない。そこでよく使うbits/秒(bps)に変える。bytes/分は60で割ればbytes/秒(ただし1分間の平均速度)になる。また、bytes/秒は8を掛ければbits/秒になる。つまり60で割って8掛けるので結果的に7.5で割ることになる。
これは .es(グラフ).divide(7.5) と書くことができる。
ちなみに 7500で割ればKbps、7500000で割ればMbps。

.es(q='host:hoge AND collectd_type:if_octets', metric='max:rx').subtract(.es(q='host:hoge AND collectd_type:if_octets', metric='max:rx',offset='-1m')).divide(60).label('RX: bits/秒'), 
.es(q='host:hoge AND collectd_type:if_octets', metric='max:tx').subtract(.es(q='host:hoge AND collectd_type:if_octets', metric='max:tx',offset='-1m')).divide(60).label('TX: bits/秒')

Timelion, VisualizeのTimeseriesを使って自在にグラフを作る 8
画面8:
ところで、人によってはRTとTXを同じ側に表示するのを嫌うかもしれない。折れ線が入り組むと見にくい。上の画像のような1エリアに複数のグラフを描く場合は棒グラフは他のグラフを隠すのであまりオススメしない。
そこでたとえばTXをマイナス値で表示してエリア分けしてみる。TXの差分の取り方を逆にするだけ。

.es(q='host:hoge AND collectd_type:if_octets', metric='max:rx').subtract(.es(q='host:hoge AND collectd_type:if_octets', metric='max:rx', offset='-1m')).divide(7500).label('RX: Kbps'), 
.es(q='host:hoge AND collectd_type:if_octets', metric='max:tx', offset='-1m').subtract(.es(q='host:hoge AND collectd_type:if_octets', metric='max:tx')).divide(7500).label('TX: Kbps')

これで上の画像のようになる。

通信総量なのでOSを再起動するなどで差分がマイナス値の起動前通信総量となる。再起動前の通信総量が巨大な数値だとグラフが使い物にならない状態になる。グラフ毎に.min(0)や.max(0) を付けるなどしてマイナス値またはプラス値を表示させないようにする。
または、プラス値しか存在しえないのであれば、全てのグラフの最後に.yaxis(min=0)を付けるとグラフ毎に書く必要がない。

Timelion, VisualizeのTimeseriesを使って自在にグラフを作る 9
画面9:
ここまでTimelionで作ったテキストボックスの内容をコピー(してVisualizerに貼り付けることに)する。
左列のメニューでVisualizerをクリックし、新しいVisualizeオブジェクト作成のために(新規作成)をクリック。

Timelion, VisualizeのTimeseriesを使って自在にグラフを作る 10
画面10:
Timelion Expressionのテキストボックスにコピーした内容を貼り付ける。
[]を押してグラフが正しく描かれることを確認する。(時間範囲を変えるなどもする)
もし、折れ線が嫌で棒グラフにしたいということであれば .es(グラフ).label('文字列').bars(stack=false width=3) のようにする。棒グラフは初期値がStack(重ねる)なので注意。重ねたい場合を除いてstack=falseを書く方が安全。(マイナス値があってstackさせるとグラフとしては破綻する)棒の太さはwidthで指定。label()とbars()の前後の位置関係はどっちでも良い。
問題無いようであれば[Save]で名前を付けて保存する。

Timelion, VisualizeのTimeseriesを使って自在にグラフを作る 11
画面11:
1つ前の画面10で作成したVisualizeオブジェクトをDashboardに[Add](追加)して保存する。
上の画像では一番下のグラフが今回作成したネットワークインターフェースの送受信速度(Kbps)、ただし1分間の平均速度。棒グラフにしてみた。

今回はTimelion, Timeseriesによるグラフ作成のキホンのキでExcelでいえばワークシート関数を初めて書くくらい。これが思い通りに書けて何でも出来る気になってくるととんでもないのを作ってelasticsearchのメモリが足りないとかになるのでほどほどに。

2018年2月19日修正: 初稿は間違った置換をしたクエリー .es(q='hoge, hage')で公開してたので修正した。正しくは(q='hoge AND hage')でした。

関連記事:

ELK Stackでシステム監視 collectdでDNSサーバの情報収集

前々回NTPサーバの情報収集を行ったのと大して変わらないかもだけどDNSサーバBINDの情報をcollectdで収集する。

collectdのプラグインはビルドの仕方によっては使えないものがある。FreeBSDのpkgでインストールした場合はbindプラグインに非対応なのでportsでビルドしてインストールする。その際、make configでCURL_JSONにチェックすることで、collectdのbindプラグインが利用可能になる。

BINDの設定変更

/usr/local/etc/namedb/named.conf (3行追加)
statistics-channels {
    inet 127.0.0.1 port 8053 allow {127.0.0.1;};
};
BIND側で統計情報を出力するように変更。上の例だとローカルホストのポート8053で統計情報にアクセス可能。

BINDの設定再読み込み

# service named reload

/usr/local/etc/collectd.conf (4行追加)
LoadPlugin bind
<Plugin bind>
    URL "http://localhost:8053/"
    OpCodes         true
    QTypes          true
    ServerStats     true
    ZoneMaintStats  true
    ResolverStats   true
    MemoryStats     false
</Plugin>

BINDが出力する統計情報にbindプラグインからアクセスして情報を取得する。なのでURL指定はローカルホストで、BIND側で設定したのと同じポート番号を指定する。


collectdの再起動

# service collectd restart

続く

関連記事:

LineageOS 15.1でイースターエッグと貢献者を表示

LineageOS 15.1でイースターエッグを表示 1
画面1:
Android設定から「端末情報」の画面を開く。

LineageOS 15.1でイースターエッグを表示 2
画面2:
上の画面1で①「Androidバージョン」を連打3回でAndroidのイースターエッグを開く。
オレオの絵が表示されるのでオレオを長押しするかオレオの縁をクルリと指でなぞるかすると次に進む。

LineageOS 15.1でイースターエッグを表示 3
画面3:
Android 8.0と8.1ではおなじみのタコっぽい気持ち悪い何か。

LineageOS 15.1でイースターエッグを表示 4
画面4:
上の画面1で②「LineageOS version」を連打3回でLineageOSのイースターエッグを開く。
LineageOSのロゴが表示されるので長押しするか白丸の縁をクルリと指でなぞるかすると次に進む。

LineageOS 15.1でイースターエッグを表示 5
画面5:
タコでもなくクラゲっぽい何か。ほとんど画面3のタコと同じだが、足が4本というのは何を意味するのだろう。Android8でタコが採用されたのは足が8本だからという認識だったんだけど。

LineageOS 15.1でイースターエッグを表示 6
画面6:
上の画面1で③「貢献者」を選択。
LineageOSのロゴのようなものが表示される。

LineageOS 15.1でイースターエッグを表示 7
画面7:
拡大すると人の名前でロゴが作られているのがわかる。
右上の(検索)を押して見る。

LineageOS 15.1でイースターエッグを表示 8
画面8:
懐かしい名前だけどその人しか知らないのでSteve Kondikさんを探す。名前の一部を入力すると候補がリスト表示されるので目的の人を選択する。

LineageOS 15.1でイースターエッグを表示 9
画面9:
検索した人の名前が赤色になって(画面7の)その名前のある場所が拡大した状態で表示される。

「がとらぼ」の中の人には到底無理だけど、何か貢献してこういう風に自分の名前が出るの良いよね。

LineageOS 15.1 スクリーンショットのファイル名
画面10:
ところで、最近のリビジョンでスクリーンショットのファイル名の付け方が変わったみたい。
以前は Screenshot_日付_時間.png だったのが、 Screenshot_アプリ名_日付_時間.png になった。
撮影したアプリ名がファイル名に入ることによってわかりやすくなったように思えるがアプリ名のせいで「ファイル名」でソートしていると並びが狂うので逆にわかりにくい。常にファイラーのサムネイル表示させながらでないと画像を選び間違える元に。