インターネットのスピードテストを定期実行して結果をCSVにまとめる

# やりたいこと
インターネットのスピードテストをLinux上で自動的に実行し、結果を記録したい。
まとまった結果を人が処理しやすい形式(.csv)で取り出したい。
とにかくサクッとやりたい。

# 概要
スピードテストはCLI（コマンドライン）で実行出来る [SPEEDTEST CLI](https://www.speedtest.net/apps/cli) を使用し、crontabで定期実行します。測定結果はjson形式で出力したものをテキストファイルに保存し、結果を蓄積していきます。最後に jq コマンドで必要な部分だけを抜き出して .csv 形式のファイルとして保存します。

# 使用環境
Rocky Linux 8.6
speedtest 1.1.1.28

# CLI版 speedtestのインストール
サクッと動かすために、バイナリをダウンロードします。[speedtest.net](https://www.speedtest.net/apps/cli)のDownload Speedtest CLIのところにあるLinuxのx86_64版をダウンロードし、ファイルを展開します。
~~~
$ wget --no-check-certificate https://install.speedtest.net/app/cli/ookla-speedtest-1.1.1-linux-x86_64.tgz
$ tar xfzp ookla-speedtest-1.1.1-linux-x86_64.tgz
~~~
（※証明書で検証エラーが出たので --no-check-certificate を付けています）

# スピードテスト
オプションを付けずに実行すれば測定が開始されます。
~~~
$ ./speedtest

   Speedtest by Ookla

     Server: i3D.net - Tokyo (id = 21569)
        ISP: J:COM
    Latency:    14.55 ms   (1.57 ms jitter)
   Download:   243.92 Mbps (data used: 312.2 MB )                               
     Upload:     9.77 Mbps (data used: 5.0 MB )                               
Packet Loss:     0.0%
 Result URL: https://www.speedtest.net/result/c/hogehoge-hugahuga
~~~

# サーバーを固定する
接続先のサーバーは自動的に選択されますが、サーバーによっても結果が変わってくると思います。定期実行する場合は同じ環境で続けた方がよいため、サーバーを固定することにします。使用可能なサーバーは -L オプションで確認することができます。

~~~
./speedtest -L
Closest servers:

    ID  Name                           Location             Country
==============================================================================
 14623  IPA CyberLab                   Bunkyo               Japan
 21569  i3D.net                        Tokyo                Japan
 20976  GLBB Japan                     Tokyo                Japan
 28910  fdcservers.net                 Tokyo                Japan
 24333  Rakuten Mobile, Inc            Tokyo                Japan
 50686  GSL Networks                   Tokyo                Japan
 50467  Verizon                        Tokyo                Japan
 50959  Osaka Electro-Communication University | Communication Research Club Tokyo                Japan
 48463  IPA CyberLab 400G              Tokyo                Japan
 44988  Misaka Network, Inc.           Tokyo                Japan
~~~

今回は一番上に出てきたIPA CyberLabを使用することにします。サーバーを固定するには -s でIDを指定します。

# JSONで取得する
speedtestの実行結果は人が見やすい形で表示されますが、後でデータの処理を行うために、結果はJSONで保存するようにします。JSONで出力するには -f json オプションを指定します。

~~~
$ ./speedtest -s 14623 -f json | jq -r
{
  "type": "result",
  "timestamp": "2022-08-08T15:42:52Z",
  "ping": {
    "jitter": 5.0300000000000002,
    "latency": 13.124000000000001
  },
  "download": {
    "bandwidth": 28668596,
    "bytes": 295922142,
    "elapsed": 10505
  },
  "upload": {
    "bandwidth": 1234097,
    "bytes": 6780240,
    "elapsed": 5510
  },
  "packetLoss": 0,
  "isp": "J:COM",
  "interface": {
    "internalIp": "192.168.xx.xx",
    "name": "ens4",
    "macAddr": "xx:xx:xx:xx:xx:xx",
    "isVpn": false,
    "externalIp": "xx.xx.xx.xx"
  },
  "server": {
    "id": 14623,
    "host": "speed.coe.ad.jp",
    "port": 8080,
    "name": "IPA CyberLab",
    "location": "Bunkyo",
    "country": "Japan",
    "ip": "103.95.184.74"
  },
  "result": {
    "id": "hogehoge-hugahuga",
    "url": "https://www.speedtest.net/result/c/hogehoge-hugahuga",
    "persisted": true
  }
}
~~~

この結果を見ると、Download/Upload speedだけだなく、様々な情報が取得できるようです。今回欲しいのはPing値とDownload/Upload速度だけですが、後で活用できるように全て保存することにします。

# crontabで定期実行する
~~~shellscript:speedtest.sh
./speedtest -s 14623 -f json >> result.jsonl
~~~
result.jsonlファイルに1行1回分のデータを蓄積していきます。

# 結果をCSV形式で取り出す
json形式のデータから任意の値を取り出すにはjqコマンドを使うと便利です。今回は日時、Ping値、Download速度、Upload速度を取り出します。

~~~
$ jq -r '[(.timestamp|fromdate|strftime("%F %X")), (.ping.latency*10|floor)/10, (.download.bandwidth*8/1024/1024*10|floor)/10, (.upload.bandwidth*8/1024/1024*10|floor)/10] | @csv' < result.jsonl
"2022-08-08 15:42:52",13.1,218.7,9.4
~~~

ちょっと見にくいですね。やってることは以下の処理です。
[date, ping, download, upload] | @csv 

日時はtimestampの値を、YYYY-MM-DD hh:mm:ssの形式に変換しています（なぜかmmのところが絵文字になってますが…）。Ping値はping＞latencyの値の小数点第一位まで取り出します。printfみたいなフォーマットの指定がよくわからなかったので10倍して10で割ってます。

Download速度はdownload＞bandwidthの値ですが、単位がbyteのようなので(?)、Mbpsにしました。Upload速度も同様です。

こうやって任意のデータを取り出して、計算して出力してくれるjqコマンドは便利ですね。はじめは集計用のプログラムを作らないとと思ってましたが、jqコマンドで事足りてしまいました。