Monitorix

Monitorix is a great tool to measure and graph your devices and services .

it works perfectly on your local device to monitor and archive performances and usages.

Custom Monitor

Although there are many builtin monitored items (system, cpu, net, sensors, applications …) and features, you may have to monitor a special device or application that is not yet integrated .

That's the purpose of this page to explain how I managed to monitor my personal gateway to the Internet which doesn't have builtin graph capabilities .

I want to get In and Out traffic like that :

install monitorix

First we need to install and configure monitorix, there are many tutorials to do that, as I am using centos 8 system I followed that one :

Custom device

In this page I will demonstrate how I manage to monitor In and Out bandwidth usage of my FreeBox-Crystal which is a French ADSL router . The device does provide an http service to get the status of its services . it replies on the Lan interface at the address of the router itself

this page returns many information in text format like this :

______________________________________________________________________

                      Etat de la Freebox                           
______________________________________________________________________

Informations générales :
========================

  Modèle                         Freebox ADSL            
  Version du firmware            1.5.28                  
  Mode de connection             Dégroupé                
  Temps depuis la mise en route  33 jours, 20 heures, 34 minutes

....
Adsl :
======

  Etat                           Showtime                
  Protocole                      ADSL2+                  
  Mode                           Interleaved             

                         Descendant         Montant           
                         --                 --                
  Débit ATM              11074 kb/s         681 kb/s          
...
   Interfaces réseau :
 -------------------

                         Lien           Débit entrant  Débit sortant 
                         --             --             --            
  WAN                    Ok             63 ko/s        9 ko/s        
  Ethernet               100baseTX-FD   10 ko/s        54 ko/s       

From the differents information provided by this web interface, the ones I want to graph is on the WAN interface the In trafic (here 63 Ko/s) and Out (9 ko/s)

Custom module

I am not a monitorix developer , but with great and smart indication from Monitorix developers , as there is no generic module nor snmp capailities (anyway my Freebox doesn't provide such) , I was advise to create my own module based on an existing one that already collect and graph values from an http request . The Nginx module was my starting point .

copy nginx

you can check location of all the monitorix components by requesting file location of the monitorix package with :

# rpm -ql monitorix
/etc/logrotate.d/monitorix
/etc/monitorix
/etc/monitorix/conf.d
/etc/monitorix/monitorix.conf
/etc/sysconfig/monitorix
/usr/bin/monitorix
/usr/lib/monitorix
/usr/lib/monitorix/HTTPServer.pm
/usr/lib/monitorix/Monitorix.pm
...
/usr/lib/monitorix/nginx.pm
...
/var/lib/monitorix/www
/var/lib/monitorix/www/cgi
/var/lib/monitorix/www/cgi/monitorix.cgi
...

here we can see particularly /etc/monitorix/monitorix.conf which is the main configuration file and /usr/lib/monitorix/nginx.pm which is the module I will duplicate for my device .

# cp nginx.pm fbxcfr.pm
# pwd
/usr/lib/monitorix

dev environment

After you have checked that monitorix works fine with native modules, to help debugging , I disabled all modules from the main config file : monitorix.conf in order that logs shows only potential problem of my specific module here named fbxcfr (just after nginx) .

<graph_enable>
        system          = n
        kern            = n
        proc            = n
        ....
        nginx           = n
        fbxcfr          = y

duplicate almost all nginx parameters in the conf file to fbxcfr (or whatever name you give to your module) so that your module is taken into account by the monitorix daemon . this happens in different sections: graph_enable, graph_name, graph_title and graphs

add module to monitorix.conf

<graph_enable>

        fbxcfr          = y

...
# fbxcfr graph
# -----------------------------------------------------------------------------
<fbxcfr>
        url = http://192.168.3.254/pub/fbx_info.txt
        port = 80
        rigid = 0, 0, 0
        limit = 100, 100, 100
</fbxcfr>
...
graph_name = system, kern, proc, ... nginx, fbxcfr,

<graph_title>
...
  nginx           = Nginx statistics
  fbxcfr          = FreeboX-Crystal statistics
...
<graphs>
...
 _nginx1         = Nginx connections
        _nginx2         = Nginx requests
        _nginx3         = Nginx traffic
        _fbxcfr1                = FbxCFR connections
        _fbxcfr2                = FbxCFR requests
        _fbxcfr3                = FbxCFR traffic
...

monitorix daemon in debug mode

stop your traditional run of monitorix

# systemctl stop monitorix.service 

execute it in debug and foreground mode to be able to see potential errors

# /usr/bin/monitorix -c /etc/monitorix/monitorix.conf -n -d all

if the module is up and running (cf code fbxcfr.pm next) here's what the logs says after starting the daemon in debug mode

Tue Apr 21 17:57:49 2020 - Starting Monitorix version 3.12.0 (pid 1166).
Tue Apr 21 17:57:49 2020 - Loaded main configuration file '/etc/monitorix/monitorix.conf'.
Tue Apr 21 17:57:49 2020 - Entering in debug mode.
Tue Apr 21 17:57:49 2020 - Changed process name to '/usr/bin/monitorix -c /etc/monitorix/monitorix.conf -p /run/monitorix.pid -d all'.
Tue Apr 21 17:57:49 2020 - Flushing out iptables rules.
Tue Apr 21 17:57:49 2020 - 0 iptables rules have been flushed.
Tue Apr 21 17:57:49 2020 - 0 ip6tables rules have been flushed.
Tue Apr 21 17:57:49 2020 - Initializing graphs.

Tue Apr 21 17:57:49 2020 - fbxcfr::fbxcfr_init: Ok

Tue Apr 21 17:57:49 2020 - Generating the 'index.html' file.
Tue Apr 21 17:57:49 2020 - Setting owner/group and permission bits for the imgs/ directory.
Tue Apr 21 17:57:49 2020 - Started HTTP built-in server (pid 1214).
Tue Apr 21 17:57:49 2020 - Ok, ready.
HTTPServer: You can connect to your server at http://localhost:8080/

then after few second (at next minute) , here comes my two values (converted to bytes) In and Out inserted in the rrd file

Tue Apr 21 17:58:00 2020 - Calling fbxcfr_update()
Tue Apr 21 17:58:01 2020 - fbxcfr::fbxcfr_update: N:57344:6144

RRD file for the module

we can check the rrd file for the value it collected

#  rrdtool fetch /var/lib/monitorix/fbxcfr.rrd LAST | tail -5
1587484440: 3,1267075959e+04 8,8793457323e+03
1587484500: 5,9931363328e+04 1,6254763554e+04
1587484560: 2,7674024499e+05 1,2321572864e+04
1587484620: 6,6060986658e+04 4,2323786411e+03
1587484680: 5,7390888533e+04 6,1252445867e+03

fbxcfr.pm module code

as explained earlier , I copied the nginx module to create mine fbxcfr module . I followed the same process of fetching a URL and parse it to collect interesting values to graph .

Frame

here the “Frame” of the package with 3 subroutines :

package fbxcfr;
...
sub fbxcfr_init {
...
sub fbxcfr_update {
...
sub fbxcfr_cgi {
...

in order to not forget any replacement occurence of the nginx string, I search and replace every occurence of nginx with fbxcfr I used VI to do that , here's the magic command to search and repalce all in VI

:1,$s/nginx/fbxcfr/g
  • : switch to comand
  • 1 from 1st line of the file
  • ,$ to last line
  • /nginx search nginx string
  • /fbxcfr/ and replace it by fxcfr
  • g globally (if more than one occurence by line

collected values code

I changed a few lines in the code (a dozen ) and commented many . Indeed the nginx module collect all these :

$reqs:$tot:$reads:$writes:$waits:$in:$out

from these only the 2 last ones (in/out) are of interest to me .

not to confused with the original values/variables I named mine din and dout

here are the main changes I did :

sub fbxcfr_update {
...
 my $fbxcfr = $config->{fbxcfr};
...
        my $in = 0;
        my $out = 0;
        my $din = 0;
        my $dout = 0;

        my $url;

        if($fbxcfr->{url}) {
                $url = $fbxcfr->{url};
        } else {
                $url = "http://192.168.0.254/pub/fbx_info.txt"; #hard coded here but can be set in monitorix.conf module parameters
        }
...
                #if(/^Reading:\s+(\d+).*Writing:\s+(\d+).*Waiting:\s+(\d+)\s*/) {
                #get line starting with 2 spaces then WAN string and match the 2 digit (\d+)  values before string ko/s 
                if(/^\s\sWAN\s+Ok\s+(\d+)\sko\/s\s+(\d+)\sko\/s/) { 
                        $din = $1; #print "din: $din\n"; # for debug
                        $dout = $2; #print "dout: $dout\n"; # for debug 
                        $din *= 1024;
                        $dout *= 1024;


 $rrdata .= ":$din:$dout";
 RRDs::update($rrd, $rrdata);
...

sub fbxcfr_cgi {
...
                push(@output, "    <tr>\n");
                push(@output, "    <td bgcolor='$colors->{title_bg_color}'>\n");
        }
# comment out everything related to request , total, reads, writes , wait from the nginx values around line 387   
 =BEGIN
        push(@tmp, "AREA:total#44EEEE:Total");
        push(@tmp, "GPRINT:total:LAST:       Current\\: %5.0lf");
        push(@tmp, "GPRINT:total:AVERAGE:    Average\\: %5.0lf");
        push(@tmp, "GPRINT:total:MIN:    Min\\: %5.0lf");
        push(@tmp, "GPRINT:total:MAX:    Max\\: %5.0lf\\n");
        push(@tmp, "AREA:reading#44EE44:Reading");
        push(@tmp, "GPRINT:reading:LAST:     Current\\: %5.0lf");
...
        @riglim = @{setup_riglim($rigid[2], $limit[2])};
        undef(@tmp);
        undef(@tmpz);
        undef(@CDEF);
 =END
 =cut
# end comment up until around line 626 (quite long !) 

# to begin with our In and Out values to graph 
        push(@tmp, "AREA:B_in#44EE44:Input");
        push(@tmp, "AREA:B_out#4444EE:Output");
        push(@tmp, "AREA:B_out#4444EE:");
        push(@tmp, "AREA:B_in#44EE44:");
        push(@tmp, "LINE1:B_out#0000EE");
        push(@tmp, "LINE1:B_in#00EE00");
        push(@tmpz, "AREA:B_in#44EE44:Input");
        push(@tmpz, "AREA:B_out#4444EE:Output");
        push(@tmpz, "AREA:B_out#4444EE:");
        push(@tmpz, "AREA:B_in#44EE44:");
        push(@tmpz, "LINE1:B_out#0000EE");
        push(@tmpz, "LINE1:B_in#00EE00");
...
        return @output;
}

1;

fbxcfr.pm file

here is the full module file (unzip to get the .pm )

fbxcfr.pm.zip

image result zoom