低価格Androidスマートフォン2019年秋 Xiaomi Mi Phoneシリーズ

みんな大好きXiaomi(小米=シャオミ)からMi Phoneシリーズ(ハイグレードの方)のミドルレンジ以下の機種です。2019年9月20日現在の現役モデルになります。

Xiaomi Mi 9 Lite

価格: US$330(36,000円)程度
SoC: Qualcomm Snapdragon 710
RAM: 6GB
ストレージ: 64GB 他に128GBモデル有り
画面: 6.39インチ FHD+ (2340 x 1080px) AMOLED
SIMスロット: デュアル
カメラ(外): 3カメラ 4800万画素+800万画素(広角用)+200万画素(被写界深度用)
カメラ(内): 3200万画素
バッテリー: 4030mAh
重量: 179g
USB: Type-C
初期OS: MIUI 10 (Android 9.0)
認証: 技適未確認
通信バンド: GSM 省略
3G: WCDMA /2 /3 /5 /8
4G: TDD-LTE 38 /40
4G: FDD-LTE 1 /2 /3 /4 /5 /7 /8 /20 /28
Wi-Fi: IEEE802.11 a/b/g/n/ac
Bluetooth: 5.0
Antutuスコア: 170000〜180000程度

性能はミドルレンジで、カメラがハイスペック、他全部入りに近い豪華な機種です。お値段が3万後半円なのでお高め。価格が範囲外なのでこのページで紹介予定ではありませんでしたが、性能がミドルなのでちょっと入れてみました。

Xiaomi Mi A3

価格: US$176 (19,000円)程度
SoC: Qualcomm Snapdragon 665
RAM: 4GB
ストレージ: 64GB 他に128GBモデル有り
画面: 6.1インチ HD+ (1560 x 720px) AMOLED
SIMスロット: デュアル
カメラ(外): 3カメラ 4800万画素+800万画素(広角用)+200万画素(被写界深度用)
カメラ(内): 3200万画素
バッテリー: 4030mAh
重量: 174g
USB: Type-C
初期OS: Android One (Android 9.0)
認証: 技適未確認
通信バンド: GSM 省略
3G: WCDMA 1 /2 /4 /5 /8
4G: TDD-LTE 38 /40
4G: FDD-LTE 1 /2 /3 /4 /5 /7 /8 /20 /28
Wi-Fi: IEEE802.11 a/b/g/n/ac
Bluetooth: 5.0
Antutuスコア: 140000程度

性能はミドルレンジで、カメラがハイスペック、画面がHD+解像度なのとAndroid Oneという点に注意。お値段は普通。

Xiaomi MI 9 SE

価格: US$280 (30,300円)程度
SoC: Qualcomm Snapdragon 712
RAM: 6GB
ストレージ: 64GB 他に128GBモデル有り
画面: 6インチ FHD+ (2340 x 1080px) AMOLED
SIMスロット: デュアル
カメラ(外): 3カメラ 4800万画素+1300万画素(広角用)+800万画素(望遠)
カメラ(内): 2000万画素
バッテリー: 3070mAh
重量: 155g
USB: Type-C
初期OS: MIUI 10 (Android 9.0)
認証: 技適未確認
通信バンド: GSM 省略
3G: WCDMA 1 /2 /4 /5 /8
4G: TDD-LTE 38 /40
4G: FDD-LTE 1 /2 /4 /5 /7 /8 /20 /28
Wi-Fi: IEEE802.11 a/b/g/n/ac
Bluetooth: 5.0
Antutuスコア: 180000程度

実売価格が3万円程度なのでちょっとお高めですが、隙きのないスペックで大きさと重量のバランスも良さげ。

Xiaomi MI 8

価格: US$270 (29,200円)程度
SoC: Qualcomm Snapdragon 845
RAM: 6GB 他に8GBモデル有り
ストレージ: 64GB 他に128GBモデル有り
画面: 6.2インチ FHD+ (2248 x 1080px) AMOLED
SIMスロット: デュアル
カメラ(外): 2カメラ 1200万画素(広角用)+1200万画素(望遠用)
カメラ(内): 2000万画素
バッテリー: 3400mAh
重量: 175g
USB: Type-C
初期OS: MIUI 10 (Android 9.0)
認証: 技適未確認
通信バンド: GSM 省略
3G: WCDMA 1 /2 /4 /5 /8
4G: TDD-LTE 34 /38 /39 /40 /41
4G: FDD-LTE 1 /2 /3 /4 /5 /7 /8 /12 /17 /20
Wi-Fi: IEEE802.11 a/b/g/n/ac
Bluetooth: 5.0
Antutuスコア: 290000程度

2018年夏のフラッグシップモデルです。実売価格が3万円程度から入手できてこの性能は凄い。しかし、古いので画面のノッチが大型で古臭さが強く、そこが残念ポイント。

Xiaomi MI 8 Lite

価格: US$152 (16,500円)程度
SoC: Qualcomm Snapdragon 660
RAM: 6GB 他に4GBモデル有り
ストレージ: 64GB 他に128GBモデル有り
画面: 6.26インチ FHD+ (2280 x 1080px) AMOLED
SIMスロット: デュアル
カメラ(外): 2カメラ 1200万画素+500万画素
カメラ(内): 2400万画素
バッテリー: 3350mAh
重量: 169g
USB: Type-C
初期OS: MIUI 10 (Android 8.1)
認証: 技適未確認
通信バンド: GSM 省略
3G: WCDMA 1 /2 /4 /5 /8
4G: TDD-LTE 38 /40
4G: FDD-LTE 1 /2 /3 /4 /5 /7 /8 /20 /28
Wi-Fi: IEEE802.11 a/b/g/n/ac
Bluetooth: 5.0
Antutuスコア: 140000程度

2018年夏のモデルです。実売価格が安価でバランスの良いミドルロー機種です。古いので画面のノッチが縦画面上部中央にありますが、水滴型には敵わないものの中サイズなので許容できる範囲かもしれません。

Xiaomi MI Max 3

価格: US$158 (17,000円)程度
SoC: Qualcomm Snapdragon 636
RAM: 4GB 他に6GBモデル有り
ストレージ: 64GB 他に128GBモデル有り
画面: 6.9インチ FHD+ (2160 x 1080px) 方式不明
SIMスロット: デュアル
カメラ(外): 2カメラ 1200万画素+500万画素
カメラ(内): 800万画素
バッテリー: 5500mAh
重量: 221g
USB: Type-C
初期OS: MIUI 10 (Android 8.1)
認証: 技適未確認
通信バンド: GSM 省略
3G: WCDMA 1 /2 /5 /8
4G: TDD-LTE 34 /38 /39 /40 41
4G: FDD-LTE 1 /3 /4 /5 /7 /8 /20
Wi-Fi: IEEE802.11 a/b/g/n/ac
Bluetooth: 5.0
Antutuスコア: 115000程度

ほとんどタブレットに近い大型スマートフォンです。そしてタブレット並に重いです。性能的にはちょうどミドルロー機種なので大きいのにゲームにも向きません。正直、どういうユーザーを想定しているのかわかりません。

Xiaomi MI A2

価格: US$158 (17,000円)程度
SoC: Qualcomm Snapdragon 660
RAM: 4GB 他に6GBモデル有り
ストレージ: 64GB 他に32GB, 128GBモデル有り
画面: 6.0インチ FHD+ (2160 x 1080px) 方式不明
SIMスロット: デュアル (4G対応は1つのみ)
カメラ(外): 2カメラ 2000万画素+1200万画素
カメラ(内): 2000万画素
バッテリー: 3010mAh
重量: 168g
USB: Type-C
初期OS: MIUI 10 (Android 8.1)
認証: 技適未確認
通信バンド: GSM 省略
3G: WCDMA 1 /2 /4 /5 /8
4G: TDD-LTE 34 /38 /40
4G: FDD-LTE 1 /2 /3 /4 /5 /7 /8 /20
Wi-Fi: IEEE802.11 a/b/g/n/ac
Bluetooth: 5.0
Antutuスコア: 125000程度

ノッチのない昔ながらの太ベゼルの機種です。個人的には巨大で醜いノッチよりよほど太ベゼルの方が好きです。

Xiaomi MI A2 Lite

価格: US$136 (14,700円)程度
SoC: Qualcomm Snapdragon 625
RAM: 3GB 他に4GBモデル有り
ストレージ: 32GB 他に64GBモデル有り
画面: 5.8インチ FHD+ (2280 x 1080px) 方式不明
SIMスロット: デュアル (4G対応は1つのみ)
カメラ(外): 2カメラ 1200万画素+500万画素
カメラ(内): 500万画素
バッテリー: 4000mAh
重量: 178g
USB: Micro USB
初期OS: Android One (Android 8.1)
認証: 技適未確認
通信バンド: GSM 省略
3G: WCDMA 1 /2 /5 /8
4G: TDD-LTE 38 /40
4G: FDD-LTE 1 /2 /3 /4 /5 /7 /8 /20
Wi-Fi: IEEE802.11 a/b/g/n
Bluetooth: 4.2
Antutuスコア: 75000程度

画面上部に醜い中型ノッチがあります。そして、実売価格がA2と大きくは変わらないのに性能だけはこれでもかといわんばかりに削られています。魅力ある機種とは思えません。

Xiaomi MI Mix 2S

価格: US$283 (30,600円)程度
SoC: Qualcomm Snapdragon 845
RAM: 6GB
ストレージ: 64GB 他に127GBモデル有り
画面: 6.0インチ FHD+ (2160 x 1080px) 方式不明
SIMスロット: デュアル
カメラ(外): 2カメラ 1200万画素+1200万画素
カメラ(内): 500万画素
バッテリー: 3400mAh
重量: 189g
USB: Type-C
初期OS: MIUI 9 (Android 8.1)
認証: 技適未確認
通信バンド: GSM 省略
3G: WCDMA 1 /2 /3 /4 /5 /6 /8 /9 /19
4G: TDD-LTE 34 /38 /39 /40 /41
4G: FDD-LTE 1 /2 /3 /4 /5 /7 /8 /12 /13 /17 /18 /19 /20 /25 /26 /27 /28 /29 30
Wi-Fi: IEEE802.11 a/b/g/n/ac
Bluetooth: 4.2
Antutuスコア: 290000程度

ノッチ無しの狭額モデルなのですっきりしています。フロントカメラは縦持ちで右下です。ポップアップではありません。Xiaomiらしいまさに理想的なスマートフォンです。携帯電話の対応バンドも豪華です。Xiaomiが好きでお値段3万円程度が支出可能なら購入する選択肢に入れたい機種の1つでしょう。Xiaomiのウェブの機種リストのMi Phonesシリーズでは何故か最後に掲載されていたのでこのページでも倣って最後にしていますが、性能から考えると上位のモデルです。特にこのページではトップ性能です。2018年春モデルで古いのでAndroid 10相当に更新されるかは不明です。

Prometheus2によるシステム監視 FreeBSD標準のエクスポーター prometheus_sysctl_exporterを使う

FreeBSD 12からはprometheus_sysctl_exporterというPrometheus用のExporterが何故かOS標準で入っている。
Linuxではprocで取れるような値でsysctlで取得できる値は、難しいことをしなくてもprometheus_sysctl_exporterで取れてしまう。
前々回あたりにやったFreeBSDのCPU温度取得はsysctlで取っていたので、当然それもprometheus_sysctl_exporterで取れる。
FreeBSDだとNode Exporterでは取れない値が多いのだが、prometheus_sysctl_exporterが一部その代替となるかも。

問題は「がとらぼ」の中の人が管理するホストにはFreeBSD 11がまだ半分ほど残っているので、全てでprometheus_sysctl_exporterが使えないこと。
また、FreeBSDだけではなくてLinuxもあるので全てのホストでprometheus_sysctl_exporterに統一するというのも無理。
できたらNode Exporterとprometheus_sysctl_exporterを併用は避けたいかなと思う心がある。
FreeBSDではNode Exporterで取れない値があるといってもそれが重要な値でもないというのが正直な感想。
さらに、Node Exporterの標準状態で取れない値で必要なのがあればCPU温度みたいにsysctlで取ってNode Exporterに渡せば良いじゃん?
prometheus_sysctl_exporterの出力データが多すぎるんだけど、これを全てPrometheusで受けさせるの?
prometheus_sysctl_exporter側で出力項目を制御できないのかしら?

どうしようかな?
是非使ってみたいという気持ちではないけど、今後に備えて一応触ってみた。ネットに情報が全然無いので手探りだけど。

prometheus_sysctl_exporter はターミナルで /usr/sbin/prometheus_sysctl_exporter を実行すれば、「sysctl_hoge_hoge 値」というのを大量に返してくる。
これをPrometheusが取りに来た時に渡すようにすれば良い。
FreeBSDではこれはinetdで動かすことを想定しているみたい。

/etc/inetd.conf (最終行)
#prom-sysctl stream tcp nowait nobody /usr/sbin/prometheus_sysctl_exporter prometheus_sysctl_exporter -dgh

行頭の#を削ってinetdを起動すれば使えるみたい。
ただ、inetdは昔から嫌いなのよね。最近は改善されているのかも知らないけど。

そこで20年前と変わらずinetdの代替としてtcpserverを使うことにする。(頭が化石でスミマセン)

tcpserverのインストール

# cd /usr/ports/sysutils/ucspi-tcp
# make install

configオプションは初期値で特に問題ない。
tcpserverはサービス起動周りが何か用意されているわけでもないのでこれだけ。

prometheus_sysctl_exporterをネットで使う

prometheus_sysctl_exporterは標準でTCPポート9124を使うみたい。

$ tcpserver -H -R  0 9124 /usr/sbin/prometheus_sysctl_exporter & 

今回はtcpserverのアクセス制御は入れていない。

では、ネット経由でprometheus_sysctl_exporterのメトリクスを表示してみます。

$ curl http://ホストアドレス:9124
curl: (1) Received HTTP/0.9 when not allowed

あれっ?HTTP/0.9だって言ってる?HTTP応答ヘッダが無いの?

$ curl --http0.9 http://ホストアドレス:9124
または
$ echo -e "GET /\r\n" | nc ホストアドレス 9124
sysctl_kern_osrevision 199506
sysctl_kern_maxvnodes 3350688
sysctl_kern_maxproc 13444
sysctl_kern_maxfiles 4030976
sysctl_kern_argmax 262144
sysctl_kern_securelevel -1
sysctl_kern_hostid 1764859756
sysctl_kern_posix1version 200112
sysctl_kern_ngroups 1023
sysctl_kern_job_control 1
sysctl_kern_saved_ids 0
sysctl_kern_boottime_seconds 1568628839.445746
sysctl_kern_osreldate 1200086
sysctl_kern_maxfilesperproc 3627792
sysctl_kern_maxprocperuid 12099
大量に後略

おおっ、表示できた。でも、Exporterのデータで見るHELP hogeっていう説明が一切付いてない。
prometheus_sysctl_exporterのヘルプによるとオプションが3つだけあるのね。

  • -d メトリクスの説明を付けて表示
  • -g HTTP応答ボディのGzip 圧縮あり
  • -h HTTP応答ヘッダーを付ける
なるほど、-hオプション無しだとHTTP応答ヘッダ無しなのね。っていうか、これオプション全指定が標準で良くない?

自動起動スクリプト

直前で見たオプション3つを指定して自動起動させる。
FreeBSDの自動起動は起動スクリプトを書いて/usr/local/etc/rc.dの下に置くだけ。
ただし、起動しっぱなしは行儀が悪いと思ったら同ディレクトリの他のスクリプトと同様にstart, stopで制御できるものにした方が良いかも。(下)

/usr/local/etc/rc.d/prometheus_sysctl_exporter (新規作成)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/sh
# Add the following line to /etc/rc.conf to enable prometheus_sysctl_exporter:
# prometheus_sysctl_exporter="YES"

PATH=/usr/local/bin:/bin:/usr/bin:/usr/sbin

. /etc/rc.subr

name="prometheus_sysctl_exporter"
rcvar="${name}_enable"
start_cmd="${name}_start"
stop_cmd="${name}_stop"

prometheus_sysctl_exporter_start() {
        tcpserver -H -R 0 9124 prometheus_sysctl_exporter -dgh & 
}

prometheus_sysctl_exporter_stop() {
        killall tcpserver
}

run_rc_command "$1"

なお、上のスクリプトではサービス停止がkillallによる全tcpserver停止という手抜きなので他にtcpserverを使っていたら注意。

実行属性を付ける
# chmod +x /usr/local/etc/rc.d/prometheus_sysctl_exporter
自動実行フラグの設定
/etc/rc.conf (1行追加)
prometheus_sysctl_exporter_start="YES"
または(コマンド)
# sysrc prometheus_sysctl_exporter=”YES”
サービスの開始・停止
# service prometheus_sysctl_exporter start      システム再起動後のサービス手動スタート
# service prometheus_sysctl_exporter onestart   システム再起動前のサービス臨時スタート
# service prometheus_sysctl_exporter stop      システム再起動後のサービス手動停止
# service prometheus_sysctl_exporter onestop   システム再起動前のサービス臨時停止

出力確認

GZIP圧縮を有効にしたので確認にはブラウザを使う。http://ホストアドレス:9124を開く。

# HELP sysctl_kern_osrevision Operating system revision
sysctl_kern_osrevision 199506
# HELP sysctl_kern_maxvnodes Target for maximum number of vnodes
sysctl_kern_maxvnodes 3350688
# HELP sysctl_kern_maxproc Maximum number of processes
sysctl_kern_maxproc 13444
# HELP sysctl_kern_maxfiles Maximum number of files
sysctl_kern_maxfiles 4030976
# HELP sysctl_kern_argmax Maximum bytes of argument to execve(2)
sysctl_kern_argmax 262144
# HELP sysctl_kern_securelevel Current secure level
sysctl_kern_securelevel -1
# HELP sysctl_kern_hostid Host ID
sysctl_kern_hostid 1764859756
# HELP sysctl_kern_posix1version Version of POSIX attempting to comply to
sysctl_kern_posix1version 200112
# HELP sysctl_kern_ngroups Maximum number of supplemental groups a user can belong to
sysctl_kern_ngroups 1023
# HELP sysctl_kern_job_control Whether job control is available
sysctl_kern_job_control 1
# HELP sysctl_kern_saved_ids Whether saved set-group/user ID is available
sysctl_kern_saved_ids 0
大量に後略

希望通りの出力になった。
この後は、Prometheusに読み込ませて、Grafanaのダッシュボードを作成するところだけど、今回はここで気力が尽きたのでおしまい。

関連記事:

Prometheus2とGrafana6によるシステム監視 NTP統計情報の表示

Node ExporterではNTP情報も出力できるということになっている。起動オプションで ntp関係の指定をするだけ。
ただ、このNTP情報は参照する時刻ソースを見てくれないみたい。できたらNTPサーバの統計情報でいうところのpeerstatsを取りたい。
また、Node ExporterのNTP情報用のテンプレートが提供されているが、こちらは参照するホストの選択と表示がどうなっているのかわからない。監視対象に複数台のNTPサーバがいてそれぞれNode ExporterでNTP情報を出力した場合に表示が変なのでどう使ってよいのか良くわからない。
ntpdが出力する統計情報を使用すれば、欲しい情報は取れるわけなのでそれをNode Exporterに渡してGrafanaで表示することにした。これ、以前のElastic Stackのよりもはるかに簡単。

なお、ブログの1ページでやるにはいろいろあり過ぎるので「がとらぼ」ではpeerstatsだけを対象とする。

ntpdに統計情報を出力させる

/etc/ntp.conf (変更 or 5行挿入)
1
2
3
4
5
statistics loopstats peerstats clockstats sysstats
statsdir /var/lib/ntp/ntpstats/
filegen peerstats  file peerstats  type day enable
filegen loopstats  file loopstats  type day enable
filegen clockstats file clockstats type day enable

2行目は統計ファイルの出力先

このとき、Linuxのsystemd系のシステムではNTPの起動設定ファイルに注意。privatetempが有効にされていると統計ファイルが何処に出力されるのか判らないということも。/lib/systemd/system/ntp.serviceファイルのprivatetemp行を削除してNTPサービスを停止→無効化→最有効化・開始する。(全てのディストリビューションでこの通りとは限らないかも)

NTPの再起動
#Linuxの場合
% sudo service ntp restart

#FreeBSDの場合
# service ntpd restart

NTP再起動後から指定したディレクトリに統計情報ファイルが出力されるので確認する。

NTP統計情報をNTP plotterで表示する
1日以上経って出力されたpeerstatsファイルをWindowsアプリのNTP plotterで表示してみた。
はっきり言ってこのアプリは動作が遅いのでpeerstatsファイルを選択してからグラフが表示されるまで時間がかかる。まぁこんな感じのグラフが表示されるようにしたいという例。ただし、グラフを見れば判るが、ネットの時刻ソースからPPSまで全て1つのグラフに入れるのはちょっとね。

peerstats統計情報をNode Exporterに渡す

ファイル名は何でも良いと思うが/usr/local/bin/get_peerstats.shというスクリプトを作成した。

/usr/local/bin/get_peerstats.sh (新規作成)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#!/bin/sh

log="/var/lib/ntp/ntpstats/peerstats"
name="node_ntp_peerstats"
outdir="/tmp/node-exporter/"

#NTP Servers
srv1='2001:3a0:0:2001::27'
srv2='2001:3a0:0:2005::57'
srv3='2001:3a0:0:2006::87'

offset1="# HELP node_ntpstats_offset_seconds Time offset in between local system and reference clock."
offset2="# TYPE node_ntpstats_offset_seconds gauge"
delay1="# HELP node_ntpstats_delay_seconds Time delay in between local system and reference clock."
delay2="# TYPE node_ntpstats_delay_seconds gauge"
disps1="# HELP node_ntpstats_dispersion_seconds Time dispersion in between local system and reference clock."
disps2="# TYPE node_ntpstats_dispersion_seconds gauge"
skew1="# HELP node_ntpstats_skew_seconds Time skew in between local system and reference clock."
skew2="# TYPE node_ntpstats_skew_seconds gauge"

pps='127.127.22.0'
ppsdata=`/bin/cat ${log} | /bin/grep ${pps} | /usr/bin/tail -1`
ppsoffset=`echo ${ppsdata} | cut -d " " -f 5`
ppsdelay=`echo ${ppsdata} | cut -d " " -f 6`
ppsdisps=`echo ${ppsdata} | cut -d " " -f 7`
ppsskew=`echo ${ppsdata} | cut -d " " -f 8`
ppsl1="node_ntpstats_offset_seconds{device=\"pps\"} ${ppsoffset}"
ppsl2="node_ntpstats_delay_seconds{device=\"pps\"} ${ppsdelay}"
ppsl3="node_ntpstats_dispersion_seconds{device=\"pps\"} ${ppsdisps}"
ppsl4="node_ntpstats_skew_seconds{device=\"pps\"} ${ppsskew}"

nmea='127.127.20.0'
nmeadata=`/bin/cat ${log} | /bin/grep ${nmea} | /usr/bin/tail -1`
nmeaoffset=`echo ${nmeadata} | cut -d " " -f 5`
nmeadelay=`echo ${nmeadata} | cut -d " " -f 6`
nmeadisps=`echo ${nmeadata} | cut -d " " -f 7`
nmeaskew=`echo ${nmeadata} | cut -d " " -f 8`
nmeal1="node_ntpstats_offset_seconds{device=\"nmea\"} ${nmeaoffset}"
nmeal2="node_ntpstats_delay_seconds{device=\"nmea\"} ${nmeadelay}"
nmeal3="node_ntpstats_dispersion_seconds{device=\"nmea\"} ${nmeadisps}"
nmeal4="node_ntpstats_skew_seconds{device=\"nmea\"} ${nmeaskew}"

srv1data=`/bin/cat ${log} | /bin/grep ${srv1} | /usr/bin/tail -1`
srv1offset=`echo ${srv1data} | cut -d " " -f 5`
srv1delay=`echo ${srv1data} | cut -d " " -f 6`
srv1disps=`echo ${srv1data} | cut -d " " -f 7`
srv1skew=`echo ${srv1data} | cut -d " " -f 8`
srv1l1="node_ntpstats_offset_seconds{device=\"${srv1}\"} ${srv1offset}"
srv1l2="node_ntpstats_delay_seconds{device=\"${srv1}\"} ${srv1delay}"
srv1l3="node_ntpstats_dispersion_seconds{device=\"${srv1}\"} ${srv1disps}"
srv1l4="node_ntpstats_skew_seconds{device=\"${srv1}\"} ${srv1skew}"

srv2data=`/bin/cat ${log} | /bin/grep ${srv2} | /usr/bin/tail -1`
srv2offset=`echo ${srv2data} | cut -d " " -f 5`
srv2delay=`echo ${srv2data} | cut -d " " -f 6`
srv2disps=`echo ${srv2data} | cut -d " " -f 7`
srv2skew=`echo ${srv2data} | cut -d " " -f 8`
srv2l1="node_ntpstats_offset_seconds{device=\"${srv2}\"} ${srv2offset}"
srv2l2="node_ntpstats_delay_seconds{device=\"${srv2}\"} ${srv2delay}"
srv2l3="node_ntpstats_dispersion_seconds{device=\"${srv2}\"} ${srv2disps}"
srv2l4="node_ntpstats_skew_seconds{device=\"${srv2}\"} ${srv2skew}"

srv3data=`/bin/cat ${log} | /bin/grep ${srv3} | /usr/bin/tail -1`
srv3offset=`echo ${srv3data} | cut -d " " -f 5`
srv3delay=`echo ${srv3data} | cut -d " " -f 6`
srv3disps=`echo ${srv3data} | cut -d " " -f 7`
srv3skew=`echo ${srv3data} | cut -d " " -f 8`
srv3l1="node_ntpstats_offset_seconds{device=\"${srv3}\"} ${srv3offset}"
srv3l2="node_ntpstats_delay_seconds{device=\"${srv3}\"} ${srv3delay}"
srv3l3="node_ntpstats_dispersion_seconds{device=\"${srv3}\"} ${srv3disps}"
srv3l4="node_ntpstats_skew_seconds{device=\"${srv3}\"} ${srv3skew}"

echo "${offset1}\n${offset2}\n${ppsl1}\n${nmeal1}\n${srv1l1}\n${srv2l1}\n${srv3l1}\n${delay1}\n${delay2}\n${ppsl2}\n${nmeal2}\n${srv1l2}\n${srv2l2}\n${srv3l2}\n${disps1}\n${disps2}\n${ppsl3}\n${nmeal3}\n${srv1l3}\n${srv2l3}\n${srv3l3}\n${skew1}\n${skew2}\n${ppsl4}\n${nmeal4}\n${srv1l4}\n${srv2l4}\n${srv3l4}" > ${outdir}${name}.prom.$$

/bin/mv ${outdir}${name}.prom.$$ ${outdir}${name}.prom
/bin/chmod 666 ${outdir}${name}.prom

ボーンシェルのスクリプトにしたのは、BSD/Linuxほぼ全ての環境でも動くから。Linuxだと/bin/shの実体はdashが多いようだけど、問題なく動く筈。
変数を${変数名}形式にしてるのは編集のときにわかりやすいから。
やってることは単純でpeerstatsファイルから各時刻ソースの最新行1行を取得して、空白文字で分割して目的の数値を得るというもの。最新レコードの時刻突合はボーンシェルだと難しくなるのでパスというインチキだけど、ntpdが動いていて正しく時刻ソースから情報が得られている限りは特に問題ない筈。

PPSが無いNTPサーバの場合、PPS関係の記述を全て消してください。特に最後近くのecho行の${pps*}\nを全て。
外部の時刻参照サーバが2つの場合はSRV3関係を全て消してください。特に最後近くのecho行の${srv3*}\nを全て。
でないと、Node Exporter的には不適切なデータが出力されてしまう。
xBSDでは\nによる改行がおそらく利用できないので\nの代わりに改行してください。ダブルクォーテーションの中で改行したらそれが反映されます。また、xBSDではgrepが/bin/grepではなく/usr/bin/grepだと思われるので上のようにフルパス指定の場合は要修正。
Node Exporterが読み込む外部ファイルのディレクトリはoutdir変数で指定しています。
前回と同じなら /tmp/node-exporter です。
FreeBSDのports/pkgでNode Exporterをインストールしている場合は外部参照ディレクトリが /usr/local/etc/rc.d/node_exporter内で /var/tmp/node_exporter に指定されているのでスクリプト4行目のoutdir変数の値を/var/tmp/node_exporterにしてください。または/etc/rc.confで node_exporter_textfile_dir="好みのdir"行を追加してそこで指定したディレクトリにします。このようになっているので/etc/rc.confのnode_exporter_args行で --collector.textfile.directory=hoge は指定するとエラーになります。Node Exporterが即死するので絶対NGです。

実行属性を付ける。
$ sudo chmod +x /usr/local/bin/get_peerstats.sh
/etc/crontab (1行追加)
*  *  *  *  *  root    /usr/local/bin/get_peerstats.sh >/dev/null 2>&1

cronで1分ごとに実行するようにする。

出力内容の確認

Node Exporterを再起動する必要があるかは不明。「がとらぼ」の中の人は躊躇なく再起動したので外部ファイル追加時の挙動を確認していない。

http://node_exporterホスト:9100/metrics を確認する。
出力されるデータの何処かに以下のような内容が含まれていたらOK

# HELP node_ntpstats_delay_seconds Time delay in between local system and reference clock.
# TYPE node_ntpstats_delay_seconds gauge
node_ntpstats_delay_seconds{device="2001:3a0:0:2001::27"} 0.011966835
node_ntpstats_delay_seconds{device="2001:3a0:0:2005::57"} 0.012230173
node_ntpstats_delay_seconds{device="2001:3a0:0:2006::87"} 0.011432178
node_ntpstats_delay_seconds{device="nmea"} 0
node_ntpstats_delay_seconds{device="pps"} 0
# HELP node_ntpstats_dispersion_seconds Time dispersion in between local system and reference clock.
# TYPE node_ntpstats_dispersion_seconds gauge
node_ntpstats_dispersion_seconds{device="2001:3a0:0:2001::27"} 0.002332928
node_ntpstats_dispersion_seconds{device="2001:3a0:0:2005::57"} 0.00157883
node_ntpstats_dispersion_seconds{device="2001:3a0:0:2006::87"} 0.00320245
node_ntpstats_dispersion_seconds{device="nmea"} 0.000237624
node_ntpstats_dispersion_seconds{device="pps"} 0.000235834
# HELP node_ntpstats_offset_seconds Time offset in between local system and reference clock.
# TYPE node_ntpstats_offset_seconds gauge
node_ntpstats_offset_seconds{device="2001:3a0:0:2001::27"} 0.000939802
node_ntpstats_offset_seconds{device="2001:3a0:0:2005::57"} 0.001022241
node_ntpstats_offset_seconds{device="2001:3a0:0:2006::87"} 0.000583119
node_ntpstats_offset_seconds{device="nmea"} -0.00125271
node_ntpstats_offset_seconds{device="pps"} 1.1725e-05
# HELP node_ntpstats_skew_seconds Time skew in between local system and reference clock.
# TYPE node_ntpstats_skew_seconds gauge
node_ntpstats_skew_seconds{device="2001:3a0:0:2001::27"} 0.000138265
node_ntpstats_skew_seconds{device="2001:3a0:0:2005::57"} 0.000146675
node_ntpstats_skew_seconds{device="2001:3a0:0:2006::87"} 0.000125755
node_ntpstats_skew_seconds{device="nmea"} 0.000134344
node_ntpstats_skew_seconds{device="pps"} 1.3283e-05

Grafanaでグラフ表示

Grafanaの側は、何か適当にダッシュボードを造るか、既存のダッシュボードを使うかして、そこにグラフを追加してクエリーを書いて表示周りをチョイチョイですぐ表示できるのでとても簡単。
で、Node ExporterのNTPコレクタ機能で得た情報をGrafanaに表示するダッシュボードがhttps://grafana.com/grafana/dashboards/7496で入手できるが、使ってみた限りでは外部の時刻ソースとのズレを表示するようなことができない?POOLだけ?表示される情報の意味もちょっとよくわからない。そもそもNode Exporterが取得するNTP情報というのが何の情報なんだかわからないという・・・

今回は、新しいダッシュボードではなく、以前に紹介したNode Exporter用のダッシュボードNode Exporter Fullにパネル(グラフ)を追加する形にする。ダッシュボードを切り替えなくて済むというのが「がとらぼ」の中の人の好みなので。

NTP統計情報をGrafanaで表示する 1
Grafana画面1:
Grafanaのダッシュボードを作成するか既存のダッシュボードを選択するなど、NTP統計情報を表示するパネル(グラフ)を追加するダッシュボードを表示した状態にする。
追加ボタンを押す。

NTP統計情報をGrafanaで表示する 2
Grafana画面2:
ダッシュボードの左上に新しいパネルが追加される。
そのパネルに表示されている「Add Query」をクリックする。

NTP統計情報をGrafanaで表示する 3
Grafana画面3:
クエリー設定画面が開くのでMetrics欄にクエリーを書く。
クエリーを書くと基本的にはリアルタイムに上のグラフ欄にクエリーに対応したグラフが表示される。ただし、実際にはフォーカスを変更するなどしないと更新されないかも。また、インスタンスを指定した場合はそのデータが存在するホストを選択しておかないとグラフ欄には何も表示されない。インスタンスを指定しなければホストで絞られないのでグラフが表示されるかもしれないが、そのグラフは複数のホストのデータが混ざっているかもしれない。
Legendの欄は未指定だとクエリーに近いものが表示される。グラフの線が何を表示しているのか等を表示するものなので例えばデバイス名などを表示すると良い筈。(次)

NTP統計情報をGrafanaで表示する 4
Grafana画面4:
1つの例としてNMEAのOffsetを表示するクエリー。
node_ntpstats_offset_seconds{job=~"$job", device="nmea"} これでホストで絞らない状態。 node_ntpstats_offset_seconds{instance=~"$node:$port", job=~"$job", device="nmea"} これで、ホストで絞られる状態。(上の画像の状態)
Legendは今回であれば、「 {{device}} 」のように指定する。 これで対応するデバイス名が代入される。

NTP統計情報をGrafanaで表示する 5
Grafana画面5:
左から「グラフ」(Visualization)のアイコンを選ぶ。
Axesの中のLeft Yにある単位の種類(Unit)を選択する。今回のpeerstatsは数値の単位が「秒」なので、プルダウンメニューから「Time」サブ項目を選び、さらに下の「Seconds(s)」を選択する。

NTP統計情報をGrafanaで表示する 6
Grafana画面6:
左から「歯車+スパナ」(General)のアイコンを選ぶ。
「Title」欄にグラフの名前を入力する。(任意)
そこまでで、確定するなら最上部のFDアイコンをクリックして保存する。クリックすると、入力窓が開くが、メモの入力欄なので特に入力しなくても良くて「Save」ボタンを押す。
なお、この保存はパネル単体ではなくダッシュボード全体の保存なので違うダッシュボードを表示しようとするまでに保存すれば良い。
また、パネルの位置を変えるなど何らかの変更を行ったらダッシュボードを出る際に保存するか確認される。迂闊な操作は保存しない方が良い場合も多い。

NTP統計情報をGrafanaで表示する 7
Grafana画面7:
1つのパネルに複数のグラフ(折れ線やバー等)を表示する場合、複数のクエリーを追加するという方法があり、その場合は「Add Query」ボタンを押して、別のクエリーを登録する。
または、1つのクエリーで正規表現を使って必要なグラフを選択表示することもできる。
この画面の例では、「デバイス」で正規表現を使って「2001」から始まるIPv6アドレス全てを意味する「2001.*」または「pps」デバイスを表示させる「(A | B)」という形式で「(2001.*|pps)」を指定。

NTP統計情報をGrafanaで表示する 8
Grafana画面8:
好きなだけパネルを追加してPeerstats関係のグラフを作った。この画像はブラウザの窓幅を800pxに狭めているので貧相なグラフになっているが、幅を広げるともう少し見ごたえのあるグラフになる。

関連記事: