Files
qweZabbixDashboard/CLAUDE.md
2026-04-20 17:10:57 +02:00

4.2 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commands

npm install          # install dependencies
npm start            # run production server (port 3000)
npm run dev          # run with --watch (auto-restart on file changes)

There are no tests or linters configured.

Docker:

docker-compose up -d --build

Architecture

Single-process Node.js app. server.js acts as both an API proxy (keeping the Zabbix token server-side) and a static file host for the vanilla JS frontend in public/.

server.js          Express backend — Zabbix JSON-RPC proxy + REST API
public/
  index.html       Shell: header, view toggle, countries layout container, modal
  style.css        Light theme, CSS variables for hex sizing, hex grid layout
  app.js           All frontend logic — fetch, render, interactions
.env               Runtime config (gitignored)
docker-compose.yml Reads ZABBIX_TOKEN from env or .env

Config (env vars)

Variable Default Purpose
ZABBIX_URL https://monitor.stranto.com Zabbix instance
ZABBIX_TOKEN API bearer token (required)
CUSTOMER_TAG_VALUE QWE Zabbix host tag customer=<value> that identifies KFC hosts
COUNTRY_TAG country Zabbix host tag name used for country grouping
PORT 3000 HTTP port

Zabbix API conventions

  • Auth: Authorization: Bearer <token> header (Zabbix 6.4+ style — NOT the legacy auth body field)
  • All hosts are scoped by tag customer=QWE (operator 1 = equals)
  • Host groups use selectHostGroups / host.hostgroups — NOT the deprecated selectGroups / host.groups
  • Countries come from a country host tag (e.g. AT, SK)
  • Restaurants group by location host tag; device types group by host group, keyed as groupid__country
  • Severity 0 (Not classified) and 1 (Information) are treated as OK throughout
  • Acknowledged problems are excluded via withLastEventUnacknowledged: true
  • expandDescription: true on trigger.get resolves {HOST.NAME} and other macros in descriptions

Backend API endpoints

Endpoint Returns
GET /api/restaurants Array of { location, country, hostCount, problemCount, severity, problems[] }
GET /api/devices Same shape but grouped by host group; name instead of location
GET /api/stats { [countryCode]: { hostCount, itemCount, triggerCount } } — fetched in parallel with grid data
GET /api/detail?type=&id= Per-host problem detail for modal
GET /api/config { zabbixUrl, customerTagValue }
GET /api/health Zabbix connectivity check

Each problems[] entry: { description, priority, lastchange (unix seconds), hostName }, sorted by severity desc then time desc.

Frontend data flow

  1. Boot: fetch /api/config, then fetch grid data + /api/stats in parallel
  2. Items are grouped by country field and rendered as equal-width .country-col columns
  3. Each column renders: flag + country header → hex grid → problem list (locations with active problems)
  4. Single click → detail modal (/api/detail); double click → Zabbix Problems page in new tab (240ms timer separates the two)
  5. Auto-refresh every 30 seconds

Hex grid geometry

For equal gaps on all 6 sides, the hex dimensions must satisfy --hex-w = --hex-h × sin(60°) ≈ --hex-h × 0.866. The row vertical overlap is:

margin-top: calc(var(--hex-h) * -0.25 + var(--hex-gap) * 0.866);

Changing --hex-gap without updating margin-top will make diagonal gaps unequal. The even-row offset (margin-left on .hex-row.offset) is always (hex-w + hex-gap) / 2.

Zabbix Problems URL format (7.x)

Parameters use no filter_ prefix. Key params: show=1 (recent), evaltype=0, tags[N][tag/value/operator], groupids[], severities[]=2..5. The legacy filter_show, filter_tags, filter_set format does not work in Zabbix 7.x.

Severity mapping

Zabbix priority Label Colour
-1 (no problems / ack / info) OK green #2da44e
2 Warning amber #c69026
3 Average orange #e16f24
4 High red #d1242f
5 Disaster purple #8250df (pulses)