5 可加载模块

5.1 概述

可加载模块提供了一种关于Zabbix性能扩展的选项。

可以通过以下方式扩展Zabbix功能:

它们能运行的很好,但有一个主要的缺点,即fork()。 Zabbix必须在每次处理用户指标时分配一个新进程,这对于性能不利。这一般来讲不是严重的问题,但是在监控嵌入式系统,具有大量监控参数或具有复杂逻辑或启动时间很长的复杂脚本的情况下,这也许是一个严重的问题。

支持可加载模块提供了扩展Zabbix代理、服务器、代理服务器的方法,同时不牺牲性能。

可加载模块基本上是Zabbix守护程序使用的共享库,并在启动时加载。该库应包含某些功能,以便Zabbix进程可能会检测到该文件确实是可以加载和使用的模块。

可加载模块具有许多优点。卓越的性能和可实现任何逻辑的能力是非常重要的,但更最重要的优势是使用和共享Zabbix模块的开发能力。它有助于可靠的维护,并有助于更轻松、更独立于Zabbix核心代码库提供新功能。

5.2 模块API

为了将共享库按照Zabbix模块进行处理,它应该执行和导出多个功能。Zabbix模块API目前有六个功能,其中只有一个是强制性的,另外五个是可选的。

5.2.1 强制接口

唯一的强制功能是 zbx_module_api_version():

  1. int zbx_module_api_version(void);

此函数应该返回此模块的API版本,为了模块加载此版本必须匹配Zabbix支持的模块API版本。 Zabbix支持的模块API版本为ZBXMODULEAPIVERSION。 所以这个函数应该返回一个常数。用于此目的的旧常数ZBX_MODULEAPIVERSION_ONE现在被定义为等于ZBX_MODULEAPI_VERSION以保持兼容性,但不推荐使用。

5.2.2 可选接口

可选的接口是 zbx_module_init(), zbx_module_item_list(), zbx_module_item_timeout(), zbx_module_history_write_cbs()zbx_module_uninit():

  1. int zbx_module_init(void);

该功能应该对模块进行必要的初始化(如果有的话)。如果成功,应该返回ZBX_MODULE_OK。否则,应该返回ZBX_MODULE_FAIL。在后一种情况下,Zabbix将不会启动。

  1. ZBX_METRIC *zbx_module_item_list(void);

此功能应返回模块支持的监控项列表。每个监控项都是在ZBX_METRIC结构中定义的,有关详细信息,请参阅下面的部分。列表由ZBX_METRIC结构终止,“key”字段为NULL。

  1. void zbx_module_item_timeout(int timeout);

如果模块导出zbx_module_item_list(),那么Zabbix使用该函数来指定Zabbix配置文件中由模块实现的监控项检查应该遵循的超时设置。这里,“timeout”参数是以秒为单位。

  1. ZBX_HISTORY_WRITE_CBS zbx_module_history_write_cbs(void);

该函数应该返回回调函数Zabbix服务器或代理服务器将用于导出不同数据类型的历史记录。回调函数作为ZBX_HISTORY_WRITE_CBS结构的字段提供,如果模块对某种类型的历史不感兴趣,则字段可以为NULL。

  1. int zbx_module_uninit(void);

此功能应执行必要的反初始化(如果有的话),如释放分配的资源、关闭文件描述符等。

模块加载时、Zabbix启动时,所有功能除了zbx_module_uninit()都将被调用一次。在卸载模块时、Zabbix关闭时会调用一次。

5.2.3 定义监控项

每个监控项都在ZBX_METRIC结构中定义:

  1. typedef struct
  2. {
  3. char *key;
  4. unsigned flags;
  5. int (*function)();
  6. char *test_param;
  7. }
  8. ZBX_METRIC;

这里,key是监控项Key(例如,“dummy.random”),标志是CF_HAVEPARAMS或0(取决于监控项是否接受参数),function是实现该项目的C函数(例如,“zbx_module_dummy_random” ),test_param是使用“-p”标志启动Zabbix代理时使用的参数列表(例如,“1,1000”,可以为NULL)。 示例定义如下所示:

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

实现一个监控项的每个函数应该接受两个指针参数,第一个是AGENT_REQUEST类型,第二个是AGENT_RESULT类型的参数:

  1. int zbx_module_dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result)
  2. {
  3. ...
  4.  
  5. SET_UI64_RESULT(result, from + rand() % (to - from + 1));
  6.  
  7. return SYSINFO_RET_OK;
  8. }

如果监控项的值成功获取,这些函数应返回SYSINFO_RET_OK。否则,它们应该返回SYSINFO_RET_FAIL。有关如何从AGENT_REQUEST获取信息以及如何在AGENT_RESULT中设置信息的详细信息,请参阅下面的示例“dummy”模块。

5.2.4 提供历史记录导出回调

模块可以指定按类型导出历史数据的函数:Numeric(float),Numeric(unsigned),Character,Text和Log:

  1. typedef struct
  2. {
  3. void (*history_float_cb)(const ZBX_HISTORY_FLOAT *history, int history_num);
  4. void (*history_integer_cb)(const ZBX_HISTORY_INTEGER *history, int history_num);
  5. void (*history_string_cb)(const ZBX_HISTORY_STRING *history, int history_num);
  6. void (*history_text_cb)(const ZBX_HISTORY_TEXT *history, int history_num);
  7. void (*history_log_cb)(const ZBX_HISTORY_LOG *history, int history_num);
  8. }
  9. ZBX_HISTORY_WRITE_CBS;

每个人都应该以“history_num”元素的“history”数组为参数。 根据要导出的历史数据类型,“history”分别是以下结构的数组:

  1. typedef struct
  2. {
  3. zbx_uint64_t itemid;
  4. int clock;
  5. int ns;
  6. double value;
  7. }
  8. ZBX_HISTORY_FLOAT;
  9.  
  10. typedef struct
  11. {
  12. zbx_uint64_t itemid;
  13. int clock;
  14. int ns;
  15. zbx_uint64_t value;
  16. }
  17. ZBX_HISTORY_INTEGER;
  18.  
  19. typedef struct
  20. {
  21. zbx_uint64_t itemid;
  22. int clock;
  23. int ns;
  24. const char *value;
  25. }
  26. ZBX_HISTORY_STRING;
  27.  
  28. typedef struct
  29. {
  30. zbx_uint64_t itemid;
  31. int clock;
  32. int ns;
  33. const char *value;
  34. }
  35. ZBX_HISTORY_TEXT;
  36.  
  37. typedef struct
  38. {
  39. zbx_uint64_t itemid;
  40. int clock;
  41. int ns;
  42. const char *value;
  43. const char *source;
  44. int timestamp;
  45. int logeventid;
  46. int severity;
  47. }
  48. ZBX_HISTORY_LOG;

数据写入Zabbix数据库并保存在值缓存中之后,Zabbix服务器或代理服务器历史记录进程将在历史记录同步过程结束时使用回调。

只有原始值可用于通过代理模块导出。(自定义乘法器将不能应用,三角形将不被计算等)

5.2.5 构建模块

模块是要在Zabbix源代码树中构建的,因为模块API依赖于在Zabbix头文件中定义的一些数据结构。

可加载模块最重要的头是include/module.h,它定义了这些数据结构。另一个有用的头是include/sysinc.h,它执行包含必要的系统头,这本身就有助于include/module.h正常工作。

为了include/module.h和include/sysinc.h被包括在内,应该首先在.bbbix源代码树的根目录中运行./configure命令(不带参数)。这将创建include/config.h文件,其中包括/sysinc.h依赖。(如果你获得Zabbix源代码作为Subversion存储库检出,则./configure脚本不存在,应首先运行./bootstrap.sh命令生成它。)

在上述情况都考虑到之后,一切都为建立模块准备好了。该模块应包括sysinc.hmodule.h,构建脚本应确保这两个文件位于包含路径中。有关详细信息,请参见下面的“dummy”模块示例。

另一个有用的头是include/log.h,它定义了zabbix_log()函数,可用于记录和调试目的。

5.3 配置参数

Zabbix代理、服务器和代理服务器支持两种模块参数:

  • LoadModulePath – 可加载模块位置的全路径

  • LoadModule – 模块在启动时加载。模块必须位于LoadModulePath指定的目录中。允许包含多个LoadModule参数。

例如,要扩展Zabbix代理,我们可以添加以下参数:

  1. LoadModulePath=/usr/local/lib/zabbix/agent/
  2. LoadModule=mariadb.so
  3. LoadModule=apache.so
  4. LoadModule=kernel.so
  5. LoadModule=dummy.so

代理启动后,将从/usr/local/lib/zabbix/agent目录加载mariadb.so,apache.so,kernel.so和dummy.so模块。如果模块丢失、权限不匹配或共享库不是Zabbix模块,则会失败。

5.4 Web前端的配置

Zabbix代理、服务器和代理服务器支持可加载模块。 因此,Zabbix Web前端中的监控项类型取决于模块的加载位置。如果模块加载到代理中,则监控项类型应为“Zabbix代理”或“Zabbix代理(活动)”。 如果模块加载到服务器或代理服务器,则监控项类型应为“简单检查”。

通过Zabbix模块的历史导出不需要任何前端配置。如果模块由服务器或代理服务器成功加载,并提供返回至少一个非NULL回调函数的zbx_module_history_write_cbs()函数,那么历史导出将自动启用。

5.5 Dummy模块

Zabbix包含用C语言编写的示例模块。该模块位于src/modules/dummy下:

  1. [email protected]:~trunk/src/modules/dummy$ ls -l
  2. -rw-rw-r-- 1 alex alex 9019 Apr 24 17:54 dummy.c
  3. -rw-rw-r-- 1 alex alex 67 Apr 24 17:54 Makefile
  4. -rw-rw-r-- 1 alex alex 245 Apr 24 17:54 README

该模块有详细的文档,它可以用作你自己的模块的模板。

在./configure已经在Zabbix源代码树的根目录中运行,如上所述,只需运行make即可构建dummy.so

  1. /*
  2. ** Zabbix
  3. ** Copyright (C) 2001-2016 Zabbix SIA
  4. **
  5. ** This program is free software; you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation; either version 2 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. **/
  19.  
  20. #include "sysinc.h"
  21. #include "module.h"
  22.  
  23. /* the variable keeps timeout setting for item processing */
  24. static int item_timeout = 0;
  25.  
  26. /* module SHOULD define internal functions as static and use a naming pattern different from Zabbix internal */
  27. /* symbols (zbx_*) and loadable module API functions (zbx_module_*) to avoid conflicts */
  28. static int dummy_ping(AGENT_REQUEST *request, AGENT_RESULT *result);
  29. static int dummy_echo(AGENT_REQUEST *request, AGENT_RESULT *result);
  30. static int dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result);
  31.  
  32. static ZBX_METRIC keys[] =
  33. /* KEY FLAG FUNCTION TEST PARAMETERS */
  34. {
  35. {"dummy.ping", 0, dummy_ping, NULL},
  36. {"dummy.echo", CF_HAVEPARAMS, dummy_echo, "a message"},
  37. {"dummy.random", CF_HAVEPARAMS, dummy_random, "1,1000"},
  38. {NULL}
  39. };
  40.  
  41. /******************************************************************************
  42. * *
  43. * Function: zbx_module_api_version *
  44. * *
  45. * Purpose: returns version number of the module interface *
  46. * *
  47. * Return value: ZBX_MODULE_API_VERSION - version of module.h module is *
  48. * compiled with, in order to load module successfully Zabbix *
  49. * MUST be compiled with the same version of this header file *
  50. * *
  51. ******************************************************************************/
  52. int zbx_module_api_version(void)
  53. {
  54. return ZBX_MODULE_API_VERSION;
  55. }
  56.  
  57. /******************************************************************************
  58. * *
  59. * Function: zbx_module_item_timeout *
  60. * *
  61. * Purpose: set timeout value for processing of items *
  62. * *
  63. * Parameters: timeout - timeout in seconds, 0 - no timeout set *
  64. * *
  65. ******************************************************************************/
  66. void zbx_module_item_timeout(int timeout)
  67. {
  68. item_timeout = timeout;
  69. }
  70.  
  71. /******************************************************************************
  72. * *
  73. * Function: zbx_module_item_list *
  74. * *
  75. * Purpose: returns list of item keys supported by the module *
  76. * *
  77. * Return value: list of item keys *
  78. * *
  79. ******************************************************************************/
  80. ZBX_METRIC *zbx_module_item_list(void)
  81. {
  82. return keys;
  83. }
  84.  
  85. static int dummy_ping(AGENT_REQUEST *request, AGENT_RESULT *result)
  86. {
  87. SET_UI64_RESULT(result, 1);
  88.  
  89. return SYSINFO_RET_OK;
  90. }
  91.  
  92. static int dummy_echo(AGENT_REQUEST *request, AGENT_RESULT *result)
  93. {
  94. char *param;
  95.  
  96. if (1 != request->nparam)
  97. {
  98. /* set optional error message */
  99. SET_MSG_RESULT(result, strdup("Invalid number of parameters."));
  100. return SYSINFO_RET_FAIL;
  101. }
  102.  
  103. param = get_rparam(request, 0);
  104.  
  105. SET_STR_RESULT(result, strdup(param));
  106.  
  107. return SYSINFO_RET_OK;
  108. }
  109.  
  110. /******************************************************************************
  111. * *
  112. * Function: dummy_random *
  113. * *
  114. * Purpose: a main entry point for processing of an item *
  115. * *
  116. * Parameters: request - structure that contains item key and parameters *
  117. * request->key - item key without parameters *
  118. * request->nparam - number of parameters *
  119. * request->timeout - processing should not take longer than *
  120. * this number of seconds *
  121. * request->params[N-1] - pointers to item key parameters *
  122. * *
  123. * result - structure that will contain result *
  124. * *
  125. * Return value: SYSINFO_RET_FAIL - function failed, item will be marked *
  126. * as not supported by zabbix *
  127. * SYSINFO_RET_OK - success *
  128. * *
  129. * Comment: get_rparam(request, N-1) can be used to get a pointer to the Nth *
  130. * parameter starting from 0 (first parameter). Make sure it exists *
  131. * by checking value of request->nparam. *
  132. * *
  133. ******************************************************************************/
  134. static int dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result)
  135. {
  136. char *param1, *param2;
  137. int from, to;
  138.  
  139. if (2 != request->nparam)
  140. {
  141. /* set optional error message */
  142. SET_MSG_RESULT(result, strdup("Invalid number of parameters."));
  143. return SYSINFO_RET_FAIL;
  144. }
  145.  
  146. param1 = get_rparam(request, 0);
  147. param2 = get_rparam(request, 1);
  148.  
  149. /* there is no strict validation of parameters for simplicity sake */
  150. from = atoi(param1);
  151. to = atoi(param2);
  152.  
  153. if (from > to)
  154. {
  155. SET_MSG_RESULT(result, strdup("Invalid range specified."));
  156. return SYSINFO_RET_FAIL;
  157. }
  158.  
  159. SET_UI64_RESULT(result, from + rand() % (to - from + 1));
  160.  
  161. return SYSINFO_RET_OK;
  162. }
  163.  
  164. /******************************************************************************
  165. * *
  166. * Function: zbx_module_init *
  167. * *
  168. * Purpose: the function is called on agent startup *
  169. * It should be used to call any initialization routines *
  170. * *
  171. * Return value: ZBX_MODULE_OK - success *
  172. * ZBX_MODULE_FAIL - module initialization failed *
  173. * *
  174. * Comment: the module won't be loaded in case of ZBX_MODULE_FAIL *
  175. * *
  176. ******************************************************************************/
  177. int zbx_module_init(void)
  178. {
  179. /* initialization for dummy.random */
  180. srand(time(NULL));
  181.  
  182. return ZBX_MODULE_OK;
  183. }
  184.  
  185. /******************************************************************************
  186. * *
  187. * Function: zbx_module_uninit *
  188. * *
  189. * Purpose: the function is called on agent shutdown *
  190. * It should be used to cleanup used resources if there are any *
  191. * *
  192. * Return value: ZBX_MODULE_OK - success *
  193. * ZBX_MODULE_FAIL - function failed *
  194. * *
  195. ******************************************************************************/
  196. int zbx_module_uninit(void)
  197. {
  198. return ZBX_MODULE_OK;
  199. }
  200.  
  201. /******************************************************************************
  202. * *
  203. * Functions: dummy_history_float_cb *
  204. * dummy_history_integer_cb *
  205. * dummy_history_string_cb *
  206. * dummy_history_text_cb *
  207. * dummy_history_log_cb *
  208. * *
  209. * Purpose: callback functions for storing historical data of types float, *
  210. * integer, string, text and log respectively in external storage *
  211. * *
  212. * Parameters: history - array of historical data *
  213. * history_num - number of elements in history array *
  214. * *
  215. ******************************************************************************/
  216. static void dummy_history_float_cb(const ZBX_HISTORY_FLOAT *history, int history_num)
  217. {
  218. int i;
  219.  
  220. for (i = 0; i < history_num; i++)
  221. {
  222. /* do something with history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... */
  223. }
  224. }
  225.  
  226. static void dummy_history_integer_cb(const ZBX_HISTORY_INTEGER *history, int history_num)
  227. {
  228. int i;
  229.  
  230. for (i = 0; i < history_num; i++)
  231. {
  232. /* do something with history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... */
  233. }
  234. }
  235.  
  236. static void dummy_history_string_cb(const ZBX_HISTORY_STRING *history, int history_num)
  237. {
  238. int i;
  239.  
  240. for (i = 0; i < history_num; i++)
  241. {
  242. /* do something with history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... */
  243. }
  244. }
  245.  
  246. static void dummy_history_text_cb(const ZBX_HISTORY_TEXT *history, int history_num)
  247. {
  248. int i;
  249.  
  250. for (i = 0; i < history_num; i++)
  251. {
  252. /* do something with history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... */
  253. }
  254. }
  255.  
  256. static void dummy_history_log_cb(const ZBX_HISTORY_LOG *history, int history_num)
  257. {
  258. int i;
  259.  
  260. for (i = 0; i < history_num; i++)
  261. {
  262. /* do something with history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... */
  263. }
  264. }
  265.  
  266. /******************************************************************************
  267. * *
  268. * Function: zbx_module_history_write_cbs *
  269. * *
  270. * Purpose: returns a set of module functions Zabbix will call to export *
  271. * different types of historical data *
  272. * *
  273. * Return value: structure with callback function pointers (can be NULL if *
  274. * module is not interested in data of certain types) *
  275. * *
  276. ******************************************************************************/
  277. ZBX_HISTORY_WRITE_CBS zbx_module_history_write_cbs(void)
  278. {
  279. static ZBX_HISTORY_WRITE_CBS dummy_callbacks =
  280. {
  281. dummy_history_float_cb,
  282. dummy_history_integer_cb,
  283. dummy_history_string_cb,
  284. dummy_history_text_cb,
  285. dummy_history_log_cb,
  286. };
  287.  
  288. return dummy_callbacks;
  289. }

该模块导出三个新监控项:

  • dummy.ping - 总是返回 '1'

  • dummy.echo[param1] - 返回第一个参数,例如dummy.echo[ABC]将返回ABC

  • dummy.random[param1, param2] - 返回param1-param2范围内的随机数, 例如, dummy.random[1,1000000]

5.6 限制

仅针对Unix平台实现可加载模块的支持。这意味着它不适用于Windows代理。

在某些情况下,模块可能需要从zabbix_agentd.conf读取相关的配置参数。如果你需要使用模块来使用某些配置参数,那么你应该可以实现对特定于模块的配置文件的解析。