Áú»¢¶Ä²©

5 M¨®dulos carreg¨¢veis

5.1 Vis?o geral

Os m¨®dulos carreg¨¢veis s?o uma op??o para estender as funcionalidades do Áú»¢¶Ä²© com o foco em alta performance.

Existem outras formas de se estender as funcionalidades do Áú»¢¶Ä²©:

Todas estas formas funcionam muito bem, mas tem um problema intr¨ªnseco, normalmente conhecido como 'fork()'. O Áú»¢¶Ä²© precisa direcionar um de seus processos para gerenciar m¨¦trica que se quer obter, toda vez que ¨¦ necess¨¢rio coleta-la, e isso n?o ¨¦ uma boa op??o para performance. Normalmente isso n?o ¨¦ um grande problema, mas se formos fazer uma monitora??o s¨¦ria de sistemas cr¨ªticos, com uma grande quantidade de par?metros ou scripts muito complexos / longos de se executar... isso deixa de ser verdade.

O Áú»¢¶Ä²© 2.2 inovou ao adicionar o suporte a m¨®dulos carreg¨¢veis para estender as funcionalidades do Áú»¢¶Ä²© Agent, Server e Proxy sem perder performance.

Um m¨®dulo carreg¨¢vel ¨¦ basicamente uma biblioteca compartilhada utilizada por um processo do Áú»¢¶Ä²© e carregada junto com o mesmo. A biblioteca precisar¨¢ ter determinadas fun??es para que o Áú»¢¶Ä²© possa detecta-las no arquivo e saber como trabalhar com ela.

Os m¨®dulos carreg¨¢veis tem uma grande quantidade de benef¨ªcios. O aumento de performance e a habilidade de se aplicar qualquer l¨®gica ¨¦ muito importante, mas talvez o maior ganho seja a habilidade de desenvolver, usar e compartilhar os m¨®dulos. Isso auxilia nos processos de manuten??o livre de problemas e auxilia a entregar novas funcionalidades de forma f¨¢cil e independente do c¨®digo base do Áú»¢¶Ä²©.

5.2 API de m¨®dulos

Para que uma biblioteca compartilhada possa ser tratada como um m¨®dulo do Áú»¢¶Ä²©, ¨¦ muito importante que ela implemente e exporte determinadas fun??es. Atualmente s?o cinco as fun??es da API de m¨®dulos do Áú»¢¶Ä²©, sendo duas obrigat¨®rias e as outras tr¨ºs opcionais.

5.2.1 Interfaces obrigat¨®rias

As duas fun??es obrigat¨®rias s?o: zbx_module_api_version() e zbx_module_init():

int zbx_module_api_version(void);

Esta fun??o deve retornar a vers?o da API implementada no m¨®duo, atualmente existe somente uma vers?o: ZBX_MODULE_API_VERSION_ONE (definida com o valor 1), ent?o esta fun??o dever¨¢ retornar esta constante.

int zbx_module_init(void);

Esta fun??o ¨¦ respons¨¢vel por fazer a inicializa??o do m¨®dulo (se existir). Se for conclu¨ªda com sucesso dever¨¢ retornar: ZBX_MODULE_OK. Em qualquer outra situa??o, dever¨¢ retornar: ZBX_MODULE_FAIL.

5.2.2 Interfaces opcionais

Existem tr¨ºs fun??es opcionais: zbx_module_item_list(), zbx_module_item_timeout() e zbx_module_uninit():

ZBX_METRIC  *zbx_module_item_list(void);

Esta fun??o dever¨¢ retornar uma lista de itens suportados no m¨®dulo. Cada item ¨¦ definido como uma estrutura 'ZBX_METRIC', veja a se??o a seguir para detalhes. Uma lista ZBX_METRIC dever¨¢ possuir uma estrutura onde o ¨²ltimo campo key tem o valor NULL.

void    zbx_module_item_timeout(int timeout);

Esta fun??o ¨¦ utilizada pelo Áú»¢¶Ä²© para especificar as configura??es de 'timeout' no arquivo de configura??o do Áú»¢¶Ä²© que o m¨®dulo dever¨¢ obedecer. O tempo de espera ¨¦ definido em segundos.

int zbx_module_uninit(void);

Esta fun??o executa a libera??o de recursos, tal qual liberar recursos alocados, fechar descritores de arquivo, etc..

Todas as fun??es s?o chamadas durante a inicializa??o do Áú»¢¶Ä²©, quando o m¨®dulo ¨¦ carregado, com exce??o da fun??o zbx_module_uninit(), que ser¨¢ chamada quando o Áú»¢¶Ä²© estiver sendo terminado.

5.2.3 Definindo itens

Cada item ¨¦ definido com uma estrutura 'ZBX_METRIC':

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

Nesta estrutura:

  • key - a chave do item (ex. "dummy.random")
  • flags - pode ser 'CF_HAVEPARAMS' ou '0' (dependendo do item aceitar par?metros ou n?o)
  • function - ¨¦ uma fun??o em C que implementa o item (ex. "zbx_module_dummy_random")
  • test_param - ¨¦ ua lista de par?metros para ser utilizada quando o Áú»¢¶Ä²© Agent for inicializado usando a marca "-p" (ex "1,1000", pode ser 'NULL'). Uma exemplo de defini??o usando esta estrutura pode ser:
static ZBX_METRIC keys[] =
       {
           { "dummy.random", CF_HAVEPARAMS, zbx_module_dummy_random, "1,1000" },
           { NULL }
       }

Cada fun??o que implementa um item deve aceitar dois ponteiros, o primeiro com o tipo AGENT_REQUEST, o segundo com o tipo 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;
       }

Estas fun??es dever?o retornar 'SYSINFO_RET_OK', se o valor foi obtido com sucesso. Qualquer outra situa??o o retorno dever¨¢ ser 'SYSINFO_RET_FAIL'. Veja o exemplo do m¨®dulo "dummy" a seguir para detalhes sobre como obter informa??es sobre o AGENT_REQUEST e como configurar o AGENT_RESULT.

5.2.4 Construindo os m¨®dulos

Os m¨®dulos precisam ser constru¨ªdos internamente na ¨¢rvore do c¨®digo fonte do Áú»¢¶Ä²©, pois o m¨®dulo depende de algumas estruturas de dados que s?o definidas nos cabe?alhos do Áú»¢¶Ä²©.

O cabe?alho mais importante para os m¨®dulos carreg¨¢veis ¨¦ include/module.h, que define as estruturas de dados. Outro cabe?alho ¨²til ¨¦ include/sysinc.h, que faz a inclus?o dos cabe?alhos de sistema que ser?o necess¨¢rios, que por sua vez auxilia o include/module.h a funcionar adequadamente.

Para que include/module.h e include/sysinc.h sejam inclu¨ªdos, o comando ./configure (sem par?metros) dever¨¢ ser executado no diret¨®rio raiz dos fontes do Áú»¢¶Ä²©. Isso ir¨¢ criar o arquivo include/config.h, com as depend¨ºncias do include/sysinc.h. (Se voc¨º tiver obtido o c¨®digo fonte do Áú»¢¶Ä²© a partir do "Subversion repository", o script ./configure n?o existir¨¢ e o comando ./bootstrap.sh dever¨¢ ser executado primeiro para gera-lo.)

Com esta informa??o em mente, tudo est¨¢ pronto para criar o m¨®dulo. O m¨®dulo dever¨¢ incluir sysinc.h e module.h, e o script de cria??o se certificar¨¢ que estes dois arquivos est?o dispon¨ªveis no path. Veja o exemplo do m¨®dulo "dummy" a seguir para maiores detalhes.

Outro cabe?alho ¨²til ¨¦ o include/log.h, que define a fun??o zabbix_log(), que poder¨¢ ser utilizada com o prop¨®sito de registro e debug.

5.3 Par?metros de configura??o

O Áú»¢¶Ä²© Agent, Server e Proxy suportam dois par?metros para lidar com os m¨®dulos:

  • LoadModulePath ¨C caminho completo para a localiza??o dos m¨®dulos carreg¨¢veis
  • LoadModule ¨C m¨®dulo(s) para ser carregado durante a inicializa??o. Os m¨®dulos dever?o estar localizados no diret¨®rio definido em LoadModulePath. Tamb¨¦m ¨¦ permitida a inclus?o de m¨²ltiplos m¨®dulos.

Por exemplo, para estender o Áú»¢¶Ä²© Agent n¨®s podemos adicionar os par?metros a seguir:

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

Quando o agente for inicializado ele ir¨¢ carregar os m¨®dulos mariadb.so, apache.so, kernel.so and dummy.so a partir do diret¨®rio /usr/local/lib/zabbix/agent. Se um dos m¨®dulos estiver ausente, ou n?o tiver com o permissionamento correto, ou n?o for um 'M¨®dulo Áú»¢¶Ä²©' a carga do agente ir¨¢ falhar.

5.4 Configura??o na interface web

Os m¨®dulos carreg¨¢veis s?o suportados pelo Áú»¢¶Ä²© Agent, Server e Proxy. Portanto, o tipo do item depende de onde foi carregado. Se o m¨®dulo tiver sido carregado no agente, o tipo dever¨¢ ser "Agente Áú»¢¶Ä²©" ou "Agente Áú»¢¶Ä²© (ativo)". Se o m¨®dulo tiver sido carregado no Server ou Proxy, o tipo do item dever¨¢ ser "Verifica??o simples".

5.5 M¨®dulo Dummy

O c¨®digo fonte do Áú»¢¶Ä²© 2.2 inclui um exemplo de m¨®dulo desenvolvido em C. O m¨®dulo est¨¢ localizado em 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

O m¨®dulo ¨¦ bem documentado e pode ser utilizado como um modelo para que voc¨º construa os seus pr¨®prios m¨®dulos.

Ap¨®s executar o ./configure no diret¨®rio raiz dos fontes do Áú»¢¶Ä²©, conforme informado anteriormente, apenas execute o comando make para compilar o dummy.so.

/*
       ** Áú»¢¶Ä²©
       ** Copyright (C) 2001-2013 Áú»¢¶Ä²© 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 "sysinc.h"
       #include "module.h"
       
       /* the variable keeps timeout setting for item processing */
       static int    item_timeout = 0;
       
       int    zbx_module_dummy_ping(AGENT_REQUEST *request, AGENT_RESULT *result);
       int    zbx_module_dummy_echo(AGENT_REQUEST *request, AGENT_RESULT *result);
       int    zbx_module_dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result);
       
       static ZBX_METRIC keys[] =
       /* KEY               FLAG           FUNCTION                TEST PARAMETERS */
       {
           {"dummy.ping",   0,             zbx_module_dummy_ping,  NULL},
           {"dummy.echo",   CF_HAVEPARAMS, zbx_module_dummy_echo,  "a message"},
           {"dummy.random", CF_HAVEPARAMS, zbx_module_dummy_random,"1,1000"},
           {NULL}
       };
       
       /***
       *                                                                            *
       * Function: zbx_module_api_version                                           *
       *                                                                            *
       * Purpose: returns version number of the module interface                    *
       *                                                                            *
       * Return value: ZBX_MODULE_API_VERSION_ONE - the only version supported by   *
       *               Áú»¢¶Ä²© currently                                             *
       *                                                                            *
       ***/
       int    zbx_module_api_version()
       {
           return ZBX_MODULE_API_VERSION_ONE;
       }
       
       /***
       *                                                                            *
       * 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()
       {
           return keys;
       }
       
       int    zbx_module_dummy_ping(AGENT_REQUEST *request, AGENT_RESULT *result)
       {
           SET_UI64_RESULT(result, 1);
       
           return SYSINFO_RET_OK;
       }
       
       int    zbx_module_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: zbx_module_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¡útimeout - processing should not take longer than     *
       *                                 this number of seconds                     *
       *              request¡úparams[N-1] - pointers to item key parameters        *
       *                                                                            *
       *             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.                             *
       *                                                                            *
       ***/
       int    zbx_module_dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result)
       {
           char  *param1, *param2;
           int   from, to;
       
           if (request¡únparam != 2)
           {
               /* 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 for simplicity sake */
           from = atoi(param1);
           to = atoi(param2);
       
           if (from > to)
           {
               SET_MSG_RESULT(result, strdup("Incorrect range given"));
               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()
       {
           /* 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()
       {
           return ZBX_MODULE_OK;
       }

Este m¨®dulo exporta tr¨ºs novos itens:

  • dummy.ping - sempre retorna '1'
  • dummy.echo[param1] - retorna o primeiro par?metro que for informado, por exemplo, dummy.echo[ABC] retornar¨¢: ABC
  • dummy.random[param1, param2] - retorna um n¨²mero rand?mico dentro do range definido em param1-param2, por exemplo, dummy.random[1,1000000]

5.6 Limita??es

O suporte para m¨®dulos carreg¨¢veis foi implementado apenas na plataforma UNIX. Isso significa que n?o ir?o funcionar em Agentes para Windows.

Em alguns casos o m¨®dulo pode precisar ler par?metros de configura??o do zabbix_agentd.conf. Isso ainda n?o ¨¦ fornecido pela API, se voc¨º precisar obter tais par?metros voc¨º dever¨¢ implementar a an¨¢lise do arquivo de configura??es.