はじめに
InfluxDBのpythonクライアント(InfluxDB-Python)でナノ秒単位のデータを登録する際に、タイムスタンプが崩れるため工夫が必要だったという話です。
環境
- OS: Windows 10
- InfluxDB: v1.7.8
- Python: v3.7.4
- InfluxDB-Python: v5.2.3
再現コード
InfluxDB-PythonのREADMEを参考にして、ナノ秒単位のデータ登録を行ってみます。
from influxdb import InfluxDBClient
if __name__ == '__main__':
client = InfluxDBClient('localhost', 8086)
ts = '2019-01-01T00:00:00.123456789Z'
body = [{
'measurement': 'cpu',
'time': ts,
'fields': {
'sys': 12.3,
'usr': 45.6,
}
}]
client.write_points(body, database='my_db', time_precision='n')
サーバ設定はデフォルトのままです。期待ではそのままのタイムスタンプで登録されていて欲しかったのですが、サーバには丸められたタイムスタンプで登録されていました。
> select * from cpu
name: cpu
time sys usr
---- --- ---
1546300800123456000 12.3 45.6
他にも例えば「2019-01-01T00:00:00.123Z」のようにミリ秒単位のタイムスタンプを指定すると、「1546300800122999808」とズレたタイムスタンプで入ってしまうのが困りました。
対応コード
どうもクライアント側で丸められているようでした。タイムスタンプをUnix時刻(ナノ秒)で指定すると問題なさそう。
from influxdb import InfluxDBClient
if __name__ == '__main__':
client = InfluxDBClient('localhost', 8086)
ut = 1546300800123456789
body = [{
'measurement': 'cpu',
'time': ut,
'fields': {
'sys': 12.3,
'usr': 45.6,
}
}]
client.write_points(body, database='my_db', time_precision='n')
これだとうまく入ります。
> select * from cpu
name: cpu
time sys usr
---- --- ---
1546300800123456789 12.3 45.6
InfluxDB-Pythonのナノ秒単位のタイムスタンプの文字列の扱いにはどうも制約があるようです。ナノ秒単位のデータを扱い得るときには、基本的に整数型で指定する方がよいように思います。
ちなみにタイムスタンプの文字列(RFC3339)をナノ秒単位のUnix時刻に変換するには、標準ライブラリでさくっと、というわけにはいかなさそうです。いちばん手軽にできるのはnumpyのdatetime64ですかね。
from influxdb import InfluxDBClient
import numpy
if __name__ == '__main__':
client = InfluxDBClient('localhost', 8086)
ts = '2019-01-01T00:00:00.123456789Z'
dt = numpy.datetime64(ts, 'ns')
ut = dt.astype('uint64')
body = [{
'measurement': 'cpu',
'time': ut,
'fields': {
'sys': 12.3,
'usr': 45.6,
}
}]
client.write_points(body, database='my_db', time_precision='n')
おわりに
InfluxDB-Pythonでナノ秒単位のデータを登録する際に、タイムスタンプの文字列の扱いに制約があるため工夫が必要だったという話でした。