Downloads Change Log Discord Telegram Url ✉️

Tutorial: Observing Zabbix events on a Geospatial Map


Mixed Grafana datasource

Create a mixed datasource:

Datasource 1: Mysql

Let's assume you keep coordinates, child/parent relations, and other important hosts information in a separate DB. Switch to 'Code' mode from 'Builder' and make a similar query:

SELECT switchId,
  sw.addr switchIp,
  sw.vendor_id vendorId,
  sw.topology_level topologyLevel, city, street, house, houseId, parentSwitchId,
  psw.addr parentSwitchIp,  
  ST_X(h.coordinate) longitude,
  ST_Y(h.coordinate) latitude,   description,

 FROM TCC.switch_a sw 
  LEFT JOIN TCC.switch_a psw ON = sw.parent_switch_id
  LEFT JOIN TCC.houses_new h ON = sw.house_id
  LEFT JOIN TCC.district_street ds ON = h.district_street
  LEFT JOIN TCC.streets_new s ON = ds.street_id
  LEFT JOIN TCC.districts d ON = ds.district_id
  LEFT JOIN TCC.cities c ON d.city_id =
 WHERE sw.is_deleted = 0 AND psw.is_deleted = 0 AND coordinate is not null
  AND = district_id
  AND = "$city" OR IF("$city"="All",1,0) = 1 
  AND sw.is_deleted = 0 AND psw.is_deleted = 0 AND coordinate is not null
  AND = district_id
  • This information could as well be fetched directly from Zabbix API or Zabbix Mysql DB, if you have coordinates and other info filled out in hosts inventory.

$city - is a sample Grafana variable you can set in dashboard options to group your points in every query. Its value options can be also automatically queried from the same datasource:

SELECT 'All' AS name;

Datasource 2: Zabbix Mysql DB

Get problem events with messages (acknowledges), severity metrics from Zabbix Mysql DB:

SELECT switchIp,
    clock as lastUpd, message,
    COALESCE(severity, 0) as severity, event

  SELECT as switchIp,
         WHEN triggers.value = 1 THEN 0
         ELSE 1
         END AS status
         , events.clock as clock, a.message AS message, p.severity as severity, as event
  FROM events
  JOIN triggers ON events.objectid = triggers.triggerid
  JOIN functions ON functions.triggerid = triggers.triggerid
  JOIN items ON items.itemid = functions.itemid
  JOIN hosts ON items.hostid = hosts.hostid
  JOIN problem p on events.eventid = p.eventid

  LEFT JOIN acknowledges a on events.eventid = a.eventid

  WHERE events.source = 0 AND p.severity > 2 AND triggers.value = 1


  SELECT as switchIp, history_uint.value as status, history_uint.clock as clock,
'' AS message, null AS severity, null AS event
  FROM hosts, items, history_uint
    hosts.hostid = items.hostid and
    items.itemid = history_uint.itemid and = 'ICMP ping' and
    history_uint.clock between  (unix_timestamp() - 90) and unix_timestamp()
) as combined_result
  • 'Union' operation is intended to fill in the information about hosts, that are not covered by the 'problem' table. We're going to need this in order to transform our Grafana mixed datasource with INNER JOIN by the location name (switchIp) field
  • 'Coalesce' for 'severity' sets null values to 0. It makes all severity values numeric, so that you can set color thresholds for these values.


Choose 'Join by field' mode: "INNER", and select location name field (switchIp)