2026/06/03(水)OpenWrtのメトリクスとログをGrafanaで雑に見れるようにした

投稿日:

OpenWrtのメトリクスやログをUbuntu側のGrafanaで見れるようにするまで。

メトリクスの取得にはPrometheus、ログはLokiを使っている。

確認環境

監視する側

Env Ver
Ubuntu 24.04.3 LTS
Prometheus 3.5.0
Grafana v12.1.1
Loki 3.5.9

監視される側

Env Ver
OpenWrt 24.10.0
Prometheus 3.5.0
prometheus-node-exporter-lua 2025.07.15-r1
prometheus-node-exporter-lua-nat_traffic 2025.07.15-r1
prometheus-node-exporter-lua-netstat 2025.07.15-r1
prometheus-node-exporter-lua-openwrt 2025.07.15-r1
prometheus-node-exporter-lua-thermal 2025.07.15-r1
perl 5.40.0-r2
perlbase-json-pp 5.40.0-r2
perlbase-http-tiny 5.40.0-r2
perl-time-moment 0.44.5.40-r1

Prometheusでメトリクスを取得してGrafanaで見れるようにする

ほぼOpenWRT | Grafana Labsに書いてある通り。

  1. 必要なパッケージをインストールする
    opkg update
    opkg install \
       prometheus-node-exporter-lua \
       prometheus-node-exporter-lua-nat_traffic \
       prometheus-node-exporter-lua-netstat \
       prometheus-node-exporter-lua-openwrt \
       prometheus-node-exporter-lua-thermal
    
  2. /etc/config/prometheus-node-exporter-luaを以下のように編集する
    config prometheus-node-exporter-lua 'main'
    +         option listen_interface 'lan'
    -         option listen_interface 'loopback'
            option listen_port '9100'
            #option cert '/etc/uhttpd.crt'
            #option key '/etc/uhttpd.key'
    
  3. prometheus-collectors/filesystem.luaprometheus-collectors/meminfo.luaを拾ってきて/usr/lib/lua/prometheus-collectorsに配置する
  4. サービスを再起動
    /etc/init.d/prometheus-node-exporter-lua restart
    
  5. /etc/prometheus/prometheus.yaml
    - job_name: "OpenWRT"
      static_configs:
        - targets: ['xxxx:xxxx:xxxx:xxxx::1:9100']
    
  6. Prometheus再起動
    sudo systemctl restart prometheus.service
    
  7. 取れるメトリクスの一覧
    curl 'http://[xxxx:xxxx:xxxx:xxxx::1]:9100/metrics'
    
  8. Grafanaのダッシュボードを作成しID: 18153を取り込む
  9. WiFi関係使ってないので全消し
  10. Used SWAPのQueriesを以下のように書き換えて0除算でエラーが出ないようにする
    (
      (
        (node_memory_SwapTotal_bytes{instance=~"$node:$port",job=~"$job"} - node_memory_SwapFree_bytes{instance=~"$node:$port",job=~"$job"})
        /
        (node_memory_SwapTotal_bytes{instance=~"$node:$port",job=~"$job"} > 0)
      ) * 100
    )
    or
    (node_memory_SwapTotal_bytes{instance=~"$node:$port",job=~"$job"} * 0)
    

細かい部分の整理はまた追々として、いい感じに見れるようになった気がする。

ログをLokiに送る

Loki exporter for OpenWRTが動かないので自作した。

  1. OpenWrtのログをLokiに送るやつを拾ってくる
  2. インストール方法にある通りにファイルを配置、設定ファイルをいじる
  3. Lokiにログが飛んでればOK
    • ログが飛んでいない場合は/tmp/openwrt-loki.errの中身を見てエラーがないか見る

一旦こんな感じで見れるようになった。

既知の問題

複数行のエラーログがLoki上で別のログになる

親子関係を作ってないせい。Claude Opus 4.8には難しいようだったので、そのうち作る。

おまけ:Lokiにログを投げる方法

POST /loki/api/v1/pushを叩けばよい。ペイロードは以下の書式。

LokiのAPIペイロード

{
  "streams": [
    {
      "stream": {
        "label": "value"
      },
      "values": [
          [ "<unix epoch in nanoseconds>", "<log line>", { "hoge": "aaaa", "fuga": "1234" } ],
          [ "<unix epoch in nanoseconds>", "<log line>", { "hoge": "bbbb", "fuga": "2345" } ]
      ]
    }
  ]
}

ペイロードの意味合い

nginxのログはペイロードしか入ってなかったりするがどうやって実現してるのか不明。もしかするとvalues[1]にJSONを突っ込んでるのかもしれない。

項目 意味合い
streams よくわかってない
stream この配下に検索用のラベルをぶら下げる。jobとかlevelhostとかを入れとくとよいと思われる
values ログの本体を入れる
values[0] ナノ秒まで入ったEPOCH
values[1] ログ本文の文字列
values[2] オプションペイロード。KEY=VALUE

おまけ:Loki exporter for OpenWRTのエラーログ

あのシェルスクリプトを読む気が起きなかったので、なぜこうなっているかはわからない。

BOOT=0 /bin/ash /usr/bin/loki_exporter
openwrt-loki-exporter/v1.0.6-0-gd20fb55-20260322-23413663016 started with BOOT=0
/usr/bin/loki_exporter: line 257: malformed ?: operator

あとがき

去年の8月にはやろうとしていたものの、そのままズルズルと長らく放置していたOpenWrtの監視周りだが、このままではいけないということで、一旦は雑に整備した。

大変雑なのでログ周りは機能するかも怪しいし、私以外が使えるようにも作ってない。最低限動くとかそんなレベル。LLMが書いたコードもろくにレビューしていないので、動いている原理さえ不明だ。

幸い全部で300行そこらなのでおいおい読んで理解していきたいとは思う。

基本原理はlogread -fした結果をいい感じに取り込んでLokiにたたきつけているだけのはずだが、この「いい感じ」が難しく、重くなっていると考えている。例えばログの取得漏れや、重複取得などを考慮しないといけないので、なんかそこら辺をいい感じにやってもらうようにLLMに指示したら一気に重くなった。ベースのコードは私が書いていたのだが、全くの別物になってしまった。

しかし去年の8月にしかかって放置している部分はできていないので、またそこは追々やっていきたいところだ。具体的には今回の対応はサーバー側でメトリクスを見る対応なのでネットワークが死ぬと終わってしまう。そこでルーター側でも簡易に見れるのを作ろうという計画がある。

しかしルーター側はスペックがしょぼいので大したことはできないし、ストレージがeMMCなので頻繁な書き込みもできないから、普段はメモリストレージ(/tmp)に置いておき、定期的に永続化のためにeMMCに吐き出すというのをやろうとしている。

そしてeMMCに端に吐き出すのもパフォーマンスと寿命の影響があるのでファイルシステムレベルでの対策をしてやろうみたいなことを考えていたが、尻切れとんぼのままなので、何とかしていきたいところだ。