wd and cc

-- Good good study, day day up!

Add Monitor Graphs to Openwrt

#Openwrt #Graph

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-statistics

We 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-thermal

Most 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=    1639282486
  • wg0 is the device name
  • L8yns9ycPwd5/gxIm02zGifWfnMCg5f0hGqdya8pAxg is the public key.
  • 1639282486 is 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
24done

The 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 HOSTNAME and INTERVAL are placeholders. They will be replaced with the correct value later.
  • For the exec-wireguard, exec is the plugin name, the wireguard is the plugin instance name.
  • For the gauge-last_handshake_$name, gauge is the metric type. It must be inclued in the /usr/share/collectd/types.db file. You also can use one of the existed type from there. last_handshake_$name is 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"
11done

This 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.rrd

Add 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_wg0 and gauge_last_handshake_wg1: this is optional. I want to rename the metrics name and set the color for the graph. Please notice the _ after the gauge is very important. Don't use - here.
comments powered by Disqus