Add Monitor Graphs to Openwrt
According to the docs here https://openwrt.org/docs/guide-user/luci/luci_app_statistics, OpenWrt supports us using the Collectd to collect metrics and the Rrdtool draw the graph later.
Install
1opkg update
2opkg install luci-app-statisticsWe can run the command opkg list | grep collectd-mod to see what mertics we can collect. I have installed these modules
1collectd-mod-cpu
2collectd-mod-curl
3collectd-mod-dns
4collectd-mod-exec
5collectd-mod-interface
6collectd-mod-iwinfo
7collectd-mod-load
8collectd-mod-memory
9collectd-mod-network
10collectd-mod-ping
11collectd-mod-rrdtool
12collectd-mod-thermalMost of the plugins work out of the box, such as the cpu one. And some of them need some configurations on the UI, such as the curl one. You have to tell the plugin the URL you want to monitor.
The exec plugin is a special one. It needs you to write some codes to get it work.
Create a script for the exec plugin
On the UI settings page of the exec plugin, we can set several scripts path for that plugin to execute. We have to create the scripts by ourselves.
For example, I will create a graph for the last handshake time of the Wireguard VPN. The command and the output for getting the last handshake time are below.
1wg show all latest-handshakes
2wg0 L8yns9ycPwd5/gxIm02zGifWfnMCg5f0hGqdya8pAxg= 0
3wg0 7fR3QgAwgW/jMKWNtrnrXlxYxXc0mQA1YVv0VMz+dSg= 1639203670
4wg0 cgCozSFbCG6SvENpITD5n6SF9vWyYO0J6jOuziy3tyU= 1639282576
5wg1 wFyXEweIGqzB3Keg/bBmxGfBcKpp222/YMyNwvjRgiQ= 1639282486wg0is the device nameL8yns9ycPwd5/gxIm02zGifWfnMCg5f0hGqdya8pAxgis the public key.1639282486is the timestamp when the last handshake happened.
The command needs the root permission to execute. However, the exec plugin can be running as root. So we have to take a detour. There are three pieces of work to do.
Create a cron job to collect the data
To run the command with the root permission, we must create this script first, which will collect the data and write the data to /tmp folder.
1mkdir /etc/wg 1#!/bin/sh
2
3output=/tmp/wg.collect
4rm -f $output && touch $output && chmod 666 $output
5
6current=$(date +%s)
7
8conf="cgCozSFbCG6SvENpITD5n6SF9vWyYO0J6jOuziy3tyU= wg0
9wFyXEweIGqzB3Keg/bBmxGfBcKpp222/YMyNwvjRgiQ= wg1"
10
11wg show all latest-handshakes | while read line; do
12 device=$(echo $line | awk -F ' ' '{print $1}')
13 peer=$(echo $line | awk -F ' ' '{print $2}')
14 dt=$(echo $line | awk -F ' ' '{print $3}')
15 name=$(echo "$conf" | grep "$peer" | awk -F ' ' '{print $2}')
16
17 if [ "$dt" = "0" ] || [ -z "$name" ]; then
18 continue
19 fi
20
21 diff=$(($current - $dt))
22
23 echo "PUTVAL \"HOSTNAME/exec-wireguard/gauge-last_handshake_$name\" interval=INTERVAL N:$diff" >> $output
24doneThe script will write the outputs to the /tmp/wg.collect file. You may want to change the conf settings. It will help us filter which peer we want to monitor and the alias for that peer.
The output is defined here "PUTVAL \"HOSTNAME/exec-wireguard/gauge-last_handshake_$name\" interval=INTERVAL N:$diff". The output format is critical.
- First of all, the
HOSTNAMEandINTERVALare placeholders. They will be replaced with the correct value later. - For the
exec-wireguard,execis the plugin name, thewireguardis the plugin instance name. - For the
gauge-last_handshake_$name,gaugeis the metric type. It must be inclued in the/usr/share/collectd/types.dbfile. You also can use one of the existed type from there.last_handshake_$nameis the metric name.
Add the script to the system -> Scheduled Tasks. * * * * * /etc/wg/wg.sh.
Check whether the file /tmp/wg.collect has been created and updated after adding it to the crontab.
Create the file script for the exec plugin
Create a file /etc/wg/exec-wg.sh
1#!/bin/sh
2
3HOSTNAME="${COLLECTD_HOSTNAME:-Tux}"
4INTERVAL="${COLLECTD_INTERVAL:-60}"
5INTERVAL=$(awk -v i=$INTERVAL 'BEGIN{print int(i)}')
6
7input=/tmp/wg.collect
8
9while sleep "$INTERVAL"; do
10 cat $input | sed "s/HOSTNAME/$HOSTNAME/g" | sed "s/INTERVAL/$INTERVAL/g"
11doneThis script will run and loop forever, read and print the file content. There is nothing special here.
After adding the file to the exec plugin settings UI, run these commands to check if it works.
1# ps |grep exec-wg
2 4001 nobody 1088 SN /bin/sh /etc/wg/exec-wg.sh
3
4# ls <path-to-rrd-data-directory>/exec-wireguard/
5gauge-last_handshake_wg0.rrd gauge-last_handshake_wg1.rrdAdd graph to the OpenWrt graph page
Create the file /www/luci-static/resources/statistics/rrdtool/definitions/exec.js as bellow.
1'use strict';
2'require baseclass';
3return baseclass.extend({
4 title: _('Exec'),
5 rrdargs: function(graph, host, plugin, plugin_instance, dtype) {
6 // host: Tux
7 // plugin: exec
8 // plugin_instance: wireguard
9 // dtype: null
10 var wireguard_last_handshake_time = {
11 title: "%H: wireguard last handshake time",
12 vlabel: "seconds",
13 alt_autoscale_max: true,
14 data: {
15 types: ["gauge"],
16 options: {
17 gauge_last_handshake_wg0: {
18 color: "ff0000",
19 // noavg: true,
20 noarea: true,
21 // overlay: true,
22 // flip: true,
23 title: "wg0"
24 },
25 gauge_last_handshake_wg1: {
26 color: "0000ff",
27 // noavg: true,
28 noarea: true,
29 title: "wg1"
30 }
31 }
32 }
33 };
34 return wireguard_last_handshake_time;
35 }
36});The important thing in the file
title: _('Exec'),: define the graph title.types: ["gauge"],: define the source data type.gauge_last_handshake_wg0andgauge_last_handshake_wg1: this is optional. I want to rename the metrics name and set the color for the graph. Please notice the_after thegaugeis very important. Don't use-here.