Els mòduls carregables ofereixen una opció orientada al rendiment per ampliar la funcionalitat de Zabbix.
Ja hi ha maneres d'ampliar la funcionalitat de Zabbix mitjançant:
system.run[]
.Funcionen molt bé, però tenen un inconvenient important, que és fork(). Zabbix ha de fer un nou procés cada vegada que gestiona una mètrica d'usuari, cosa que no és bona per al rendiment. Normalment no és un gran problema, però pot ser un problema seriós quan es monitoren sistemes incrustats, amb un gran nombre de paràmetres monitorats o scripts grans amb lògica complexa o temps d'inici llargs.
El suport per a mòduls carregables permet ampliar l'agent Zabbix, el servidor i el proxy sense sacrificar el rendiment.
Un mòdul carregable és bàsicament una biblioteca compartida emprada pel dimoni Zabbix i carregada a l'inici. La biblioteca ha de contindre algunes funcions, de manera que un procés Zabbix pugui detectar que el fitxer és realment un mòdul amb el qual pot carregar i treballar.
Els mòduls carregables tenen una sèrie d'avantatges. El gran rendiment i la capacitat d'implementar qualsevol lògica són molt importants, però potser l'avantatge més important és la capacitat de desenvolupar, emprar i compartir mòduls Zabbix. Contribueix a un manteniment fàcil i ajuda a oferir noves funcions de manera més fàcil i independent de la base de codi Zabbix.
La llicència i la distribució de mòduls en forma binària es regeix per la llicència GPL (els mòduls s'enllacen a Zabbix en temps d'execució i empren capçaleres Zabbix; actualment tot el codi Zabbix és sota llicència GPL). La compatibilitat binària no és garantida per Zabbix.
L'estabilitat de l'API és garantida durant un cicle LTS (Suport a llarg termini) de Zabbix (http://www.zabbix.com/life_cycle_and_release_policy). L'estabilitat de l'API Zabbix no és pas garantida (tècnicament és possible cridar funcions internes de Zabbix des d'un mòdul, però no hi ha cap garantia que aquests mòduls funcionin).
Perquè una biblioteca compartida es tracti com un mòdul Zabbix, ha d'implementar i exportar diverses funcions. Actualment hi ha sis funcions a l'API Zabbix, on només una és obligatòria i les altres cinc són opcionals.
L'única funció necessària és zbx_module_api_version():
Aquesta funció ha de retornar la versió del mòdul de l'API implementada per aquest mòdul i perquè el mòdul carregui aquesta versió ha de coincidir amb la versió del mòdul de l'API suportada per Zabbix. La versió del mòdul API admesa per Zabbix és ZBX_MODULE_API_VERSION. Per tant, aquesta funció ha de retornar aquesta constant. L'antiga constant ZBX_MODULES_API_VERSION_ONE que s'empra per a aquest propòsit ara s'estableix igual a ZBX_MODULE_API_VERSION per preservar la compatibilitat de les fonts, però aquest és un ús no recomanat.
Les funcions opcionals són zbx_module_init(), zbx_module_item_list(), zbx_module_item_timeout(), zbx_module_history _write_cbs() i zbx_module_uninit():
Aquesta funció hauria de fer la inicialització necessària per al mòdul (si cal). Si té èxit, hauria de retornar ZBX_MODULE_OK. En cas contrari hauria de retornar ZBX_MODULE_FAIL. En aquest darrer cas, Zabbix no engegarà pas.
Aquesta funció hauria de retornar una llista d'elements suportats pel mòdul. Cada element es defineix en una estructura ZBX_METRIC, veieu la secció següent per obtenir-ne més detalls. La llista acaba amb una estructura ZBX_METRIC amb el camp "clau" de NULL.
Si el mòdul exporta zbx_module_item_list(), Zabbix empra aquesta funció per especificar la configuració del temps d'espera al fitxer de configuració de Zabbix que ha de complir l'element que comprova implementat pel mòdul. Aquí, el paràmetre "temps d'espera" és en segons.
Aquesta funció hauria de retornar les funcions de devolució de crida que el servidor Zabbix emprarà per exportar l'historial de diferents tipus de dades. Les funcions de devolució de trucada es proporcionen com a camps d'estructura ZBX_HISTORY_WRITE_CBS, els camps poden ser NULL si el mòdul no té interès en cert tipus d'historial.
Aquesta funció hauria de realitzar la desinicialització necessària (si escau), com ara alliberar recursos assignats, tancar els descriptors de fitxers, etc.
Totes les funcions es criden una vegada a l'inici de Zabbix quan es carrega el mòdul, excepte zbx_module_uninit(), que es crida a l'aturada de Zabbix quan es descarrega el mòdul.
Cada element es defineix en una estructura ZBX_METRIC:
Aquí key és la clau de l'element (per exemple, "dummy.random"), flags és CF_HAVEPARAMS o 0 (segons si l'element admet paràmetres o no), function és una funció en C que implementa l'element (per exemple, "zbx_module_dummy_random"), i test_param és el llistat de paràmetres que s'emprarà quan l'agent Zabbix s'inicia amb l'opció "-p" (p. "1.1000", pot ser NULL). Un exemple de definició podria semblar-se a:
static ZBX_METRIC keys[] =
{
{ "dummy.random", CF_HAVEPARAMS, zbx_module_dummy_random, "1,1000" },
{ NULL }
}
Cada funció que implementa un element ha d'acceptar dos paràmetres de punter, el primer de tipus AGENT_REQUEST i el segon de tipus 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;
}
Aquestes funcions haurien de retornar SYSINFO_RET_OK, si el valor de l'element s'ha obtingut correctament. En cas contrari, haurien de retornar SYSINFO_RET_FAIL. Veieu el mòdul "dummy" d'exemple a continuació amb detalls sobre com obtindre informació d'AGENT_REQUEST i com configurar la informació a AGENT_RESULT.
L'exportació de l'historial mitjançant el mòdul ja no és compatible amb el proxy Zabbix des de Zabbix 4.0.0.
El mòdul pot especificar funcions per exportar dades de l'historial, de tipus: numèric (flotant), numèric (sense signe), caràcter, text i registre:
structure typedef
{
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 ;
Cadascun d'ells ha de prendre com a argument la matriu "history" d'elements "history_num". Segons el tipus de dades de l'historial que s'exportin, "history" és una matriu de les estructures següents, respectivament:
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;
Els processos de sincronització de l'historial del servidor Zabbix empraran les tornades de crida al final del procediment de sincronització de l'historial després que les dades s'escriguin a la base de dades de Zabbix i es desin a la memòria cau de valors.
En cas d'error intern al mòdul d'exportació de l'historial, es recomana escriure el mòdul de manera que no bloqui tot el monitoratge fins que es recuperi, sinó que esborri les dades i permeti que el servidor Zabbix continuï funcionant.
Actualment, els mòduls són pensats per ésser construïts a l'arbre de fonts de Zabbix, ja que el mòdul API depèn d'algunes estructures de dades definides a les capçaleres de Zabbix.
La capçalera més important per als mòduls carregables és include/module.h, que defineix aquestes estructures de dades. Una altra capçalera útil és include/sysinc.h, que realitza la inclusió de les capçaleres necessàries del sistema, permetent que include/module.h funcioni correctament.
Perquè s'incloguin include/module.h i include/sysinc.h, primer s'ha d'executar l'ordre ./configure (sense arguments) a l'arrel de l'arbre font de Zabbix. Això crearà el fitxer include/config.h, que es basa en include/sysinc.h. (Si teniu el codi font Zabbix d'un dipòsit de git, l'script ./configure encara no existeix i l'ordre ./bootstrap.sh s'ha d'executar primer per generar-lo.)
Tinguent en compte aquesta informació, tot és a punt per construir el mòdul. El mòdul ha d'incloure sysinc.h i module.h, i l'script de compilació ha de garantir que aquests dos fitxers siguin al camí d'inclusió. Veieu l'exemple de "mòdul fictici" a continuació per obtindre més detalls.
Una altra capçalera útil és include/log.h, que defineix la funció zabbix_log(), que es pot emprar amb finalitats de registre i depuració.
L'agent, el servidor i el proxy de Zabbix admeten dos paràmetres per gestionar els mòduls:
Per exemple, per ampliar l'agent Zabbix, podríem afegir els paràmetres següents:
LoadModulePath=/usr/local/lib/zabbix/agent/
LoadModule=mariadb.so
LoadModule=apache.so
LoadModule=kernel.so
LoadModule=/usr/local/lib/zabbix/dummy.so
A l'inici de l'agent, carregarà els mòduls mariadb.so, apache.so i kernel.so des del directori /usr/local/lib/zabbix/agent mentre que dummy.so es carregarà des de /usr/local/lib/zabbix. Fallarà si manca un mòdul, si hi ha permisos incorrectes o si una biblioteca compartida no és un mòdul Zabbix.
Els mòduls carregables són compatibles amb l'agent, el servidor i el proxy Zabbix. Per tant, el tipus d'element a la interfície Zabbix depèn d'on es carregui el mòdul. Si el mòdul es carrega a l'agent, el tipus d'element hauria d'ésser "agent Zabbix" o "agent Zabbix (actiu)". Si el mòdul es carrega al servidor o al proxy, el tipus d'element ha d'ésser "Verificació simple".
L'exportació de l'historial mitjançant mòduls Zabbix no necessita cap configuració frontal. Si el servidor carrega correctament el mòdul i proporciona la funció zbx_module_history_write_cbs() que retorna almenys una funció de devolució de crida no NULL, l'exportació de l'historial s'activarà automàticament.
Zabbix inclou un mòdul d'exemple escrit en llenguatge C. El mòdul es troba a src/modules/dummy:
alex@alex:~trunk/src/modules/dummy$ ls -l -rw-rw-r-- 1 alex alex 9019 Apr 24 17:54 dummy.c -rw-rw-r-- 1 alex alex 67 Apr 24 17:54 Makefile -rw-rw-r-- 1 alex alex 245 Apr 24 17:54 README
El mòdul està ben documentat, es pot emprar com a plantilla per als vostres mòduls.
Després d'executar l'ordre ./configure a l'arrel de l'arbre de fonts de Zabbix tal com es descriu anteriorment, executeu make per construir dummy.so.
/*
** 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;
}
El mòdul exporta tres nous elements:
dummy.ping
retorna sempre '1'dummy.echo[param1]
- retorna el primer paràmetre tal com és; per exemple, dummy.echo[ABC]
retornarà ABCdummy.random[param1, param2]
- retorna un nombre aleatori en l'interval de param1-param2; per exemple, dummy.random[1,1000000]
El suport de mòduls carregables només s'implementa per a la plataforma Unix. Això vol dir que no funciona amb els agents de Windows.
En alguns casos, un mòdul pot necessitar llegir els paràmetres de configuració relacionats amb el mòdul des de zabbix_agentd.conf. Això no s'admet actualment. Si necessiteu que el vostre mòdul empri determinats paràmetres de configuració, probablement haureu d'implementar l'anàlisi d'un fitxer de configuració específic del mòdul.