Last active
December 9, 2023 06:13
-
-
Save dolpen/6577ad52d5e35a7a2811 to your computer and use it in GitHub Desktop.
文字コードはSJIS、改行コードはCRLFでの動作を確認しました
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
# ルーターメトリック収集スクリプト | |
## 概要 | |
定期的にルーターのリソースを監視して、プロキシ経由で Mackerel に下記メトリック情報を送信します | |
* CPU 使用率(整数) | |
* メモリ使用率(整数) | |
* 筐体内温度(整数) | |
* 各LANインターフェースの利用帯域(目安) | |
## 前提 | |
RT(X)系のLuaスクリプト内で利用可能な rt.httprequest 命令には以下の注意点があります | |
* https をサポートしていない | |
* リクエストヘッダのカスタマイズや追加が不可能 | |
このため、このスクリプトの動作には下記の目的で http プロキシを用意する必要があります | |
* http -> https のプロキシ | |
* リクエストヘッダへ Mackerel API キー (X-Api-Key) を追加する | |
http プロキシ側にキー情報を持ち、無条件でAPIリクエストが可能なため、プロキシはローカルネットワーク内に立てることを強くお勧めします | |
## 導入手順 | |
* このファイルの設定値を適切に変更し RTFS か外部メモリに保存してください | |
* lua (Luaスクリプトファイル名) でスクリプトを実行してください | |
* このスクリプトは無限ループします、 | |
* show status lua でスクリプトの実行IDを確認してください | |
* 停止するときは terminate lua (実行ID) コマンドを実行してください | |
* schedule at 1 startup * lua (Luaスクリプトファイル名) で、ルーター起動時の自動実行をスケジューリングできます | |
## ノート | |
* カスタムメトリックのキー名変更はハードウェアリソース情報テーブル周辺を見ていい感じにおねがいします | |
* 対象のルーターによっては本体温度など取得できない情報がありますが | |
その際はハードウェアリソース情報テーブルでコメントアウトしてください | |
* YamahaのLuaサンプルページからいろいろ持ってくればネットワーク帯域なども収集可能ですが | |
いろいろややこしくなるので各自いい感じにおねがいします | |
]] | |
-------------------------- ## 設定値 ##-------------------------------- | |
-- 監視間隔(1 - 864000 秒) | |
-- 5分以上の間隔にすると Mackerel の Connectivity アラートが上がるので監視から外すか5分未満にする | |
idle_time = 180 | |
-- os.time と unix time のオフセット(秒) | |
os_time_offset = 315532800; | |
-- Mackerel API に向けた http プロキシのエンドポイントURL | |
proxy_tsdb = "http://********************/api/v0/tsdb" | |
-- Mackerel で実行端末用に作成した hostId | |
-- @see http://help-ja.mackerel.io/entry/spec/api/v0#host-create | |
host = "********************" | |
-- カスタムメトリックのプレフィックス | |
name_prefix = "custom.rtx." | |
-- ハードウェアリソース定義とメトリック名 | |
res_table = { | |
cpu_5sec = { pattern = "(%d+)%%%(5sec%)", name = name_prefix .. "cpu.5sec" }, | |
cpu_1min = { pattern = "(%d+)%%%(1min%)", name = name_prefix .. "cpu.1min" }, | |
cpu_5min = { pattern = "(%d+)%%%(5min%)", name = name_prefix .. "cpu.5min" }, | |
memory = { pattern = "(%d+)%% used", name = name_prefix .. "memory.usage" }, | |
packet_small = { pattern = "(%d+)%%%(small%)", name = name_prefix .. "packetbuff.small" }, | |
packet_middle = { pattern = "(%d+)%%%(middle%)", name = name_prefix .. "packetbuff.middle" }, | |
packet_large = { pattern = "(%d+)%%%(large%)", name = name_prefix .. "packetbuff.large" }, | |
packet_huge = { pattern = "(%d+)%%%(huge%)", name = name_prefix .. "packetbuff.huge" }, | |
temp = { pattern = "筐体内温度%(℃%): (%d+)", name = name_prefix .. "temperature.body" } | |
} | |
-- LAN3まであるなら3 | |
max_lan_interface = 3 | |
-- LANインターフェースのメトリックのプレフィックス | |
lan_metric_name_prefix = { | |
send = name_prefix .. "send.lan", | |
recv = name_prefix .. "recv.lan" | |
} | |
---------------------- ## 設定値ここまで ##---------------------------- | |
------------------------------------------------------------ | |
-- ルーターのハードウェアリソースの使用状況を取得する関数 -- | |
-- サンプルからありがたく拝借して改変 | |
-- @return [metricValue] | |
------------------------------------------------------------ | |
function rt_res_status() | |
local rtn, str | |
local cmd = "show environment" | |
local rtn_table = {} | |
rtn, str = rt.command(cmd) | |
if (rtn) and (str) then | |
for k, v in pairs(res_table) do | |
local value = str:match(v.pattern) | |
if (value) then | |
table.insert(rtn_table, make_metric_value(v.name, value)) | |
end | |
end | |
end | |
return rtn, rtn_table | |
end | |
------------------------------------------------------------ | |
-- LANインターフェースから送受信オクテット数を取得する関数 -- | |
-- サンプルからありがたく拝借、改造 | |
------------------------------------------------------------ | |
function lan_load_info(interface_num) | |
local rtn, str, send, recv | |
local cmd = "show status lan" .. tostring(interface_num) | |
local t = {} | |
local ptn = "%((%d+)%s+オクテット" | |
rtn, str = rt.command(cmd) | |
if (rtn) and (str) then | |
local n = 1 | |
for w in string.gmatch(str, ptn) do | |
t[n] = w | |
n = n + 1 | |
end | |
end | |
if (t[1]) then | |
send = tonumber(t[1]) | |
end | |
if (t[2]) then | |
recv = tonumber(t[2]) | |
end | |
return rtn, send, recv | |
end | |
------------------------------------------------------------ | |
-- <metricValue> の name と value のみを持った テーブルを作る -- | |
-- { name , value } | |
------------------------------------------------------------ | |
function make_metric_value(name, value) | |
local mv = {} | |
mv.name = name; | |
mv.value = tostring(value); | |
return mv; | |
end | |
------------------------------------------------------------ | |
-- Mackerel 向けの MetricValue API Post 文字列生成 -- | |
-- @see http://help-ja.mackerel.io/entry/spec/api/v0#metric-value-post | |
------------------------------------------------------------ | |
function make_post_text(host, time, metric_table) | |
local a = ""; | |
for k, v in pairs(metric_table) do | |
a = a .. string.format("{\"hostId\":\"%s\",\"name\":\"%s\",\"value\":%d,\"time\":%d}", host, v.name, v.value, time) .. "," | |
end | |
return "[" .. string.sub(a, 1, -2) .. "]" | |
end | |
------------------------------------------------------------ | |
-- メインルーチン -- | |
------------------------------------------------------------ | |
-- HTTPリクエスト用テーブル | |
local http_req_table = { | |
url = proxy_tsdb, | |
method = "POST", | |
content_type = "application/json" | |
} | |
local lan_state_table = { | |
{ send = 0, recv = 0 }, | |
{ send = 0, recv = 0 }, | |
{ send = 0, recv = 0 } | |
} | |
local rtn, str, now, rtn_table, send, recv | |
while (true) do | |
local metric_table = {} | |
-- 1.ハードウェアリソースの取得、成功すればメトリックテーブルに追加 | |
rtn, rtn_table = rt_res_status(rt_res_tbl) | |
if (rtn) then | |
for i, v in ipairs(rtn_table) do | |
table.insert(metric_table, v) | |
end | |
end | |
-- 2.LAN インターフェースの取得、取得できたものだけ | |
for k = 1, max_lan_interface do | |
rtn, send, recv = lan_load_info(k) | |
if (rtn) and (send) and (recv) then | |
if (lan_state_table[k].send <= 0) then | |
lan_state_table[k].send = send; | |
end | |
if (lan_state_table[k].recv <= 0) then | |
lan_state_table[k].recv = recv; | |
end | |
table.insert(metric_table, | |
make_metric_value(lan_metric_name_prefix.send .. tostring(k), | |
(send - lan_state_table[k].send) * 8 / idle_time)) | |
table.insert(metric_table, | |
make_metric_value(lan_metric_name_prefix.recv .. tostring(k), | |
(recv - lan_state_table[k].recv) * 8 / idle_time)) | |
lan_state_table[k].send = send; | |
lan_state_table[k].recv = recv; | |
end | |
end | |
-- 3.現在時刻をエポック秒にする | |
now = os.time() + os_time_offset | |
-- リクエストを発行 | |
http_req_table.post_text = make_post_text( | |
host, | |
now, | |
metric_table | |
) | |
rt.httprequest(http_req_table) | |
-- http_res_table = rt.httprequest(http_req_table) | |
-- print(http_req_table.post_text) | |
-- print(http_res_table.body) | |
rt.sleep(idle_time) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment