Install Zabbix Frontend

Set up frontend for Zabbix on FreeBSD. Optinal set up weathermap and Grafana to use Zabbix database

Install Zabbix Frontend

Install software

#Need mod HTTP_REWRITE
portmaster -d www/nginx net-mgmt/zabbix6-frontend

Config PHP

cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini
vi /usr/local/etc/php.ini
max_execution_time = 600
max_input_time = 600
memory_limit = 256M
post_max_size = 16M
upload_max_filesize = 16M
date.timezone = Asia/Bangkok
cp /usr/local/etc/php-fpm.conf.default /usr/local/etc/php-fpm.conf
vi /usr/local/etc/php-fpm.d/www.conf
listen = /tmp/php-fpm.sock 
listen.owner = www 
listen.group = www

Config NGINX

vi /usr/local/etc/nginx/nginx.conf

gzip on;
server { 
     listen 80;
     server_name zabbix-frontend;

     location / {
         root /usr/local/www/zabbix6;
         index index.html index.php;
     }
     #Fix saved tab location
     location /dashboard.php {
         return 301 /;
     }

     location ~ \.php$ {
         root html;
         fastcgi_pass unix:/tmp/php-fpm.sock; 
         # fastcgi_index index.php;
         fastcgi_param SCRIPT_FILENAME /usr/local/www/zabbix6$fastcgi_script_name;
         fastcgi_param QUERY_STRING $query_string; 
         include fastcgi_params;
         proxy_read_timeout 600s;
         fastcgi_read_timeout 600s;
     }
}

Start service

vi /etc/rc.conf

zabbix_agentd_enable="YES"
php_fpm_enable="YES"
nginx_enable="YES"
service zabbix_agentd start
service php-fpm start
service nginx start

Grafana integration

Install grafana integration

portmaster -d www/grafana9
grafana-cli plugins install alexanderzobnin-zabbix-app

Download source(Compile missing binary)

fetch "https://github.com/alexanderzobnin/grafana-zabbix/archive/refs/tags/v4.2.10.zip"
unzip v4.2.10.zip
cd grafana-zabbix-4.2.10/
go mod vendor
env GOOS=freebsd GOARCH=amd64 go build -ldflags="-s -w" -mod=vendor -o ./dist/zabbix-plugin_freebsd_amd64 ./pkg
cp ./dist/zabbix-plugin_freebsd_amd64 /var/db/grafana/plugins/alexanderzobnin-zabbix-app/

Edit manifest file

Get freebsd plugin binary hash

sha256 /var/db/grafana/plugins/alexanderzobnin-zabbix-app/zabbix-plugin_freebsd_amd64

vi /var/db/grafana/plugins/alexanderzobnin-zabbix-app/MANIFEST.txt Add line in section files with sha256 from “sha256 ./dist/zabbix-plugin_freebsd_amd64”

  "files": {
    "zabbix-plugin_freebsd_amd64": "ba862df9d39b20cfb93c151e907bf91600628d555ca7ea46c6142c33a59a8a08",
    ...
  }

Remove PGP message from file, MANIFEST.txt should have only json format

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

-----BEGIN PGP SIGNATURE-----
...
-----END PGP SIGNATURE-----

Allow unsigned plugin

vi /usr/local/etc/grafana/grafana.ini

allow_loading_unsigned_plugins = alexanderzobnin-zabbix-datasource,alexanderzobnin-zabbix-triggers-panel,alexanderzobnin-zabbix-app

Restart grafana

service grafana restart

Config datasource

# Zabbix
HTTP:
  URL: http://127.0.0.1/api_jsonrpc.php
Zabbix API details:
  # Need valid username/password on zabbix server
  Username: grafana
  Password: grafana
  Trends: Enable
  # Zabbix Data storage period
  After: 90d
  Range: 7d
# If have have Zabbix Postgresql datasource set up
Direct DB Connection:
  Enable: Enable
  Data Source: Zabbix-DB-Name

Weathermap integration

Install phpweathermap

portmaster -d net-mgmt/phpweathermap

Config nginx

vi /usr/local/etc/nginx/nginx.conf

load_module /usr/local/libexec/nginx/ngx_http_fancyindex_module.so;
 location /map/ {
     alias /home/www/map/;
     #autoindex on;
     fancyindex on;
     fancyindex_exact_size off;
     fancyindex_ignore \.png;
    fancyindex_localtime on;
 }

 location = /map/overlib.js {
     return 301 /map/editor/overlib.js;
 }

 location /map/editor {
 #root /usr/local/share/phpweathermap/www/;
     alias /usr/local/share/phpweathermap/www/;
     location = /map/editor {
         return 302 /map/editor/editor.php;
     }
     location = /map/editor/ {
         return 302 /map/editor/editor.php;
     }
     location ~ \.php$ {
         fastcgi_pass unix:/tmp/php-fpm.sock;
         fastcgi_param SCRIPT_FILENAME /usr/local/share/phpweathermap/www/editor.php;
         fastcgi_param QUERY_STRING $query_string;
         include fastcgi_params;
     }
 }

Cron job

mkdir /home/www/
mkdir /home/www/map/
chown -R www:www /home/www/
vi /home/www/map.sh
#!/bin/sh

cd /usr/local/share/phpweathermap/www/
for FILE in `ls /usr/local/share/phpweathermap/www/configs`
do
     NAME=`echo $FILE | sed 's/\(.*\)\.conf/\1/'`
     /usr/local/bin/php /usr/local/bin/phpweathermap \
         --config configs/$FILE \
         --output /home/www/map/$NAME.png \
         --htmloutput /home/www/map/$NAME.html \
         --image-uri /map/$NAME.png &
done

vi /etc/crontab

*       *       *       *       *       root    /home/www/map.sh

Fix phpweathermap php legacy code

Add new code
/usr/local/share/phpweathermap/Weathermap.class.php line 408
$this->fonts[$i] = new \stdClass();

405
406
407
408
409
410
411
412
                // Adding these makes the editor's job a little easier, mainly
                for($i=1; $i<=5; $i++)
                {
                        $this->fonts[$i] = new \stdClass();
                        $this->fonts[$i]->type="GD builtin";
                        $this->fonts[$i]->file='';
                        $this->fonts[$i]->size=0;
                }

/usr/local/share/phpweathermap/Weathermap.class.php line 458
Replace function split with explode

455
456
457
458
459
460
461
        function myimagestringsize($fontnumber, $string)
        {
                $linecount = 1;

                $lines = explode("\n",$string);
                $linecount = sizeof($lines);
                $maxlinelength=0;
rm /usr/local/share/phpweathermap/lib/pre/WeatherMapPreProcessorTest.php
rm /usr/local/share/phpweathermap/lib/post/WeatherMapPostProcessorTest.php

Add zabbix DB to phpweathermap

vi /usr/local/share/phpweathermap/lib/zabbix_db.php

<?php
class ZabbixPSQL {
    private $host = '192.168.213.166';
    private $name = 'zabbix';
    private $user = 'zabbix';
    private $pass = '39zabbix';
    private $nlim = 360;
    private $slim = 4800;
    
    // DB object;
    private $db;
    function __construct() {
        $this->db = pg_connect ( "host=$this->host dbname=$this->name user=$this->user password=$this->pass" );
        if ($this->db) {
            debug ( "ZabbixPSQL Init: Connected to DB.)\n" );
            $this->prepareStmt ();
            return true;
        } else {
            debug ( "ZabbixPSQL Init: Unable to connect DB\n" );
            return false;
        }
    }
    private function prepareStmt() {
        $result = pg_query_params ( $this->db, 'SELECT name FROM pg_prepared_statements WHERE name = $1', array (
                "get_itemid_by_name" 
        ) );
        if (pg_num_rows ( $result ) == 0) {
            pg_prepare ( $this->db, "get_itemid_by_name", 
                    // SQL stmt
                    'SELECT itemid FROM items WHERE key_ = $2 AND hostid = (SELECT hostid FROM hosts WHERE name = $1) LIMIT 1;' );
        }
        $result = pg_query_params ( $this->db, 'SELECT name FROM pg_prepared_statements WHERE name = $1', array (
                "get_item_value" 
        ) );
        $lim_time = time() - $this->nlim;
        if (pg_num_rows ( $result ) == 0) {
            pg_prepare ( $this->db, "get_item_value", 
                // cache item id
                'WITH cache AS (SELECT itemid FROM items WHERE key_ = $2 AND hostid = (SELECT hostid FROM hosts WHERE name = $1))' . 
                // query from history
                '(SELECT itemid, clock, value FROM history WHERE clock > ' . $lim_time . ' AND itemid = (SELECT itemid FROM cache) ORDER BY clock DESC LIMIT 1)' . 
                // merge to
                ' UNION ALL ' . 
                // query from history_uint
            '(SELECT itemid, clock, value FROM history_uint WHERE clock > ' . $lim_time . ' AND itemid = (SELECT itemid FROM cache) ORDER BY clock DESC LIMIT 1)' . ';' );
        }
        $result = pg_query_params ( $this->db, 'SELECT name FROM pg_prepared_statements WHERE name = $1', array (
                "get_graph_by_item" 
        ) );
        if (pg_num_rows ( $result ) == 0) {
            pg_prepare ( $this->db, "get_graph_by_item", 
                    // SQL stmt
                    'SELECT graphid FROM graphs_items WHERE itemid = (SELECT itemid FROM items WHERE key_ = $2 AND hostid = (SELECT hostid FROM hosts WHERE name = $1)) LIMIT 1;' );
        }
        $result = pg_query_params ( $this->db, 'SELECT name FROM pg_prepared_statements WHERE name = $1', array (
                "get_graph_by_name" 
        ) );
        if (pg_num_rows ( $result ) == 0) {
            pg_prepare ( $this->db, "get_graph_by_name", 
                // SQL stmt
                'SELECT graphid FROM graphs WHERE name = $2 AND graphid IN (SELECT graphid FROM graphs_items WHERE itemid IN (SELECT itemid FROM items WHERE hostid = (SELECT hostid FROM hosts WHERE name = $1))) LIMIT 1;' );
        }
        $result = pg_query_params ( $this->db, 'SELECT name FROM pg_prepared_statements WHERE name = $1', array (
            "get_item_text" 
        ) );
        $lim_time = $lim_time + $this->nlim - $this->slim;
        if (pg_num_rows ( $result ) == 0) {
            pg_prepare ( $this->db, "get_item_text", 
                // cache item id
                'WITH cache AS (SELECT itemid FROM items WHERE key_ = $2 AND hostid = (SELECT hostid FROM hosts WHERE name = $1))' . 
                // query from history
                '(SELECT itemid, clock, value FROM history_str WHERE clock > ' . $lim_time . ' AND itemid = (SELECT itemid FROM cache) ORDER BY clock DESC LIMIT 1)' .
                // merge to
                ' UNION ALL ' . 
                // query from history_uint
            '(SELECT itemid, clock, value FROM history_text WHERE clock > ' . $lim_time . ' AND itemid = (SELECT itemid FROM cache) ORDER BY clock DESC LIMIT 1)' . ';' );
        }
        $result = pg_query_params ( $this->db, 'SELECT name FROM pg_prepared_statements WHERE name = $1', array (
            "get_host_by_name" 
        ) );
        $lim_time = $lim_time + $this->nlim - $this->slim;
        if (pg_num_rows ( $result ) == 0) {
            pg_prepare ( $this->db, "get_host_by_name", 
                    // SQL stmt
                    'SELECT hostid FROM hosts WHERE name = $1 LIMIT 1;' );
        }
        // END
    }
    function isConnected() {
        return pg_ping ( $this->db );
    }
    function getItemId($host, $keyname) {
        $result = pg_execute ( $this->db, "get_itemid_by_name", array (
                $host,
                $keyname 
        ) );
        if ($result) {
            $row = pg_fetch_row ( $result );
            if ($row) {
                return $row [0];
            }
        }
        return null;
    }
    function getItemLastValue($host, $keyname) {
        $result = pg_execute ( $this->db, "get_item_value", array (
                $host,
                $keyname 
        ) );
        if ($result) {
            $row = pg_fetch_row ( $result );
            if ($row) {
                $itemid = $row [0];
                $clock = $row [1];
                $val = $row [2];
                return array (
                        "lastvalue" => $val,
                        "lastclock" => $clock 
                );
            }
        }
        return null;
    }
    function getItemText($host, $keyname) {
        $result = pg_execute ( $this->db, "get_item_text", array (
                $host,
                $keyname 
        ) );
        if ($result) {
            $row = pg_fetch_row ( $result );
            if ($row) {
                $itemid = $row [0];
                $clock = $row [1];
                $val = $row [2];
                return $val;
            }
        }
        return null;
    }
    function getGraphIdByItem($host, $item) {
        $result = pg_execute ( $this->db, "get_graph_by_item", array (
                $host,
                $item 
        ) );
        if ($result) {
            $row = pg_fetch_row ( $result );
            if ($row) {
                $graphid = $row [0];
                return $graphid;
            }
        }
        return null;
    }
    function getGraphIdByName($host, $name) {
        $result = pg_execute ( $this->db, "get_graph_by_name", array (
                $host,
                $name 
        ) );
        if ($result) {
            $row = pg_fetch_row ( $result );
            if ($row) {
                $graphid = $row [0];
                return $graphid;
            }
        }
        return null;
    }
    function getHostIdByName($host) {
        $result = pg_execute ( $this->db, "get_host_by_name", array ($host) );
        if ($result) {
            $row = pg_fetch_row ( $result );
            if ($row) {
                $graphid = $row [0];
                return $graphid;
            }
        }
        return null;
    }
}

vi /usr/local/share/phpweathermap/lib/datasources/WeatherMapDataSource_zabbixdb.php

<?php
// Zabbix pluggable datasource for PHP Weathermap 0.9
// - reads a pair of values from the JSON API

// TARGET zabbix:host:in:out
require_once (__DIR__ . "/../zabbix_db.php");
class WeatherMapDataSource_zabbixdb extends WeatherMapDataSource {
    private $db;
    function Init(&$map) {
        $this->db = new ZabbixPSQL ();
        return $this->db->isConnected ();
    }
    function Recognise($targetstring) {
        if (preg_match ( "/^zabbixdb:key_:([\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+)$/", $targetstring, $matches )) {
            return true;
        } else if (preg_match ( "/^zabbixdb:ifname:([\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+)$/", $targetstring, $matches )) {
            return true;
        } else if (preg_match ( "/^zabbixdb:text:([\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+)$/", $targetstring, $matches )) {
            return true;
        } else if (preg_match ( "/^zabbixdb:ifstat:([\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+)$/", $targetstring, $matches )) {
            return true;
        }
        return false;
    }
    function ReadData($targetstring, &$map, &$item) {
        $data [IN]  = 0;
        $data [OUT] = 0;
        $data_time = 0;
        
        debug ( "ZabbixDB ReadData: Catch (" . $targetstring . ")\n" );
        
        if (preg_match ( "/^zabbixdb:ifname:([\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+)$/", $targetstring, $matches )) {
            $host = $matches [1];
            $ifname = $matches [2];
            
            $key_in  = $map->get_hint('data_zabbixdb_key_in');
            $key_out = $map->get_hint('data_zabbixdb_key_out');
        
            $key_in  = isset ( $key_in  )?$key_in:'ifHCInOctets';
            $key_out = isset ( $key_out )?$key_out:'ifHCOutOctets';
            
            $i_key_in  = $item->get_hint('data_zabbixdb_key_in');
            $i_key_out = $item->get_hint('data_zabbixdb_key_out');
            
            $f_key_in  = isset ( $i_key_in  )?$i_key_in:$key_in;
            $f_key_out = isset ( $i_key_out )?$i_key_out:$key_out;
        
            //$in  = $f_key_in  . '[' . $ifname . ']';
            //$out = $f_key_out . '[' . $ifname . ']';

            $in  = 'net.if.in[' . $f_key_in  . '.' . $ifname . ']';
            $out = 'net.if.out[' . $f_key_out  . '.' . $ifname . ']';    
            
            debug ( "ZabbixDB ReadData: Found (" . $host . "," . $ifname . ")\n" );
            
            $raw_out_value = $this->db->getItemLastValue ( $host, $out );
            $raw_in_value = $this->db->getItemLastValue ( $host, $in );
            $in_value = isset($raw_in_value["lastvalue"])?$raw_in_value["lastvalue"]:false;
            $out_value = isset($raw_out_value["lastvalue"])?$raw_out_value["lastvalue"]:false;
            $data_time = isset($raw_out_value["lastclock"])?$raw_out_value["lastclock"]:false;
            if (isset ( $in_value )) {
                $data [IN] = $in_value;
            }
            if (isset ( $out_value )) {
                $data [OUT] = $out_value;
            }
        } else if (preg_match ( "/^zabbixdb:key_:([\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+)$/", $targetstring, $matches )) {
            $host = $matches [1];
            $in = $matches [2];
            $out = $matches [3];
            
            debug ( "ZabbixDB ReadData: Found (" . $host . "," . $in . "," . $out . ")\n" );
            
            $raw_in_value = $this->db->getItemLastValue ( $host, $in );
            if($out != '-') {
                $raw_out_value = $this->db->getItemLastValue ( $host, $out );
            }
            $in_value = $raw_in_value ["lastvalue"];
            $out_value = $raw_out_value ["lastvalue"];
            $data_time = $raw_out_value ["lastclock"];
            if (isset ( $in_value )) {
                $data [IN] = $in_value;
            }
            if (isset ( $out_value )) {
                $data [OUT] = $out_value;
            }
        } else if (preg_match ( "/^zabbixdb:text:([\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+)$/", $targetstring, $matches )) {
            $host = $matches [1];
            $name = $matches [2];
            
            debug ( "ZabbixDB ReadData: Found (" . $host . "," . $name . ")\n" );
            
            $raw_value = $this->db->getItemText ( $host, $name );
            $item->add_note ( "text", $raw_value );
            debug ( "ZabbixDB ReadData: Add Note (" . $raw_value . ")\n" );
            $data [IN] = $data [OUT] = -1;
        } else if (preg_match ( "/^zabbixdb:ifstat:([\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+)$/", $targetstring, $matches )) {
            $host = $matches [1];
            $key  = $matches [2];
            $ifname = $matches [3];
            
            debug ( "ZabbixDB ReadData: Found (" . $host . "," . $key . "," . $ifname . ")\n" );
        
            $key_oper  = $map->get_hint('data_zabbixdb_key_oper');
            $key_admin = $map->get_hint('data_zabbixdb_key_admin');
        
            $key_oper  = isset ( $key_oper  )?$key_oper:'ifOperStatus';
            $key_admin = isset ( $key_admin )?$key_admin:'ifAdminStatus';
            
            $i_key_oper  = $item->get_hint('data_zabbixdb_key_oper');
            $i_key_admin = $item->get_hint('data_zabbixdb_key_admin');
            
            $f_key_oper  = isset ( $i_key_oper  )?$i_key_oper:$key_oper;
            $f_key_admin = isset ( $i_key_admin )?$i_key_admin:$key_admin;
            
            //$oper  = $f_key_oper  . '[' . $ifname . ']';
            //$admin = $f_key_admin . '[' . $ifname . ']';

            $oper  = 'net.if.status[' . $f_key_oper  . '.' . $ifname . ']';
            $admin = 'net.if.status[' . $f_key_admin  . '.' . $ifname . ']';
            
            $raw_admin_value = $this->db->getItemLastValue ( $host, $admin );
            $raw_oper_value = $this->db->getItemLastValue ( $host, $oper );
            $oper_value = $raw_oper_value ["lastvalue"];
            $admin_value = $raw_admin_value ["lastvalue"];
            $data_time = $raw_oper_value ["lastclock"];
            
            //$raw_value = $this->db->getItemText ( $host, $key . '[' . $ifname . ']' );
            $raw_value = $this->db->getItemText ( $host, 'net.if.name[' . $key  . '.' . $ifname . ']' );
            $item->add_note ( "text", $raw_value );
            debug ( "ZabbixDB ReadData: Add Note (" . $raw_value . ")\n" );
            
            if (isset ( $oper_value )) {
                if( $oper_value == 1) {
                    $data [IN] = $data [OUT] = 1;
                } else {
                    $data [IN] = $data [OUT] = -($oper_value);
                }
            }
            if (isset ( $admin_value )) {
                if( $admin_value != 1) {
                    $data [IN] = $data [OUT] = -1;
                }
            }
        }
        
        debug ( "ZabbixDB ReadData: Returning (" . ($data [IN] === null ? 'null' : $data [IN]) . "," . ($data [OUT] === null ? 'null' : $data [OUT]) . ",$data_time)\n" );
        
        return (array (
                $data [IN],
                $data [OUT],
                $data_time 
        ));
    }
}

vi /usr/local/share/phpweathermap/lib/post/WeatherMapPostProcessorZabbixDB.php

<?php
class WeatherMapPostProcessorZabbixDB extends WeatherMapPostProcessor {

    static function make_graph_url($base_url, $graph_id) {
        return $base_url . '/zabbix.php?view_as=showgraph&action=charts.view&filter_graphids%5B%5D=' . $graph_id;
    }
    static function make_graph_url2($base_url, $host_id, $name) {
        return $base_url . '/zabbix.php?action=charts.view&from=now-24h&to=now&filter_hostids%5B%5D=' . $host_id . '&filter_name=&filter_set=1&filter_show=1&subfilter_tags%5Binterface%5D%5B%5D=' . $name . '&subfilter_set=1';
    }
    static function make_img_url($base_url, $graph_id, $from_time, $width, $height) {
        return $base_url . '/chart2.php?profileIdx=web.charts.filter&width=' . $width . '&height=' . $height . '&from=' . $from_time . '&to=now&graphid=' . $graph_id;
    }
    
    static function make_batch_graph_url($base_url, $item_id, $type = 0) {
        $str = $base_url . '/history.php?action=batchgraph&graphtype=' . $type;
        foreach ($item_id as &$value) {
            $str = $str . '&itemids[' . $value . ']='. $value;
        }
        return $str;
    }
    static function make_batch_img_url($base_url, $item_id, $from_time, $width, $height, $type = 0) {
        $str = $base_url . '/chart.php?profileIdx=web.item.graph.filter&batch=1&from=' . $from_time . '&to=now&type=' . $type . '&width=' . $width . '&height=' . $height;
        foreach ($item_id as &$value) {
            $str = $str . '&itemids[' . $value . ']='. $value;
        }
        return $str;
    }

    function run($map) {
        $enable = $map->get_hint ( 'post_zabbixdb_graphs' );
        
        if ($enable) {
            $this->db = new ZabbixPSQL ();
            if ($this->db->isConnected ()) {
                debug ( "ZabbixDB PostProcessor: Database connect\n" );
                $baseUrl = $map->get_hint ( 'post_zabbixdb_graph_base_url' );
                $addGraphLink = $map->get_hint ( 'post_zabbixdb_graph_link' );
                $graphWidth = $map->get_hint ( 'post_zabbixdb_graph_width' );
                $graphHeight = $map->get_hint ( 'post_zabbixdb_graph_height' );
                $graphFrom= $map->get_hint ( 'post_zabbixdb_graph_from' );
                
                $key_in = $map->get_hint('data_zabbixdb_key_in');
                $key_in = isset ( $key_in )?$key_in:'ifHCInOctets';
                
                // foreach ( array_merge ( $map->links, $map->nodes ) as $item ) {
                foreach ( $map->links as $item ) {
                    foreach ( range ( 0, 1 ) as $k ) { // IN and OUT, if necessary
                        $graph = $item->overliburl [$k];
                        
                        foreach ( $graph as $index => $graphItem ) {
                            // Do work here
                            //debug ( "ZabbixDB PostProcessor: Catch (" . $graphItem . ")\n" );
                            
                            if (preg_match ( '/^zabbixdb:ifname:([a-zA-Z0-9\-\.]+):([a-zA-Z0-9\[\]\-\.\/\%]+)$/', $graphItem, $matches )) {
                                $host = $matches [1];
                                $name = $matches [2];
                                $name = str_replace ( "%20", " ", $name );
                                
                                debug ( "ZabbixDB PostProcessor: Found ( ifname," . $host . "," . $name . ")\n" );
                                
                                $hostId = $this->db->getHostIdByName ( $host );
                                
                                $i_key_in = $item->get_hint('data_zabbixdb_key_in');
                                $f_key_in = isset ( $i_key_in )?$i_key_in:$key_in;
                                
                                //$itemname = $f_key_in . '[' . $name . ']';
                                $itemname = 'net.if.in[' . $f_key_in  . '.' . $name . ']';
                                $graphId = $this->db->getGraphIdByItem ( $host, $itemname );
                                if (isset ( $graphId )) {
                                    if ($addGraphLink) {
                                        #$item->infourl [$k] = static::make_graph_url($baseUrl, $graphId);
                                        $item->infourl [$k] = static::make_graph_url2($baseUrl, $hostId, $name);
                                    }
                                    $item->overliburl [$k] [$index] = static::make_img_url($baseUrl, $graphId, $graphFrom, $graphWidth, $graphHeight);
                                }
                            } else if (preg_match ( '/^zabbixdb:name:([\-a-zA-Z0-9_\.\/\[\]]+):([\%\-a-zA-Z0-9_\.\/\[\]]+)$/', $graphItem, $matches )) {
                                $host = $matches [1];
                                $name = $matches [2];
                                $name = str_replace ( "%20", " ", $name );
                                
                                debug ( "ZabbixDB PostProcessor: Found ( name," . $host . "," . $name . ")\n" );
                                
                                $hostId = $this->db->getHostIdByName ( $host );
                                
                                $graphId = $this->db->getGraphIdByName ( $host, $name );
                                if (isset ( $graphId )) {
                                    if ($addGraphLink) {
                                        #$item->infourl [$k] = static::make_graph_url($baseUrl, $graphId);
                                        $item->infourl [$k] = static::make_graph_url2($baseUrl, $hostId, $name);
                                    }
                                    $item->overliburl [$k] [$index] = static::make_img_url($baseUrl, $graphId, $graphFrom, $graphWidth, $graphHeight);
                                }
                            }
                            
                            // END of work
                        }
                    }
                }
                
                foreach ( $map->nodes as $item ) {
                    //debug ( "ZabbixDB PostProcessor: Found ( ifname," . $host . "," . $item . ")\n" );
                    foreach ( range ( 0, 1 ) as $k ) { // IN and OUT, if necessary
                        $graph = $item->overliburl [$k];
                        
                        foreach ( $graph as $index => $graphItem ) {
                            if (preg_match ( "/^zabbixdb:ifstat:([\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+)$/", $graphItem, $matches )) {
                                $host = $matches [1];
                                $key  = $matches [2];
                                $ifname = $matches [3];
                                
                                debug ( "ZabbixDB PostProcessor: Found ( ifstat," . $host . "," . $name . ")\n" );
                                
                                $key_oper  = $map->get_hint('data_zabbixdb_key_oper');
                                $key_admin = $map->get_hint('data_zabbixdb_key_admin');
                                
                                $key_oper  = isset ( $key_oper  )?$key_oper:'ifOperStatus';
                                $key_admin = isset ( $key_admin )?$key_admin:'ifAdminStatus';
                                
                                $i_key_oper  = $item->get_hint('data_zabbixdb_key_oper');
                                $i_key_admin = $item->get_hint('data_zabbixdb_key_admin');
                                
                                $f_key_oper  = isset ( $i_key_oper  )?$i_key_oper:$key_oper;
                                $f_key_admin = isset ( $i_key_admin )?$i_key_admin:$key_admin;
                                
                                $oper  = 'net.if.status[' . $f_key_oper  . '.' . $ifname . ']';
                                $admin = 'net.if.status[' . $f_key_admin  . '.' . $ifname . ']';
                                
                                $admin_id = $this->db->getItemId ( $host, $admin );
                                $oper_id = $this->db->getItemId ( $host, $oper );
                                
                                if (isset ( $oper_id )) {
                                    if ($addGraphLink) {
                                        $item->infourl [$k] = static::make_batch_graph_url($baseUrl, array($oper_id, $admin_id), 1);
                                    }
                                    $item->overliburl [$k] [$index] = static::make_batch_img_url($baseUrl, array($oper_id, $admin_id), $graphFrom, $graphWidth, $graphHeight, 1);
                                }
                                
                            } else if (preg_match ( "/^zabbixdb:key_:([\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+):([\s\-a-zA-Z0-9_\.\/\[\]]+)$/", $graphItem, $matches )) {
                                $host = $matches [1];
                                $in   = $matches [2];
                                $out  = $matches [3];

                                debug ( "ZabbixDB PostProcessor: Found ( key_," . $host . "," . $name . ")\n" );

                                $in_id  = $this->db->getItemId ( $host, $in );
                                $items = array($in_id);
                                                                
                                if($out != '-') {
                                    $out_id  = $this->db->getItemId ( $host, $out );
                                    array_push($items, $out_id);
                                }
                                                                
                                if (isset ( $in_id )) {
                                    if ($addGraphLink) {
                                        $item->infourl [$k] = static::make_batch_graph_url($baseUrl, $items, 1);
                                    }
                                    $item->overliburl [$k] [$index] = static::make_batch_img_url($baseUrl, $items, $graphFrom, $graphWidth, $graphHeight, 1);
                                }
                                                                
                                $raw_in_value = $this->db->getItemLastValue ( $host, $in );
                            }
                        }
                    }
                }
            } else {
                debug ( "ZabbixDB PostProcessor: Database NOT connect\n" );
            }
        }
    }
}

Example config

WIDTH 1900
HEIGHT 900
HTMLSTYLE overlib
TITLE BKK2

KEYPOS DEFAULT -1 -1 Traffic Load
KEYTEXTCOLOR 0 0 0
KEYOUTLINECOLOR 0 0 0
KEYBGCOLOR 255 255 255
BGCOLOR 255 255 255
TITLECOLOR 0 0 0
TIMECOLOR 0 0 0

SCALE DEFAULT    0    0   0   0 255 
SCALE DEFAULT    0  0.1 192 192 192
SCALE DEFAULT  0.1  0.5 152 251 152
SCALE DEFAULT  0.5    5 144 238 144 
SCALE DEFAULT    5   10  50 205  50 
SCALE DEFAULT   10   30   0 240   0 
SCALE DEFAULT   30   50   0 184   0 
SCALE DEFAULT   50   60 154 205  50 
SCALE DEFAULT   60   70 240 240   0 
SCALE DEFAULT   70   75 255 166  77 
SCALE DEFAULT   75   80 204 102  51 
SCALE DEFAULT   80   90 255  69   0 
SCALE DEFAULT   90  100 255   0   0


SCALE DOWN  -6  -2   255   0   0 
SCALE DOWN  -1  -1     0   0 255   
SCALE DOWN   0   0   255 255 255 
SCALE DOWN   1   1   208 240 192

SET key_hidezero_DEFAULT 1
SET post_zabbixdb_graphs 1
SET post_zabbixdb_graph_link 1
SET post_zabbixdb_graph_base_url ..
SET post_zabbixdb_graph_width 634
SET post_zabbixdb_graph_height 160
SET post_zabbixdb_graph_from now-24h

SET data_zabbixdb_key_in    ifHCInOctets
SET data_zabbixdb_key_out   ifHCOutOctets
SET data_zabbixdb_key_oper  ifOperStatus
SET data_zabbixdb_key_admin ifAdminStatus

# End of global section


# TEMPLATE-only NODEs:
NODE DEFAULT
        MAXVALUE 100


# TEMPLATE-only LINKs:
LINK DEFAULT
        ARROWSTYLE compact
        BWLABEL bits
        BANDWIDTH 1G
        OVERLIBWIDTH 750
        OVERLIBHEIGHT 350
        OVERLIBGRAPH zabbixdb:ifname:{link:this:node}:{link:this:iface}
        TARGET zabbixdb:ifname:{link:this:node}:{link:this:iface}
        SET node  xxx
        SET iface yyy

LINK VIRT
        TEMPLATE DEFAULT
        SET data_zabbixdb_key_in    ifHCInOctetsVirt
        SET data_zabbixdb_key_out   ifHCOutOctetsVirt
        SET data_zabbixdb_key_oper  ifOperStatusVirt
        SET data_zabbixdb_key_admin ifAdminStatusVirt

#

NODE node05103
     LABEL Node
     ICON images/Router.png
     POSITION 110 150

NODE node05107
    LABEL {node:this:text}
    LABELFONT 2 
    TARGET zabbixdb:text:IR03.BKK2:ifAlias[FastEthernet1/0]
    USESCALE none in
    ICON images/Host.png
    POSITION 110 340

LINK node05107-node05103
    #Note use %20 for space in OVERLIBGRAPH
    OVERLIBGRAPH zabbixdb:ifname:IR03.BKK2:FastEthernet1/0
    TARGET "zabbixdb:ifname:IR03.BKK2:FastEthernet1/0"
    NODES node05107 node05103
    BANDWIDTH 60M

#END