Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!

Adminie… Czy znamy Twoje grzechy? ;-) Sprawdź!

Zabbix + grafana – część 7 – Parser JSONata

01 kwietnia 2026, 09:27 | Aktualności, Narzędzia, Teksty | 0 komentarzy
Ten tekst został przygotowany dla Zabbix 7.0, Postgresql 17.5 oraz Grafana 12.1.

Wstęp

W poprzednim artykule pokazaliśmy parser UQL — narzędzie, które pozwala w miarę bezboleśnie uporządkować odpowiedzi z API Zabbix i doprowadzić je do postaci akceptowalnej przez Grafanę (i ludzi). Dla wielu przypadków to w zupełności wystarcza i często jest najlepszym możliwym wyborem.

Są jednak sytuacje, w których odpowiedź z API zaczyna żyć własnym życiem: struktury robią się głębokie, warunki bardziej złożone, a liczba kroków w UQL zaczyna wyglądać podejrzanie. To właśnie w takich momentach pojawia się pytanie: „czy da się to zrobić inaczej?”.

Odpowiedzią jest JSONata — parser, który pozwala bardzo precyzyjnie pracować na strukturach JSON i wyciągać z nich dokładnie to, czego potrzebujemy, nawet jeśli wymaga to bardziej złożonej składni. 

Jeżeli nie masz jeszcze za sobą artykułów o konfiguracji pluginu Infinity oraz parserze UQL, warto najpierw sięgnąć do >pierwszego oraz >drugiego artykułu. W przeciwnym razie — przechodzimy dalej.

Zaczynamy!

Szybka powtórka

Na początek przypomnijmy sobie testowe środowisko:

Rysunek 1. Środowisko testowe wraz z oznaczoną komunikacją.

Dodatkowe założenia w tym przykładzie:

  • Nazwy hostów w Zabbix są zgodne z tymi skonfigurowanymi w systemie operacyjnym,
  • Obydwa hosty należą do grupy “Linux servers”,
  • Host “zabbix-7-0” jest dodatkowo w grupie “Zabbix servers”,
  • Istnieje już użytkownik “read-only” (opisany w >tym artykule) o nazwie grafana_api 

Dalej będziemy bazować na stworzonym dashboardzie Przykładowy dashboard 3, na którym aktualnie znajduje się pojedynczy panel z informacjami o niedostępności interfejsów na hostach:

Rysunek 2. Przykładowy dashboard 3 – aktualny stan

JSONata

JSONata to lekki i niezwykle elastyczny język do zapytań i transformacji danych JSON. W podstawowym użyciu może wydawać się prosty – pozwala w łatwy sposób wybrać pola z tablic (trochę jak JSONPath czy XPath dla XML-a.). Jednak pod tą pozorną prostotą kryje się ogromna moc – JSONata pozwala również na zaawansowane operacje: mapowanie, grupowanie, łączenie danych z różnych miejsc JSON-a i tworzenie kompletnie nowych struktur wyjściowych.

W przeciwieństwie do UQL, JSONata może działać zarówno w przeglądarce (frontend), jak i po stronie serwera Grafany (backend). To właśnie w wersji backendowej mamy dostęp do dodatkowych funkcji Grafany – takich jak alerting, cache’owanie wyników czy inne mechanizmy, które nie działają w trybie przeglądarki klienta. 

W praktyce oznacza to, że idealnie nadaje się do bardziej złożonych przekształceń, takich jak np. pobranie statusów agentów aktywnych, których brakowało nam w poprzednim artykule. 

Dlatego tym razem stworzymy listę z niedostępnymi interfejsami aktywnymi dla grupy Linux servers. W tym miejscu zastosujemy również uproszczenie z poprzedniego artykułu – znamy groupid naszej grupy, w naszym przykładzie to 2. By pokazać jak trudny jest to przykład, dodajmy testowo do naszego środowiska nowego hosta tylko_pasywne, który – jak sama nazwa wskazuje – posiada tylko interfejs Zabbix Agent w trybie pasywnym:

Rysunek 2. Przykładowy host tylko z interfejsem pasywnym

Wracamy więc do edycji dashboardu Przykładowy dashboard 3 i tworzymy nowy panel. Dla przypomnienia – konfiguracja zapytania wygląda podobnie jak w przypadku UQL:

  • Data source – zabbix-API-7-0
  • Type – JSON
  • Parser – tym razem wybieramy JSONATA
  • Source – URL
  • Format – tabela
  • Method – POST

URL – jeśli źródło danych jest skonfigurowane, pole można pozostawić puste

Rysunek 3. Podstawowa konfiguracja zapytania z wybranym parserem JSONata

W tym przykładzie wykorzystujemy ponownie funkcję host.get, ale w odróżnieniu od zapytania dla UQL zmieniamy zakres zwracanych danych. Chcemy pobrać:

  • host – nazwa hosta, jak poprzednio,
  • active_available – status dostępności interfejsu aktywnego (0 = Nieznany, 1 = Dostępny, 2 = Niedostępny).

Całe zapytanie wygląda następująco:

{
  "jsonrpc": "2.0",
  "method": "host.get",
  "params": {
    "groupids": 2,
    "output": ["host", "active_available"],
    "filter": { "status": 0 }
  },
  "id": 1
}

Pozostałe pola, takie jak jsonrpc, groupids, filter czy id, działają dokładnie tak samo jak w poprzednim artykule, więc nie będziemy ich powtarzać. 

Wystarczy skopiować powyższe zapytanie do sekcji Body panelu w Grafanie i pamiętać o ustawieniu Body Content Type na JSON – reszta konfiguracji pozostaje bez zmian.

Teraz pozostaje wyciągnąć z odpowiedzi tylko te pola, które nas interesują. W JSONacie można to zrobić naprawdę zwięźle — wystarczy jedno krótkie wyrażenie:

$.result.{ "host": host, "stan interfejsu aktywnego": active_available }

Co tu się dzieje?

$.result

Przechodzimy do tablicy result, którą Zabbix API zwraca przy każdym wywołaniu.

{ "host": host, "stan interfejsu aktywnego": active_available } 

Dla każdego elementu w tej tablicy budujemy nowy obiekt, zawierający wyłącznie dwa pola:

  • host – nazwa hosta,
  • stan interfejsu aktywnego – status interfejsu aktywnego (0 = nieznany, 1 = dostępny, 2 = niedostępny).

W efekcie JSONata przepisuje odpowiedź API na czystą, minimalną strukturę, idealną do wizualizacji w Grafanie — bez nadmiarowych pól, ręcznego filtrowania czy kombinowania.

Otrzymana tabela powinna wyglądać następująco:

Rysunek 4. Pierwsza próba pobrania statusu interfejsów aktywnych z grupy Linux Servers

Ale moment… dlaczego na liście pojawia się host tylko_pasywne? Przecież nie ma on aktywnych interfejsów.

Odpowiedź brzmi: tak to zostało zaprojektowane.

Metoda host.get zawsze zwraca pole active_available, niezależnie od tego, czy host faktycznie używa aktywnego trybu agenta. Zabbix w ten sposób nie weryfikuje istnienia „interfejsu aktywnego”. Pole te pokazuje ostatni stan interfejsu aktywnego. 

Jeżeli host nigdy nie posiadał sprawdzeń aktywnych, to wartość ta zawsze będzie ustawiona na 0. Natomiast posiadając hosta z działającymi sprawdzeniami aktywnym, jeżeli usuniemy wszystkie pozycje z typem Zabbix Agent (active) – z poziomu GUI Zabbix, host ten nie będzie posiadał już interfejsu aktywnego, jednak w zapytaniu API dla host.get pole active_available nadal będzie ustawione na 1 (ostatni znany stan). 

No dobrze, w takim razie jak Zabbix rozpoznaje, czy host faktycznie posiada interfejs aktywny?

W dużym uproszczeniu wykonuje następującą logikę: przegląda wszystkie pozycje przypisane do hosta i szuka tych, które mają typ Zabbix agent (active) oraz są włączone. Jeśli znajdzie choć jedną taką pozycje — traktuje host jako posiadający aktywny interfejs i raportuje faktyczny stan w active_available.

Mając już świadomość, jak działa pole active_available, możemy zmodyfikować nasze zapytanie API, aby sprawdzić nie tylko sam status interfejsu aktywnego, ale też uzyskać szczegóły dotyczące przypisanych pozycji. Dzięki temu będziemy mogli dokładniej ocenić, które hosty faktycznie mają aktywne sprawdzenia. Dodatkowo dla każdej pozycji będziemy pobierać również czas ostatniego odczytu – w ten sposób sprawdzimy, kiedy nastąpiło najświeższe sprawdzenie (zgodnie z znaną nam już wcześniej zasadą “tylko głupi by nie skorzystał”). Pozwoli to też na weryfikację opóźnień w przesyłaniu danych (kto nigdy nie zapomniał ustawić alarmu na brak odebranych danych niech pierwszy rzuci kamieniem).

Uwaga od Autora – przy bardzo dużych odpowiedziach API Grafana może działać wolniej i zużywać sporo zasobów. Jeśli planujesz obsługiwać setki tysięcy hostów, warto ograniczyć wyniki po stronie API, np. poprzez filtry, grupy lub limity.

Nasze zmodyfikowane zapytanie wygląda następująco:

{
  "jsonrpc": "2.0",
  "method": "host.get",
  "params": {
    "groupids": 2,
    "output": ["host", "active_available"],
    "selectItems": ["type", "lastclock", "status"],
    "filter": { "status": 0 }
  },
  "id": 1
}

Krótki opis poszczególnych elementów zapytania:

"groupids": 2,

Pobieramy hosty tylko z grupy Linux server (groupid = 2).

"output": ["host", "active_available"],

Pobieramy nazwę hosta oraz ostatni znany stan interfejsu aktywnego.

"selectItems": ["type", "lastclock", "status"], 

Prosimy API o listę pozycji przypisanych do hosta wraz z typem, czasem ostatniego odczytu i statusem włączony/wyłączony. Dzięki temu łatwo sprawdzimy, czy host posiada włączone pozycje typu Zabbix Agent (active).

"filter": { "status": 0 }

Ograniczamy wynik do hostów włączonych (status=0).

Dzięki tej modyfikacji uzyskamy nie tylko listę hostów i stan ich aktywnych interfejsów, ale również szczegółowe informacje o przypisanych itemach. Pozwala to na dokładniejszą analizę, które hosty mają aktywne sprawdzenia, bez ryzyka błędnej interpretacji pola active_available.

Na tym etapie powinniśmy otrzymać następujący wynik:

Rysunek 5. Początkowy wynik zapytania o interfejsy aktywne hostów

Mając już pełną odpowiedź API wraz z listą pozycji dla każdego hosta, możemy przetworzyć te dane w Grafanie, aby uzyskać czytelną i minimalną tabelę z interesującymi nas informacjami. W naszym przykładzie chcemy:

  1. Wybrać tylko te hosty, które mają włączone pozycji typu Zabbix Agent (active).
  2. Dla każdego hosta wyciągnąć jego nazwę (host) i status interfejsu aktywnego (active_available).
  3. Znaleźć ostatni czas odczytu (lastclock) spośród wszystkich pozycji typu Zabbix Agent (active) i zamienić go na milisekundy, aby Grafana mogła go poprawnie wyświetlać.

Do tego celu użyjemy już tylko trochę bardziej skomplikowanego kodu JSONata — taki, który pozwoli nam wszystko to zrobić bez dodatkowych transformat:

$map(
  $filter(result, function($h){
    $count($filter($h.items ? $h.items : [], function($it){
      $it.type = "7" and $it.status = "0"
    })) > 0
  }),
  function($h){
    {
      "host": $h.host,
      "stan interfejsu aktywnego": $h.active_available,
      "ostatni odczyt": (
        $vals := $filter($h.items ? $h.items : [], function($it){
          $it.type = "7" and $it.status = "0"
        }).lastclock;
        $nums := $map($vals, function($v){ $number($v) });
        $maxv := $max($nums);
        $maxv > 0 ? $maxv * 1000 : null
      )
    }
  }
)

No dobra, może nie jest to już taki „lekki” przykład, który da się ogarnąć jednym rzutem oka. Kod jest wyraźnie bardziej rozbudowany, dlatego rozbijmy go na mniejsze fragmenty i przejdźmy przez całość krok po kroku. 

Zaczynamy od głównej konstrukcji:

$map(... ,function($h){ ... }) 

Funkcja $map przechodzi po każdym elemencie wejściowej tablicy (pierwszy argument funkcji) i dla każdego z nich tworzy nowy obiekt wynikowy (drugi argument funkcji). Zmienna $h reprezentuje pojedynczego hosta i pozwala nam w czytelny sposób odwoływać się do jego pól w dalszej części wyrażenia. W praktyce oznacza to, że tworzymy jedną tabelę wynikową, w której każdy wiersz odpowiada jednemu hostowi. Źródłem danych dla $map jest tutaj funkcja filtrująca:

$filter(result, function($h){...})

W pierwszym argumencie funkcji $map posiadamy funkcję $filter, , aby zawęzić listę hostów tylko do tych, które spełniają określony warunek. Pierwszy argument result to nic innego jak domyślny obiekt który zawsze jest zwracany przez Zabbix API (czyli obiekty hostów z odpowiedzi API).

No dobrze, ale według jakiego kryterium filtrujemy hosty? Odpowiada za to poniższa funkcja:

function($h){
    $count($filter($h.items ? $h.items : [], function($it){
      $it.type = "7" and $it.status = "0"
    })) > 0
  }

Rozłóżmy ją na prostsze elementy.

$h.items ? $h.items : []

To proste zabezpieczenie: jeśli host posiada przypisane pozycje (items), pracujemy na tej tablicy; jeśli nie — podstawiamy pustą tablicę. Dzięki temu unikamy błędów przy przetwarzaniu hostów, które nie mają żadnych pozycji. Zabezpieczenie to wykorzystujemy potem w funkcji filtrującej:

$filter(<powyższe zabezpieczenie>, function($it){
      $it.type = "7" and $it.status = "0"
    })

W tej funkcji filtrujemy pozycje hosta, zostawiając wyłącznie te, które:

  • mają typ Zabbix Agent (active) (type = “7”),
  • są włączone (status = “0”).

W praktyce oznacza to, że interesują nas tylko włączone sprawdzenia typu Zabbix Agent (acive). Jeżeli interesuje Cię więcej informacji o obiekcie pozycj, to więcej szczegółów możesz przeczytać w >oficjalnej dokumentacji.

$count (<powyższy filtr>) > 0

Na końcu zliczamy, ile takich pozycji pozostało po filtracji. Jeżeli wynik jest większy od zera, host przechodzi dalej.

Efekt końcowy jest prosty: do głównej funkcji $map trafiają wyłącznie hosty, które mają co najmniej jedną włączoną pozycję typu Zabbix Agent (active). Dzięki temu dalsza analiza opiera się już tylko na hostach, które faktycznie korzystają z aktywnego trybu agenta, a nie na samym polu active_available.

Kiedy mamy już listę hostów ograniczoną wyłącznie do tych z aktywnymi sprawdzeniami, możemy przejść do budowania obiektów wynikowych:

function($h){
    {
      "host": $h.host,
      "stan interfejsu aktywnego": $h.active_available,
      "ostatni odczyt": (<na razie pomijamy>)
    }
  }

Dla każdego przefiltrowanego hosta tworzymy jeden obiekt zawierający trzy pola:

  • host — nazwa hosta,
  • stan interfejsu aktywnego — pole active_available zwracane przez API (czyli ostatni znany stan interfejsu aktywnego),
  • ostatni odczyt — czas ostatniego odczytu danych, obliczany dynamicznie..

Logika wyznaczania pola ostatni odczyt jest nieco bardziej złożona, dlatego również warto ją rozłożyć na etapy.

$vals := $filter($h.items ? $h.items : [], function($it){
          $it.type = "7" and $it.status = "0"
        }).lastclock;

Na początku ponownie filtrujemy listę itemów hosta, zostawiając wyłącznie włączone pozycje typu Zabbix Agent (active). Z każdego z nich pobieramy pole lastclock

W efekcie zmienna $vals zawiera tablicę wartości lastclock — na tym etapie są to jeszcze ciągi znaków. Jeżeli host ma kilka aktywnych pozycji, w tablicy znajdzie się kilka wartości.

$nums := $map($vals, function($v){ $number($v) });

Następnie konwertujemy wszystkie wartości na typ numeryczny za pomocą funkcji $number. Po tej operacji pracujemy już na tablicy liczb (a dokładniej – timestampów).

$maxv := $max($nums);

Z tak przygotowanej tablicy wybieramy największą wartość — odpowiada ona najświeższemu odczytowi spośród wszystkich aktywnych pozycji hosta.

$maxv > 0 ? $maxv * 1000 : null

Na końcu:

  • jeśli wartość $maxv istnieje i jest większa od zera, przeliczamy ją na milisekundy (Grafana operuje na czasie w tym formacie),
  • w przeciwnym wypadku zwracamy null — np. gdy pozycje istnieją, ale nie mają ustawionego lastclock.

W ten sposób dla każdego hosta otrzymujemy pojedynczy, jednoznaczny timestamp reprezentujący moment ostatniego faktycznego odczytu danych z aktywnego agenta — dokładnie to, czego potrzebujemy do dalszej analizy i wizualizacji.

Aby jeszcze lepiej zrozumieć działanie tego wyrażenia JSONata, przeanalizujmy przykładowe dane wejściowe zwrócone przez Zabbix API:

{
  "jsonrpc": "2.0",
  "result": [
    {
      "host": "web-01",
      "hostid": "10101",
      "active_available": "1",
      "items": [
        { "lastclock": "1765000000", "status": "0", "type": "7" },
        { "lastclock": "1764990000", "status": "0", "type": "7" },
        { "lastclock": "1764880000", "status": "1", "type": "7" },
        { "lastclock": "1764000000", "status": "0", "type": "0" }
      ]
    },
    {
      "host": "db-01",
      "hostid": "10102",
      "active_available": "0",
      "items": [
        { "lastclock": "1764800000", "status": "0", "type": "0" },
        { "lastclock": "1764700000", "status": "0", "type": "5" }
      ]
    },
    {
      "host": "app-01",
      "hostid": "10103",
      "active_available": "0",
      "items": [
        { "lastclock": "0", "status": "0", "type": "7" }
      ]
    }
  ],
  "id": 1
}

W dużym skrócie:

  • API zwróciło 3 hosty – web-01, db-01 oraz app-01
  • Host web-01  posiada 3 pozycje typu Zabbix Agent (active) (type=7), ale tylko dwie są włączone (status=0)
  • Host db-01 nie posiada żadnych pozycji typu Zabbix Agent (active), więc powinien zostać odrzucony na etapie filtrowania
  • Host app-01 posiada jedną pozycje typu Zabbix Agent (active), ale od dłuższego czasu nie zebrała żadnych danych i jej lastclock jest równy 0

Wracając do naszego kodu JSONata – pierwszym krokiem jest filtracja hostów. Zostawiamy tylko te, które posiadają co najmniej jedną włączoną pozycję typu Zabbix Agent (active), czyli:

  • type = 7
  • status = 0

Na tym etapie:

  • host db-01 zostaje pominięty ze względu na brak aktywnych pozycji typu Zabbix agent (active),
  • pola jsonrpc oraz id przestają nas interesować — pracujemy już wyłącznie na obiektach hostów.

Po tej filtracji otrzymujemy (wynik skrócono dla czytelności):

[
  {
    "host": "web-01",
    "hostid": "10101",
    "active_available": "1",
    "items": [<4 pozycje>]
  },
  {
    "host": "app-01",
    "hostid": "10103",
    "active_available": "0",
    "items": [<1 pozycja>]
  }
]

Następnie, zgodnie z główną funkcją $map, z każdego hosta tworzymy docelowy obiekt zawierający następujące pola:

  • host – nazwę hosta,
  • stan interfejsu aktywnego (pole active_available),
  • ostatni odczyt – zostanie obliczone.

Na tym etapie struktura wygląda następująco:

[
  {
    "host": "web-01",
    "stan interfejsu aktywnego": "1",
    "ostatni odczyt": <zostanie obliczone>
  },
  {
    "host": "app-01",
    "stan interfejsu aktywnego": "0",
    "ostatni odczyt": <zostanie obliczone>
  }
]

Ostatnim etapem jest obliczanie pola ostatni odczyt

Host web-01:

  1. Najpierw wybieramy tylko pozycje spełniające warunki type = 7 oraz status = 0:
[
  { "lastclock": "1765000000", "status": "0", "type": "7" },
  { "lastclock": "1764990000", "status": "0", "type": "7" }
]
  1. Następnie wyciągamy wartości lastclock:
["1765000000", "1764990000"]
  1. Zamieniamy je na liczby:
[1765000000, 1764990000]
  1. Wybieramy największy timestamp:
1765000000
  1. Przeliczamy go na milisekundy:
1765000000 * 1000 = 1765000000000

Host app-01:

  1. Host ten posiada tylko jedną włączoną pozycję typu Zabbix Agent (active);
[
  { "lastclock": "0", "status": "0", "type": "7" }
]
  1. Wyciągamy wartości lastclock:
["0"]
  1. Zmieniamy wartość na liczbę:
[0]
  1. Wartość maksymalna to 0, więc zgodnie z logiką JSONaty zwracamy:
null

Po pełnym przetworzeniu danych otrzymujemy:

[
  {
    "host": "web-01",
    "stan interfejsu aktywnego": "1",
    "ostatni odczyt": 1765000000000
  },
  {
    "host": "app-01",
    "stan interfejsu aktywnego": "0",
    "ostatni odczyt": null
  }
]

To dokładnie ta, minimalna i jednoznaczna struktura, którą możemy bezpośrednio wykorzystać w Grafanie do dalszej analizy i wizualizacji.

Skoro część teoretyczną mamy już za sobą, możemy przejść do praktyki. Wklejamy całe wyrażenie JSONata do pola Parsing option & Result fields.

Rysunek 6. Poprawiony wynik zapytania o interfejsy aktywne hostów

Od razu widać, że wszystko działa zgodnie z założeniami:

  • na liście nie pojawia się host tylko_pasywne,
  • dane są już przefiltrowane i ułożone dokładnie w takiej strukturze, jakiej potrzebujemy.

Na tym etapie pozostaje jedynie poprawić czytelność prezentacji danych w Grafanie.W okienku transformat dodajmy jedną o nazwie Convert field type. W jej konfiguracji w polu Field wybierzmy kolumnę ostatni odczyt – dzięki temu Grafana zacznie traktować tę kolumnę jako znacznik czasu i zamiast surowego timestampu wyświetli czytelną datę.

Rysunek 7. Transformacja traktującą kolumnę “ostatni odczyt” jako czas
  • Ponieważ chcemy prezentować dane w formie tabeli, w sekcji po prawej stronie, w polu Visualization wybieramy Table, dodatkowo dodajemy tytuł np. “Lista niedostępnych interfejsów aktywnych” oraz opis np. “Lista niedostępnych interfejsów aktywnych z grupy ‘Linux servers’”:
Rysunek 8. Podstawowe ustawienia tabeli
  • Aby dane były bardziej zrozumiałe dla osób, które nie znają szczegółów API Zabbixa, skorzystamy ponownie z mechanizmu nadpisań ustawień (opisywanego wcześniej przy parserze UQL). Na tym etapie warto dodać nadpisanie dla kolumny stan interfejsu aktywnego, czyli zamienić wartości liczbowe (0 / 1 / 2) na czytelne etykiety tekstowe (np. nieznany, dostępny, niedostępny) oraz dodać odpowiednie kolory (które zostaną wykorzystane do podkreślenia całego wiersza). Potraktuj to jako krótkie ćwiczenie — Ustawienia te konfigurujemy w taki sam sposób, jak w opisanych wcześniej przykładach z parserem UQL.
Rysunek 9. Całość ustawień nadpisania dla pola “stan interfejsu aktywnego”

Na koniec możemy dostosować wygląd całej tabeli do własnych preferencji. Dobrym pomysłem jest np. włączenie filtrowania kolumn poprzez opcję Table – Column filter. Pozwala to szybko zawęzić widok, np. tylko do hostów ze statusem nieznany lub niedostępny.

Koniec! Możemy wyjść z konfiguracji panelu (pamiętając o zapisaniu zmian), a na dashboardzie powinna pojawić się gotowa tabela z listą hostów i stanem ich aktywnych interfejsów. Jeśli tabela wydaje się zbyt wąska — warto po prostu poszerzyć kafelek panelu.

Rysunek 10. Wynik końcowy panelu “Lista niedostępnych interfejsów aktywnych”

Całość dashboardu Przykładowy dashboard 3 przedstawia się następująco:

Rysunek 11. Aktualny wygląd dashboardu “Przykładowy dashboard 3”

Dodatkowe porady

Kilka praktycznych uwag, które warto mieć z tyłu głowy podczas pracy z JSONatą:

  • JSONata nie jest językiem trywialnym, ale na szczęście został bardzo solidnie udokumentowany. Warto zaglądać do >oficjalnej dokumentacji  — dopiero tam widać, jak szerokie możliwości oferuje ten parser i jak daleko wykracza poza proste „wyciąganie pól z JSON-a”.
  • Jeżeli chcesz sprawdzić, jak zachowa się konkretne wyrażenie JSONata, bez uruchamiania Grafany, pomocne będzie narzędzie dostępne pod >tym linkiem. Umożliwia ono szybkie testy na surowych danych i obserwację wyniku „na żywo”.
  • Aktualna wersja JSONata (na moment pisania artykułu) to 2.1.0, jednak dotyczy ona implementacji w JavaScripcie. Grafana korzysta z implementacji napisanej w >języku GO, która nie jest w pełni zgodna z najnowszą wersją specyfikacji. W praktyce oznacza to, że nie wszystkie funkcje dostępne w dokumentacji będą działały w Grafanie. Najbezpieczniej jest traktować parser JSONata w Grafanie tak, jakby odpowiadał wersji około 1.5.4.
  • Filtruj jak najwcześniej – jeżeli wiesz, że interesuje Cię tylko podzbiór danych (np. hosty z aktywnymi itemami), odfiltruj je na samym początku. Każda kolejna operacja wykonana na mniejszym zbiorze jest czytelniejsza i tańsza obliczeniowo.

Podsumowanie

W tym artykule pokazaliśmy, jak przy użyciu parsera JSONata przetwarzać odpowiedzi API Zabbixa w Grafanie w sytuacjach, w których UQL zaczyna być niewystarczający. JSONata dobrze sprawdza się tam, gdzie logika przetwarzania danych jest bardziej złożona, a odpowiedź API wymaga realnej analizy, a nie tylko prostego filtrowania. Nie jest to parser najprostszy w czytaniu ani debugowaniu, ale w zamian daje dużą elastyczność i możliwość zamknięcia całej logiki w jednym miejscu.

W następnym artykule skupimy się na ostatnim parserze – JQ, który cieszy się dużą popularnością i jest szeroko stosowany do przetwarzania danych JSON w różnych środowiskach. Tym razem skupimy się na zbieraniu wszystkich błędnych pozycji (wraz z opisem błędu), i pogrupujemy je według rodzaju problemu.

Jeżeli artykuł okazał się wartościowy i pozwolił Ci spojrzeć na przetwarzanie danych z API Zabbixa w nowy sposób, możesz pokazać swoje uznanie, zostawiając autorowi >dobrą kawkę!

Jednocześnie zapraszamy na nasze nowe duże szkolenie Zabbix Expert z ponad 70% rabatem! Zapisy tutaj: https://zabbix.sekurak.pl

~ Albert Przybylski, zawodowo: Architekt ds. Monitoringu w firmie Aplitt, prywatnie: pełnoprawny fanatyk Zabbixa zasilany kawą

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

Odpowiedz