可加载模块为扩展Zabbix功能提供了一种注重性能的选择。
目前已有多种扩展Zabbix功能的方式:
user parameters(agent指标)
external checks (无agent监控)
system.run[]
Zabbix [agent
item](/manual/config/items/itemtypes/zabbix_agent).
They work very well, but have one major drawback, namely fork(). Zabbix has to fork a new process every time it handles a user metric, which is not good for performance. It is not a big deal normally, however it could be a serious issue when monitoring embedded systems, having a large number of monitored parameters or heavy scripts with complex logic or long startup time.
Support of loadable modules offers ways for extending Zabbix agent, server and proxy without sacrificing performance.
A loadable module is basically a shared library used by Zabbix daemon and loaded on startup. The library should contain certain functions, so that a Zabbix process may detect that the file is indeed a module it can load and work with.
Loadable modules have a number of benefits. Great performance and ability to implement any logic are very important, but perhaps the most important advantage is the ability to develop, use and share Zabbix modules. It contributes to trouble-free maintenance and helps to deliver new functionality easier and independently of the Zabbix core code base.
Module licensing and distribution in binary form is governed by the GPL license (modules are linking with Zabbix in runtime and are using Zabbix headers; currently the whole Zabbix code is licensed under GPL license). Binary compatibility is not guaranteed by Zabbix.
Module API stability is guaranteed during one Zabbix LTS (Long Term Support) release 周期。Zabbix API的稳定性无法保证(技术上可以从模块调用Zabbix内部函数,但不能保证此类模块能正常工作)。
为了使一个共享库被识别为Zabbix模块,它需要实现并export若干函数。当前Zabbix模块API中共有六个函数,其中仅有一个是强制性的,其余五个均为可选。
唯一必需的函数是zbx_module_api_version():
此函数应返回该模块实现的API version 为了使模块能够加载 该version必须与Zabbix支持的模块API version相匹配 Zabbix支持的模块API版本是ZBX_MODULE_API_VERSION 因此该函数应返回此常量 旧常量ZBX_MODULE_API_VERSION_ONE用于此目的 现在定义为等于ZBX_MODULE_API_VERSION以保持源代码兼容性 但不建议使用它
可选函数包括 zbx_module_init(), zbx_module_item_list(), zbx_module_item_timeout(), zbx_module_history_write_cbs() 和 zbx_module_uninit():
该函数应执行模块所需的初始化操作 (如有必要). 若成功则返回 ZBX_MODULE_OK. 否则 应返回 ZBX_MODULE_FAIL. 后者情况下Zabbix将不会 启动.
该函数应返回模块支持的监控项列表. 每个监控项通过ZBX_METRIC结构体定义, 详见下文 说明. 列表以key字段为NULL的ZBX_METRIC结构体 作为结束标识.
若模块导出zbx_module_item_list()函数, 则Zabbix会通过此函数 指定配置文件中file的超时设置, 模块实现的 监控项检查需遵守该设置. 此处 "timeout"参数单位为秒.
该函数应返回Zabbix server将用于export 不同类型历史数据的回调函数. 回调函数通过 ZBX_HISTORY_WRITE_CBS结构体的字段提供, 若模块 不关注某类历史数据则对应字段可为NULL.
该函数应执行必要的反初始化操作(如有), 如 释放分配的资源, 关闭file描述符等.
除zbx_module_uninit()外, 所有函数均在Zabbix启动时 模块加载时调用一次; zbx_module_uninit()则在 Zabbix关闭时模块卸载时调用一次.
每个监控项都在ZBX_METRIC结构中定义:
其中,key是监控项键(例如"dummy.random"),flags可以是CF_HAVEPARAMS或0(取决于监控项是否接受参数),function是实现监控项的C函数(例如"zbx_module_dummy_random"),而test_param是当Zabbix agent以"-p"flag启动时使用的参数列表(例如"1,1000",可以为NULL)。示例定义可能如下所示:
static ZBX_METRIC keys[] =
{
{ "dummy.random", CF_HAVEPARAMS, zbx_module_dummy_random, "1,1000" },
{ NULL }
}
每个实现监控项的函数应接受两个指针参数,第一个是Agent_REQUEST类型,第二个是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;
}
如果成功获取监控项值,这些函数应返回SYSINFO_RET_OK。否则,应返回SYSINFO_RET_FAIL。有关如何从Agent_REQUEST获取信息以及如何在Agent_RESULT中设置信息的详细信息,请参阅下面的"dummy"模块示例。
自Zabbix 4.0.0起,Zabbix proxy不再支持通过模块export历史数据
模块可以按类型指定export历史数据的函数:数值型 (float)、无符号数值型、字符型、文本型和日志型:
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;
每个函数都应接收"history_num"个元素的"history"array作为 参数。根据要导出的历史数据类型,"history"分别是 以下结构的array:
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;
这些回调函数将在历史同步过程结束时,由Zabbix server历史同步器进程 使用,此时数据已写入Zabbix数据库并保存在value cache中。
如果历史export模块出现内部错误,建议模块编写时应确保不会阻塞整个监控系统直到恢复,而是丢弃数据并允许Zabbix server继续运行。
模块目前需要在Zabbix源代码树内部构建, 因为模块API依赖于Zabbix头文件中定义的某些数据结构。
对于可加载模块最重要的头文件是include/module.h, 它定义了这些数据结构。其他帮助include/module.h正常工作的必要系统头文件包括stdlib.h和stdint.h。
基于这些信息,模块构建的准备工作已经就绪。模块应包含stdlib.h、stdint.h和module.h,构建脚本需确保这些文件位于包含路径中。详情请参阅下方"dummy"模块示例。
另一个有用的头文件是include/log.h,它定义了zabbix_log()函数,可用于日志记录和调试目的。
Zabbix agent、服务器和proxy支持两种 parameters来处理 模块:
LoadModulePath – 可加载模块所在位置的完整路径
LoadModule – 启动时要加载的模块。这些模块必须
located in a directory specified by LoadModulePath or the path must precede the module name. If the preceding path is absolute (starts with '/') then LoadModulePath is ignored. It is allowed to include multiple LoadModule parameters.
例如,要扩展Zabbix agent,我们可以添加以下 参数:
LoadModulePath=/usr/local/lib/zabbix/agent/
LoadModule=mariadb.so
LoadModule=apache.so
LoadModule=kernel.so
LoadModule=/usr/local/lib/zabbix/dummy.so
在agent启动时,它将从/usr/local/lib/zabbix/agent目录加载mariadb.so、apache.so和kernel.so 模块,而dummy.so 将从/usr/local/lib/zabbix加载。如果模块缺失、权限错误或共享库不是 Zabbix模块,agent将无法启动。
可加载模块由Zabbix agent、服务器和proxy支持。 因此,Zabbix前端中的监控项类型取决于模块加载位置。 若模块加载至agent,则监控项类型应为"Zabbix agent"或"Zabbix agent (active)"。 若模块加载至server 或 proxy,则监控项类型应为"Simple check"。
通过Zabbix模块实现的export历史功能无需任何前端配置。 若模块被服务器成功加载且提供zbx_module_history_write_cbs()函数, 并返回至少一个非NULL回调函数,则export历史功能将自动启用。
Zabbix包含一个用C语言编写的示例模块。该模块位于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
该模块文档完善,可作为您开发自定义模块的模板。
按照上述说明在Zabbix源码根目录执行./configurerun后,只需runmake命令即可构建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;
}
该模块导出三个新的监控项:
dummy.ping
- 始终返回'1'dummy.echo[param1]
- 原样返回第一个参数,例如dummy.echo[ABC]
将返回ABCdummy.random[param1, param2]
- 返回param1-param2范围内的随机数,例如dummy.random[1,1000000]
可加载模块的支持仅针对Unix平台实现。 这意味着它不适用于Windows agents。
在某些情况下,模块可能需要从zabbix_agentd.conf读取与模块相关的配置 参数。目前不支持此功能。如果 您需要模块使用某些配置参数,您应该 实现模块特定配置file的解析。