Você está visualizando a documentação da versão de desenvolvimento, que pode estar incompleta.
Esta página foi traduzida automaticamente. Se você notar um erro, selecione-o e pressione Ctrl+Enter para reportá-lo aos editores.

Criar um plugin (tutorial)

Este é um tutorial passo a passo sobre como criar um plugin simples carregável para o Zabbix agent 2.

Você também pode usar o repositório de exemplo como um modelo ou guia para criar seus próprios plugins.

O que você irá criar

Este tutorial demonstra como criar um novo plugin carregável MyIP. O plugin irá implementar uma única chave de item, myip, que retorna o endereço IP externo do host onde o Zabbix agent 2 está em execução.

Etapa 1: Configuração

  1. Um plugin é um módulo Go padrão. Comece inicializando o arquivo go.mod no diretório do plugin para rastrear as dependências do plugin:
cd path/to/plugins/myip # Acesse o diretório do seu plugin
       go mod init myip
  1. Instale a dependência obrigatória Zabbix Go SDK (golang.zabbix.com/sdk):
go get golang.zabbix.com/sdk@$LATEST_COMMIT_HASH

Substitua $LATEST_COMMIT_HASH pelo hash do commit HEAD mais recente do repositório golang.zabbix.com/sdk no branch de release apropriado. Por exemplo:

go get golang.zabbix.com/sdk@af85407

Observe que a versão do golang.zabbix.com/sdk atualmente não é suportada, mas isso pode mudar no futuro.

Dependências adicionais podem ser instaladas conforme necessário usando go get.

  1. Crie um arquivo vazio main.go para o código-fonte do plugin:
touch main.go

Agora a configuração inicial está concluída e o plugin está pronto para desenvolvimento.

Etapa 2: Estrutura do plugin

O módulo golang.zabbix.com/sdk, instalado na etapa anterior, fornece a estrutura necessária para o desenvolvimento de plugins e garante que todos os plugins tenham uma estrutura consistente.

  1. Configure o fluxo básico de execução.

Comece definindo o fluxo principal de execução do plugin. Adicione o seguinte código ao main.go:

package main
       
       func main() {
           err := run()
           if err != nil {
               panic(err)
           }
       }
       
       func run() error {
           return nil
       }

Isso estabelece o fluxo básico de execução para o plugin. A função run conterá posteriormente a lógica principal do plugin.

  1. Explore as interfaces do plugin.

Um plugin do Zabbix agent 2 deve ser representado por uma struct que implementa interfaces do pacote golang.zabbix.com/sdk/plugin:

  • Accessor - define métodos essenciais que todos os plugins devem implementar, como definir o nome do plugin e lidar com timeouts de chave de item.
  • Uma ou mais das seguintes interfaces funcionais de plugin:
    • Exporter - executa uma pesquisa e retorna um valor (ou valores), nada ou um erro; frequentemente usado junto com a interface Collector.
    • Collector - gerencia a coleta periódica de dados.
    • Runner - define procedimentos de inicialização e desligamento do plugin.
    • Watcher - permite implementar polling independente de métricas, ignorando o agendador interno do agent; útil para monitoramento baseado em trap ou orientado a eventos.
    • Configurator - define como o plugin lê e aplica suas configurações.

Você pode implementar essas interfaces por conta própria ou usar as implementações padrão fornecidas pelo Zabbix Go SDK, modificando-as conforme necessário. Este tutorial utiliza as implementações padrão.

  1. Crie a struct do plugin.

Agora, importe o pacote plugin e crie uma struct myIP que incorpora a struct plugin.Base:

import "golang.zabbix.com/sdk/plugin"
       
       type myIP struct {
           plugin.Base
       }

A struct myIP atualmente satisfaz a interface Accessor. Um método para implementar uma das interfaces funcionais do plugin, o Exporter, será adicionado posteriormente no tutorial.

Etapa 3: Definir as chaves de item

Seu plugin precisa das chaves de item para coletar dados e fornecê-los ao Zabbix server ou proxy.

  1. Importe o pacote errs para tratamento de erros:
import "golang.zabbix.com/sdk/errs"
  1. Registre as chaves de item usando a função plugin.RegisterMetrics() dentro da função run():
func run() error {
           p := &myIP{}
       
           // Registra a chave de item `myip`.
           err := plugin.RegisterMetrics(
               p,
               "MyIP",                           // Nome do plugin
               "myip",                           // Nome da chave de item
               "Retorna o endereço IP do host.", // Descrição da chave de item
           )
           if err != nil {
               return errs.Wrap(err, "falha ao registrar métricas")
           }
       
           return nil
       }

Para registrar várias chaves de item, repita os parâmetros nome da métrica e descrição para cada métrica. Por exemplo:

plugin.RegisterMetrics(&impl, "Myip", "metric.one", "Descrição da métrica um.", "metric.two", "Descrição da métrica dois.")

Etapa 4: Configurar o handler

O handler facilita a comunicação entre o agent e o plugin.

  1. Importe o pacote container:
import "golang.zabbix.com/sdk/plugin/container"
  1. Dentro da função run(), adicione o código para criar e configurar um handler:
func run() error {
           p := &myIP{}
       
           // Registre a chave de item `myip`.
           err := plugin.RegisterMetrics(
               p,
               "MyIP",                           // Nome do plugin
               "myip",                           // Nome da chave do item
               "Returns the host's IP address.", // Descrição da chave do item
           )
           if err != nil {
               return errs.Wrap(err, "failed to register metrics")
           }
       
           // Crie um novo handler.
           h, err := container.NewHandler("MyIP") // Nome do plugin
           if err != nil {
               return errs.Wrap(err, "failed to create new handler")
           }
       
           // Configure o log para encaminhar logs do plugin para o agent.
           // Disponível via p.Logger.Infof, p.Logger.Debugf, etc.
           p.Logger = h
       
           // Inicie a execução do plugin.
           // Bloqueia até que uma solicitação de término seja recebida do agent.
           err = h.Execute()
           if err != nil {
               return errs.Wrap(err, "failed to execute plugin handler")
           }
       
           return nil
       }

Etapa 5: Implementar a coleta de dados

A coleta de dados é feita por meio da interface Exporter, que descreve o método Export:

func Export(
         key string,             // O item key a ser coletado.
         params []string,        // Argumentos passados para o item key (`myip[arg1, arg2]`).
         context ContextProvider // Metadados sobre a coleta de dados do item key.
       ) (any, error)
  1. Importe os pacotes necessários para requisições HTTP e leitura de resposta:
import (
           "io"
           "net/http"
       )
  1. Implemente o método Export para a struct myIP:
func (p *myIP) Export(
           key string, params []string, context plugin.ContextProvider,
       ) (any, error) {
           // O plugin pode usar diferentes lógicas de coleta de dados com base no parâmetro `key`.
           // Esta implementação apenas verifica se o `key` fornecido é suportado.
           if key != "myip" {
               return nil, errs.Errorf("unknown item key %q", key)
           }
       
           // O log será encaminhado para o log do agent 2.
           p.Infof(
               "received request to handle %q key with %d parameters",
               key,
               len(params),
           )
       
           // Colete os dados e retorne-os.
       
           resp, err := http.Get("https://api.ipify.org")
           if err != nil {
               return nil, errs.Wrap(err, "failed to get IP address")
           }
       
           defer resp.Body.Close()
       
           body, err := io.ReadAll(resp.Body)
           if err != nil {
               return nil, errs.Wrap(err, "failed to read response body")
           }
       
           return string(body), nil
       }

Etapa 6: Compile e configure o plugin

  1. Para compilar o plugin, execute:
go mod tidy
       go build

Isso deve criar um executável myip no diretório atual.

  1. Configure o Zabbix agent 2 para usar o plugin:
echo "Plugins.MyIP.System.Path=$PATH_TO_THE_MYIP_PLUGIN_EXECUTABLE" > /etc/zabbix_agent2.d/plugins.d/myip.conf

Substitua $PATH_TO_THE_MYIP_PLUGIN_EXECUTABLE pelo caminho para o myip criado na etapa 5.

O nome do plugin no parâmetro de configuração (MyIP neste tutorial) deve corresponder ao nome do plugin definido na função plugin.RegisterMetrics().

  1. Para testar o plugin e seu item myip, execute:
zabbix_agent2 -c /etc/zabbix_agent2.conf -t myip

A saída deve conter um endereço IP externo do seu host e ser semelhante a esta:

myip                                          [s|192.0.2.0]

Com isso, você criou um plugin simples carregável para o Zabbix agent 2. Parabéns!

Código-fonte completo

package main
       
       import (
           "io"
           "net/http"
       
           "golang.zabbix.com/sdk/errs"
           "golang.zabbix.com/sdk/plugin"
           "golang.zabbix.com/sdk/plugin/container"
       )
       
       var _ plugin.Exporter = (*myIP)(nil)
       
       type myIP struct {
           plugin.Base
       }
       
       func main() {
           err := run()
           if err != nil {
               panic(err)
           }
       }
       
       func run() error {
           p := &myIP{}
       
           // Registra a chave do item `myip`.
           err := plugin.RegisterMetrics(
               p,
               "MyIP",                           // Nome do plugin
               "myip",                           // Nome da chave do item
               "Returns the host's IP address.", // Descrição da chave do item
           )
           if err != nil {
               return errs.Wrap(err, "failed to register metrics")
           }
       
           // Cria um novo handler.
           h, err := container.NewHandler("MyIP") // Nome do plugin
           if err != nil {
               return errs.Wrap(err, "failed to create new handler")
           }
       
           // Configura o log para encaminhar logs do plugin para o agent.
           // Disponível via p.Logger.Infof, p.Logger.Debugf, etc.
           p.Logger = h
       
           // Inicia a execução do plugin.
           // Bloqueia até receber uma solicitação de término do agent.
           err = h.Execute()
           if err != nil {
               return errs.Wrap(err, "failed to execute plugin handler")
           }
       
           return nil
       }
       
       func (p *myIP) Export(
           key string, params []string, context plugin.ContextProvider,
       ) (any, error) {
           // O plugin pode usar diferentes lógicas de coleta de dados com base no parâmetro `key`.  
           // Esta implementação apenas verifica se a `key` fornecida é suportada. 
           if key != "myip" {
               return nil, errs.Errorf("unknown item key %q", key)
           }
       
           // O log será encaminhado para o log do agent 2.
           p.Infof(
               "received request to handle %q key with %d parameters",
               key,
               len(params),
           )
       
           // Coleta os dados e os retorna.
       
           resp, err := http.Get("https://api.ipify.org")
           if err != nil {
               return nil, errs.Wrap(err, "failed to get IP address")
           }
       
           defer resp.Body.Close()
       
           body, err := io.ReadAll(resp.Body)
           if err != nil {
               return nil, errs.Wrap(err, "failed to read response body")
           }
       
           return string(body), nil
       }