6 Laadbare modules

1 Overzicht

Laadmodules bieden een prestatiegerichte optie om de functionaliteit van Zabbix uit te breiden.

Er zijn al manieren om Zabbix-functionaliteit uit te breiden via:

Deze werken heel goed, maar hebben één groot nadeel, namelijk fork(). Zabbix moet elke keer dat het een gebruikersmeting verwerkt, een nieuw proces fork(). Dit is niet goed voor de prestaties. Normaal gesproken is dit geen groot probleem, maar het kan een serieus probleem zijn bij het monitoren van ingebedde systemen, bij grote aantallen gemonitorde parameters of bij zware scripts met complexe logica of een lange opstarttijd.

De ondersteuning van laadmodules biedt manieren om de Zabbix-agent, -server en -proxy uit te breiden zonder de prestaties op te offeren.

Een laadmodule is in feite een gedeelde bibliotheek die door het Zabbix-daemon wordt gebruikt en bij het opstarten wordt geladen. De bibliotheek moet bepaalde functies bevatten, zodat een Zabbix-proces kan detecteren dat het bestand inderdaad een module is waarmee het kan werken.

Laadmodules hebben verschillende voordelen. Geweldige prestaties en de mogelijkheid om elke logica te implementeren zijn zeer belangrijk, maar misschien wel het belangrijkste voordeel is de mogelijkheid om Zabbix-modules te ontwikkelen, te gebruiken en te delen. Dit draagt bij aan probleemloos onderhoud en helpt om nieuwe functionaliteit gemakkelijker en onafhankelijk van de Zabbix-kerncodebasis te leveren.

De licentie en distributie van modules in binaire vorm vallen onder de GPL-licentie (modules koppelen met Zabbix tijdens runtime en maken gebruik van Zabbix-headers; momenteel is de hele Zabbix-code gelicentieerd onder de GPL-licentie). Binaire compatibiliteit wordt niet gegarandeerd door Zabbix.

De stabiliteit van de module-API wordt gegarandeerd gedurende één Zabbix LTS (Long Term Support) release-cyclus. De stabiliteit van de Zabbix API wordt niet gegarandeerd (technisch gezien is het mogelijk om interne Zabbix-functies vanuit een module aan te roepen, maar er is geen garantie dat dergelijke modules zullen werken).

2 Module API

Om een gedeelde bibliotheek te laten behandelen als een Zabbix-module, moet deze verschillende functies implementeren en exporteren. Momenteel zijn er zes functies in de Zabbix-module-API, waarvan er slechts één verplicht is en de andere vijf optioneel zijn.

2.1 Verplichte interface

De enige verplichte functie is zbx_module_api_version():

int zbx_module_api_version(void);

Deze functie moet de API-versie retourneren die door deze module is geïmplementeerd. Om de module te kunnen laden, moet deze versie overeenkomen met de module-API-versie die door Zabbix wordt ondersteund. De versie van de module-API die wordt ondersteund door Zabbix is ZBX_MODULE_API_VERSION. Deze functie moet dus deze constante retourneren. De oude constante ZBX_MODULE_API_VERSION_ONE die voor dit doel werd gebruikt, is nu gedefinieerd als gelijk aan ZBX_MODULE_API_VERSION om de broncompatibiliteit te behouden, maar het gebruik ervan wordt niet aanbevolen.

2.2 Optionele interface

De optionele functies zijn zbx_module_init(), zbx_module_item_list(), zbx_module_item_timeout(), zbx_module_history_write_cbs() en zbx_module_uninit():

int zbx_module_init(void);

Deze functie moet de nodige initialisatie voor de module uitvoeren (indien van toepassing). Als dit succesvol is, moet het ZBX_MODULE_OK retourneren. Anders moet het ZBX_MODULE_FAIL retourneren. In het laatste geval zal Zabbix niet starten.

ZBX_METRIC  *zbx_module_item_list(void);

Deze functie moet een lijst retourneren van items die door de module worden ondersteund. Elk item is gedefinieerd in een ZBX_METRIC-structuur, zie de volgende sectie voor details. De lijst wordt beëindigd door een ZBX_METRIC-structuur met een "key"-veld van NULL.

void    zbx_module_item_timeout(int timeout);

Als de module zbx_module_item_list() exporteert, wordt deze functie door Zabbix gebruikt om de time-outinstellingen in het Zabbix-configuratiebestand op te geven die de itemcontroles geïmplementeerd door de module moeten volgen. Hier is het "timeout"-parameter in seconden.

ZBX_HISTORY_WRITE_CBS   zbx_module_history_write_cbs(void);

Deze functie moet teruggeefcallbackfuncties retourneren die door de Zabbix-server zullen worden gebruikt om geschiedenis van verschillende gegevenstypen te exporteren. Callbackfuncties worden geleverd als velden van de ZBX_HISTORY_WRITE_CBS-structuur; velden kunnen NULL zijn als de module niet geïnteresseerd is in de geschiedenis van bepaalde typen.

int zbx_module_uninit(void);

Deze functie moet de nodige oninitialisatie uitvoeren (indien van toepassing), zoals het vrijmaken van toegewezen bronnen, het sluiten van bestandsdescriptors, enzovoort.

Alle functies worden één keer aangeroepen bij het opstarten van Zabbix wanneer de module wordt geladen, met uitzondering van zbx_module_uninit(), die één keer wordt aangeroepen bij het afsluiten van Zabbix wanneer de module wordt gelost.

2.3 Items definiëren

Elk item wordt gedefinieerd in een ZBX_METRIC-structuur:

typedef struct
       {
           char        *key;
           unsigned    flags;
           int     (*function)();
           char        *test_param;
       }
       ZBX_METRIC;

Hier is key de item key (bijv. "dummy.random"), flags is ofwel CF_HAVEPARAMS of 0 (afhankelijk van of het item parameters accepteert of niet), function is een C-functie die het item implementeert (bijv. "zbx_module_dummy_random"), en test_param is de parameterlijst die wordt gebruikt wanneer de Zabbix-agent wordt gestart met de "-p" vlag (bijv. "1,1000", kan NULL zijn). Een voorbeelddefinitie kan er als volgt uitzien:

static ZBX_METRIC keys[] =
       {
           { "dummy.random", CF_HAVEPARAMS, zbx_module_dummy_random, "1,1000" },
           { NULL }
       }

Elke functie die een item implementeert, moet twee pointerparameters accepteren, waarvan de eerste van het type AGENT_REQUEST is en de tweede van het type AGENT_RESULT:

int zbx_module_dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result)
       {
           ...
       
           SET_UI64_RESULT(result, from + rand() % (to - from + 1));
       
           return SYSINFO_RET_OK;
       }

Deze functies moeten SYSINFO_RET_OK retourneren als de itemwaarde succesvol is verkregen. Anders moeten ze SYSINFO_RET_FAIL retourneren. Zie het voorbeeld "dummy" module hieronder voor details over hoe informatie uit AGENT_REQUEST kan worden verkregen en hoe informatie in AGENT_RESULT kan worden ingesteld.

2.4 Aanbieden van geschiedeniseksport-callbacks

Geschiedeniseksport via modules wordt niet langer ondersteund door de Zabbix-proxy sinds Zabbix 4.0.0.

Een module kan functies opgeven om geschiedenisgegevens per type te exporteren: Numeriek (float), Numeriek (unsigned), Karakter, Tekst en Log:

typedef struct
       {
           void    (*history_float_cb)(const ZBX_HISTORY_FLOAT *history, int history_num);
           void    (*history_integer_cb)(const ZBX_HISTORY_INTEGER *history, int history_num);
           void    (*history_string_cb)(const ZBX_HISTORY_STRING *history, int history_num);
           void    (*history_text_cb)(const ZBX_HISTORY_TEXT *history, int history_num);
           void    (*history_log_cb)(const ZBX_HISTORY_LOG *history, int history_num);
       }
       ZBX_HISTORY_WRITE_CBS;

Elk van deze functies moet "geschiedenis"-array van "history_num" elementen als argumenten aannemen. Afhankelijk van het type geschiedenisgegevens dat moet worden geëxporteerd, is "geschiedenis" respectievelijk een array van de volgende structuren:

typedef struct
       {
           zbx_uint64_t    itemid;
           int     clock;
           int     ns;
           double      value;
       }
       ZBX_HISTORY_FLOAT;
       
       typedef struct
       {
           zbx_uint64_t    itemid;
           int     clock;
           int     ns;
           zbx_uint64_t    value;
       }
       ZBX_HISTORY_INTEGER;
       
       typedef struct
       {
           zbx_uint64_t    itemid;
           int     clock;
           int     ns;
           const char  *value;
       }
       ZBX_HISTORY_STRING;
       
       typedef struct
       {
           zbx_uint64_t    itemid;
           int     clock;
           int     ns;
           const char  *value;
       }
       ZBX_HISTORY_TEXT;
       
       typedef struct
       {
           zbx_uint64_t    itemid;
           int     clock;
           int     ns;
           const char  *value;
           const char  *source;
           int     timestamp;
           int     logeventid;
           int     severity;
       }
       ZBX_HISTORY_LOG;

Deze callbackfuncties worden gebruikt door Zabbix-servergeschiedenissynchronisatieprocessen aan het einde van het geschiedenissynchronisatieproces, nadat de gegevens in de Zabbix-database zijn geschreven en in de waardecache zijn opgeslagen.

Bij een interne fout in de geschiedeniseksportmodule wordt aanbevolen om de module zodanig te schrijven dat deze geen volledige monitoring blokkeert tot het herstelt, maar in plaats daarvan gegevens negeert en Zabbix-server in staat stelt om door te blijven draaien.

2.5 Modules bouwen

Momenteel is het de bedoeling dat modules worden gebouwd binnen de Zabbix-broncode, omdat de module-API afhankelijk is van enkele gegevensstructuren die worden gedefinieerd in Zabbix-headers.

De belangrijkste header voor laadbare modules is include/module.h, die deze gegevensstructuren definieert. Andere noodzakelijke systeemheaders die include/module.h helpen om correct te werken, zijn stdlib.h en stdint.h.

Met deze informatie is alles klaar om de module te bouwen. De module moet stdlib.h, stdint.h en module.h bevatten, en het buildscript moet ervoor zorgen dat deze bestanden zich in het include-pad bevinden. Zie het onderstaande voorbeeld van de "dummy"-module voor meer details.

Een andere nuttige header is include/log.h, die de functie zabbix_log() definieert, die kan worden gebruikt voor loggen en debuggen.

3 Configuratieparameters

Zabbix-agent, -server en -proxy ondersteunen twee parameters om met modules om te gaan:

  • LoadModulePath - volledig pad naar de locatie van laadbare modules
  • LoadModule - module(s) om bij het opstarten te laden. De modules moeten zich bevinden in een map die is gespecificeerd door LoadModulePath of het pad moet voorafgaan aan de modulenaam. Als het voorafgaande pad absoluut is (begint met '/'), wordt LoadModulePath genegeerd. Het is toegestaan om meerdere LoadModule parameters op te nemen.

Bijvoorbeeld, om Zabbix-agent uit te breiden, zouden we de volgende parameters kunnen toevoegen:

LoadModulePath=/usr/local/lib/zabbix/agent/
       LoadModule=mariadb.so
       LoadModule=apache.so
       LoadModule=kernel.so
       LoadModule=/usr/local/lib/zabbix/dummy.so

Bij het starten van de agent laadt deze de mariadb.so, apache.so en kernel.so modules vanuit de map /usr/local/lib/zabbix/agent, terwijl dummy.so wordt geladen vanuit /usr/local/lib/zabbix. De agent zal niet kunnen starten als een module ontbreekt, in het geval van slechte machtigingen of als een gedeelde bibliotheek geen Zabbix-module is.

4 Front-endconfiguratie

Laadmodules worden ondersteund door Zabbix-agent, -server en -proxy. Daarom hangt het itemtype in de Zabbix-front-end af van waar de module is geladen. Als de module in de agent wordt geladen, moet het itemtype "Zabbix-agent" of "Zabbix-agent (actief)" zijn. Als de module in de server of proxy wordt geladen, moet het itemtype "Eenvoudige controle" zijn.

Geschiedenisexport via Zabbix-modules vereist geen front-endconfiguratie. Als de module succesvol wordt geladen door de server en de functie zbx_module_history_write_cbs() levert die ten minste één niet-NULL callbackfunctie op, dan wordt de geschiedenisexport automatisch ingeschakeld.

5 Voorbeeldmodule "dummy"

Zabbix bevat een voorbeeldmodule die is geschreven in de C-taal. De module is te vinden in src/modules/dummy:

alex@alex:~trunk/src/modules/dummy$ ls -l
       -rw-rw-r-- 1 alex alex 9019 24 apr 17:54 dummy.c
       -rw-rw-r-- 1 alex alex   67 24 apr 17:54 Makefile
       -rw-rw-r-- 1 alex alex  245 24 apr 17:54 README

De module is goed gedocumenteerd en kan worden gebruikt als sjabloon voor uw eigen modules.

Nadat ./configure is uitgevoerd in de hoofdmap van de Zabbix-bron zoals hierboven beschreven, voert u gewoon make uit om dummy.so te compileren.

/*
       ** Zabbix
       ** Copyright (C) 2001-2020 Zabbix SIA
       **
       ** This program is free software; you can redistribute it and/or modify
       ** it under the terms of the GNU General Public License as published by
       ** the Free Software Foundation; either version 2 of the License, or
       ** (at your option) any later version.
       **
       ** This program is distributed in the hope that it will be useful,
       ** but WITHOUT ANY WARRANTY; without even the implied warranty of
       ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
       ** GNU General Public License for more details.
       **
       ** You should have received a copy of the GNU General Public License
       ** along with this program; if not, write to the Free Software
       ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
       **/
       
       #include <stdlib.h>
       #include <string.h>
       #include <time.h>
       #include <stdint.h>
       
       #include "module.h"
       
       /* the variable keeps timeout setting for item processing */
       static int  item_timeout = 0;
       
       /* module SHOULD define internal functions as static and use a naming pattern different from Zabbix internal */
       /* symbols (zbx_*) and loadable module API functions (zbx_module_*) to avoid conflicts                       */
       static int  dummy_ping(AGENT_REQUEST *request, AGENT_RESULT *result);
       static int  dummy_echo(AGENT_REQUEST *request, AGENT_RESULT *result);
       static int  dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result);
       
       static ZBX_METRIC keys[] =
       /*  KEY         FLAG        FUNCTION    TEST PARAMETERS */
       {
           {"dummy.ping",      0,      dummy_ping, NULL},
           {"dummy.echo",      CF_HAVEPARAMS,  dummy_echo, "a message"},
           {"dummy.random",    CF_HAVEPARAMS,  dummy_random,   "1,1000"},
           {NULL}
       };
       
       /******************************************************************************
        *                                                                            *
        * Function: zbx_module_api_version                                           *
        *                                                                            *
        * Purpose: returns version number of the module interface                    *
        *                                                                            *
        * Return value: ZBX_MODULE_API_VERSION - version of module.h module is       *
        *               compiled with, in order to load module successfully Zabbix   *
        *               MUST be compiled with the same version of this header file   *
        *                                                                            *
        ******************************************************************************/
       int zbx_module_api_version(void)
       {
           return ZBX_MODULE_API_VERSION;
       }
       
       /******************************************************************************
        *                                                                            *
        * Function: zbx_module_item_timeout                                          *
        *                                                                            *
        * Purpose: set timeout value for processing of items                         *
        *                                                                            *
        * Parameters: timeout - timeout in seconds, 0 - no timeout set               *
        *                                                                            *
        ******************************************************************************/
       void    zbx_module_item_timeout(int timeout)
       {
           item_timeout = timeout;
       }
       
       /******************************************************************************
        *                                                                            *
        * Function: zbx_module_item_list                                             *
        *                                                                            *
        * Purpose: returns list of item keys supported by the module                 *
        *                                                                            *
        * Return value: list of item keys                                            *
        *                                                                            *
        ******************************************************************************/
       ZBX_METRIC  *zbx_module_item_list(void)
       {
           return keys;
       }
       
       static int  dummy_ping(AGENT_REQUEST *request, AGENT_RESULT *result)
       {
           SET_UI64_RESULT(result, 1);
       
           return SYSINFO_RET_OK;
       }
       
       static int  dummy_echo(AGENT_REQUEST *request, AGENT_RESULT *result)
       {
           char    *param;
       
           if (1 != request->nparam)
           {
               /* set optional error message */
               SET_MSG_RESULT(result, strdup("Invalid number of parameters."));
               return SYSINFO_RET_FAIL;
           }
       
           param = get_rparam(request, 0);
       
           SET_STR_RESULT(result, strdup(param));
       
           return SYSINFO_RET_OK;
       }
       
       /******************************************************************************
        *                                                                            *
        * Function: dummy_random                                                     *
        *                                                                            *
        * Purpose: a main entry point for processing of an item                      *
        *                                                                            *
        * Parameters: request - structure that contains item key and parameters      *
        *              request->key - item key without parameters                    *
        *              request->nparam - number of parameters                        *
        *              request->params[N-1] - pointers to item key parameters        *
        *              request->types[N-1] - item key parameters types:              *
        *                  REQUEST_PARAMETER_TYPE_UNDEFINED (key parameter is empty) *
        *                  REQUEST_PARAMETER_TYPE_ARRAY (array)                      *
        *                  REQUEST_PARAMETER_TYPE_STRING (quoted or unquoted string) *
        *                                                                            *
        *             result - structure that will contain result                    *
        *                                                                            *
        * Return value: SYSINFO_RET_FAIL - function failed, item will be marked      *
        *                                 as not supported by zabbix                 *
        *               SYSINFO_RET_OK - success                                     *
        *                                                                            *
        * Comment: get_rparam(request, N-1) can be used to get a pointer to the Nth  *
        *          parameter starting from 0 (first parameter). Make sure it exists  *
        *          by checking value of request->nparam.                             *
        *          In the same manner get_rparam_type(request, N-1) can be used to   *
        *          get a parameter type.                                             *
        *                                                                            *
        ******************************************************************************/
       static int  dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result)
       {
           char    *param1, *param2;
           int from, to;
       
           if (2 != request->nparam)
           {
               /* set optional error message */
               SET_MSG_RESULT(result, strdup("Invalid number of parameters."));
               return SYSINFO_RET_FAIL;
           }
       
           param1 = get_rparam(request, 0);
           param2 = get_rparam(request, 1);
       
           /* there is no strict validation of parameters and types for simplicity sake */
           from = atoi(param1);
           to = atoi(param2);
       
           if (from > to)
           {
               SET_MSG_RESULT(result, strdup("Invalid range specified."));
               return SYSINFO_RET_FAIL;
           }
       
           SET_UI64_RESULT(result, from + rand() % (to - from + 1));
       
           return SYSINFO_RET_OK;
       }
       
       /******************************************************************************
        *                                                                            *
        * Function: zbx_module_init                                                  *
        *                                                                            *
        * Purpose: the function is called on agent startup                           *
        *          It should be used to call any initialization routines             *
        *                                                                            *
        * Return value: ZBX_MODULE_OK - success                                      *
        *               ZBX_MODULE_FAIL - module initialization failed               *
        *                                                                            *
        * Comment: the module won't be loaded in case of ZBX_MODULE_FAIL             *
        *                                                                            *
        ******************************************************************************/
       int zbx_module_init(void)
       {
           /* initialization for dummy.random */
           srand(time(NULL));
       
           return ZBX_MODULE_OK;
       }
       
       /******************************************************************************
        *                                                                            *
        * Function: zbx_module_uninit                                                *
        *                                                                            *
        * Purpose: the function is called on agent shutdown                          *
        *          It should be used to cleanup used resources if there are any      *
        *                                                                            *
        * Return value: ZBX_MODULE_OK - success                                      *
        *               ZBX_MODULE_FAIL - function failed                            *
        *                                                                            *
        ******************************************************************************/
       int zbx_module_uninit(void)
       {
           return ZBX_MODULE_OK;
       }
       
       /******************************************************************************
        *                                                                            *
        * Functions: dummy_history_float_cb                                          *
        *            dummy_history_integer_cb                                        *
        *            dummy_history_string_cb                                         *
        *            dummy_history_text_cb                                           *
        *            dummy_history_log_cb                                            *
        *                                                                            *
        * Purpose: callback functions for storing historical data of types float,    *
        *          integer, string, text and log respectively in external storage    *
        *                                                                            *
        * Parameters: history     - array of historical data                         *
        *             history_num - number of elements in history array              *
        *                                                                            *
        ******************************************************************************/
       static void dummy_history_float_cb(const ZBX_HISTORY_FLOAT *history, int history_num)
       {
           int i;
       
           for (i = 0; i < history_num; i++)
           {
               /* do something with history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... */
           }
       }
       
       static void dummy_history_integer_cb(const ZBX_HISTORY_INTEGER *history, int history_num)
       {
           int i;
       
           for (i = 0; i < history_num; i++)
           {
               /* do something with history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... */
           }
       }
       
       static void dummy_history_string_cb(const ZBX_HISTORY_STRING *history, int history_num)
       {
           int i;
       
           for (i = 0; i < history_num; i++)
           {
               /* do something with history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... */
           }
       }
       
       static void dummy_history_text_cb(const ZBX_HISTORY_TEXT *history, int history_num)
       {
           int i;
       
           for (i = 0; i < history_num; i++)
           {
               /* do something with history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... */
           }
       }
       
       static void dummy_history_log_cb(const ZBX_HISTORY_LOG *history, int history_num)
       {
           int i;
       
           for (i = 0; i < history_num; i++)
           {
               /* do something with history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... */
           }
       }
       
       /******************************************************************************
        *                                                                            *
        * Function: zbx_module_history_write_cbs                                     *
        *                                                                            *
        * Purpose: returns a set of module functions Zabbix will call to export      *
        *          different types of historical data                                *
        *                                                                            *
        * Return value: structure with callback function pointers (can be NULL if    *
        *               module is not interested in data of certain types)           *
        *                                                                            *
        ******************************************************************************/
       ZBX_HISTORY_WRITE_CBS   zbx_module_history_write_cbs(void)
       {
           static ZBX_HISTORY_WRITE_CBS    dummy_callbacks =
           {
               dummy_history_float_cb,
               dummy_history_integer_cb,
               dummy_history_string_cb,
               dummy_history_text_cb,
               dummy_history_log_cb,
           };
       
           return dummy_callbacks;
       }

The module voert drie nieuwe items uit:

  • dummy.ping - retourneert altijd '1'
  • dummy.echo[param1] - retourneert de eerste parameter zoals deze is, bijvoorbeeld, dummy.echo[ABC] zal ABC retourneren
  • dummy.random[param1, param2] - retourneert een willekeurig getal binnen het bereik van param1-param2, bijvoorbeeld, dummy.random[1,1000000] zal een willekeurig getal tussen 1 en 1000000 retourneren

6 Beperkingen

Ondersteuning voor laadbare modules is alleen geïmplementeerd voor het Unix-platform. Dit betekent dat het niet werkt voor Windows-agents.

In sommige gevallen moet een module modulegerelateerde configuratieparameters lezen vanuit zabbix_agentd.conf. Dit wordt momenteel niet ondersteund. Als je wilt dat je module enkele configuratieparameters gebruikt, moet je waarschijnlijk het parsen van een modulespecifiek configuratiebestand implementeren.