見出し画像

TWSNMP FCの改善:syslogから情報を取り出す画期的なアイデアを試しています

今朝は4時に、助手の猫さんが起こしにきました。かみさんと一緒に2階に来て寝ていなかったようで朝から大騒ぎしていました。

PlemolJP+Starshipの環境は快適です。なんとなくプログラムを作るスピードが増したような気がします。

調子が出たところで、今朝は前々から考えていたログ分析のアイデアを作ってみることにしました。
アイデアの元はESP32の開発で使ったArudino IDEについているシリアルプロッター機能です。ESP32のシリアルポートから出力された文字列から数値を自動で読み取ってグラフに描く機能です。右上のボタンで簡単に表示できます。

こんな感じの画面です。
TWSNMP FCには、syslogから数値情報を読み取ってグラフに描く抽出機能がありますが、抽出する方法はGROKを使って設定しなければならないのでちょっと難しいです。そこで、もっとシンプルにしたいというのが今回のテーマです。
シリアルプロッターは、単に数値ぽい文字列か、CSVぽい文字列から数値を取り出しています。これは、正規表現を使えば簡単にできます。
数値なら

(-?[.0-9]+)

にマッチするものを全部取り出せばよいはずです。
数値だけでなく、少し欲がでてきて、IPアドレスやメールアドレスも取り出せたらよいなと思いました。さらにSplunk風の

key=value

のようなデータも自動で取り出すようにしたくなりました。データを取り出すプログラムを

// Extract by regexp
var reSplunk = regexp.MustCompile(`([-a-zA-Z0-1_]+)=([^, ;]+)`)
var reNumber = regexp.MustCompile(`(-?[.0-9]+)`)
var reIPv4 = regexp.MustCompile(`\d{1,3}\.\d{1,3}.\d{1,3}.\d{1,3}`)
var reMAC = regexp.MustCompile(`[0-9a-fA-F]:[0-9a-fA-F]:[0-9a-fA-F]:[0-9a-fA-F]:[0-9a-fA-F]:[0-9a-fA-F]`)
var reEMail = regexp.MustCompile(`[A-Za-z]+[A-Za-z0-1]+@[A-Za-z.]+`)

const (
	none = iota
	splunk
	number
	other
)

func getExtractType(t string) int {
	switch t {
	case "re_splunk":
		return splunk
	case "re_number":
		return number
	case "re_other":
		return other
	}
	return none
}

func regExtract(t int, msg string) (map[string]string, error) {
	r := make(map[string]string)
	switch t {
	case splunk:
		m := reSplunk.FindAllStringSubmatch(msg, -1)
		for _, e := range m {
			if len(e) > 2 {
				r[e[1]] = e[2]
			}
		}
	case number:
		m := reNumber.FindAllStringSubmatch(msg, -1)
		for i, e := range m {
			k := fmt.Sprintf("number%d", i+1)
			if len(e) > 1 {
				r[k] = e[1]
			}
		}
	default:
		m := reIPv4.FindAllStringSubmatch(msg, -1)
		for i, e := range m {
			k := fmt.Sprintf("ip%d", i+1)
			if len(e) > 1 {
				r[k] = e[1]
			}
		}
		m = reMAC.FindAllStringSubmatch(msg, -1)
		for i, e := range m {
			k := fmt.Sprintf("mac%d", i+1)
			if len(e) > 1 {
				r[k] = e[1]
			}
		}
		m = reEMail.FindAllStringSubmatch(msg, -1)
		for i, e := range m {
			k := fmt.Sprintf("email%d", i+1)
			if len(e) > 1 {
				r[k] = e[1]
			}
		}
	}
	return r, nil
}

のように作って、これまでGROKの抽出パターンを選択していたところに、

のような項目を追加しました。

2024/03/07 05:32:10.284 info:local5 twWifiScan type=Monitor,cpu=0.485,load=0.000,mem=50.938,recv=57872,sent=30758,rxSpeed=0.008,txSpeed=0.004,process=167,param=wlan0

のようなログから数値だけ取り出すと

のような感じになります。順番にnumber1,number2のような変数名になります。SPLUNK風の取り出しかたをすれば、

のようにちゃんと変数の名前がつきます。グラフも表示できます。

すばらしい!
この機能は、シン・TWSNMPにも応用しようと思っています。
ログに関して、もっといろいろアイデアがあって楽しくなってきましたが、今朝は時間切れです。

明日に続く

開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。