Crie um plugin (tutorial)

Este é um tutorial passo a passo para criar um plug-in carregável simples para o Zabbix agent 2.

O que você criará

Durante este tutorial, você adicionará um novo plug-in carregável MyIP. O plug-in implementará uma métrica chamada myip, que retorna o endereço IP externo do host em que o Zabbix Agent 2 está sendo executado.

Parte 1: Escrevendo o código Go

Nesta seção, você aprenderá a escrever o plug-in que adiciona uma nova métrica ao Zabbix Agent 2.

  1. Crie um novo diretório myip em /usr/local/zabbix/go/plugins/.

  2. Crie o arquivo main.go dentro do diretório myip e defina o nome do seu pacote Go.

/usr/local/zabbix/go/plugins/myip/main.go

package main

Mantenha o arquivo aberto para adicionar mais linhas, conforme descrito nas próximas etapas.

  1. Especifique os pacotes a serem importados.
    Esses são os pacotes que suportam o plug-in.

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
  1. Defina a estrutura do plug-in.
    Incorpore a estrutura plugin.Base para obter acesso à funcionalidade padrão do plug-in.

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
  1. Implemente a interface de plug-in [Export] (/devel/plugins/interfaces).
    A interface Export executa uma pesquisa e retorna um valor.

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
       
       func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error)
  1. Adicione o registro.
    As mensagens de registro aparecerão no log do Zabbix Agent 2. Você pode usar uma das funções de registro disponíveis para os plug-ins: Critf(), Errf(), Infof(), Warningf(), Debugf(), Tracef().

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
       
       func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error){
           p.Infof("received request to handle %s key with %d parameters", key, len(params))
       }
  1. Implemente a lógica central do plug-in.
    Essa lógica obtém a resposta da URL especificada e a lê, depois retorna o endereço IP como resposta e fecha a solicitação.
    Em caso de erro ao executar a solicitação GET ou ao ler uma resposta, o erro é retornado.

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
       
       func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error){
           p.Infof("received request to handle %s key with %d parameters", key, len(params))
           resp, err := http.Get("https://api.ipify.org")
           if err != nil {
               return nil, err
           }
              
           defer resp.Body.Close()
              
           body, err := ioutil.ReadAll(resp.Body)
           if err != nil {
               return nil, err
           }
              
           return string(body), nil    
       }
  1. Registre a métrica.
    O Zabbix Agent 2 inicia a execução da função init() na inicialização. Essa função chamará o método plugin.RegisterMetrics(structure, nome do plugin, nome da métrica, descrição) para obter os dados do plugin.

A descrição do parâmetro do método plugin.RegisterMetrics:

  • structure - um ponteiro para a implementação do plug-in; concede acesso à estrutura do plug-in, incluindo a lista de interfaces de plug-in disponíveis (por exemplo, &impl).
  • name - nome do plugin; deve ser exclusivo (por exemplo, "Myip ").
  • metric name - nome da métrica (por exemplo, "myip "). Essa é a chave do item usada para coletar dados de um plug-in.
  • description - descrição da métrica; deve começar com uma letra maiúscula e terminar com um ponto (por exemplo, ""Return the external IP address of the host where agent is running. ").

Para registrar várias métricas, repita os parâmetros nome da métrica e descrição para cada métrica.
Por exemplo: plugin.RegisterMetrics(&impl, "Myip", "metric.one", "Metric one description.", "metric.two", "Metric two description.")

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
       
       func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error){
           p.Infof("received request to handle %s key with %d parameters", key, len(params))
           resp, err := http.Get("https://api.ipify.org")
           if err != nil {
               return nil, err
           }
              
           defer resp.Body.Close()
              
           body, err := ioutil.ReadAll(resp.Body)
           if err != nil {
               return nil, err
           }
              
           return string(body), nil    
       }
       
       func init() {
           plugin.RegisterMetrics(&impl, "Myip", "myip", "Return the external IP address of the host where agent is running.")
       }
  1. Defina a função main(), que criará uma nova instância do manipulador de plug-in, atribuirá a ela o uso para registro pelo plug-in e, em seguida, executará o manipulador de plug-in.

A definição da função main() é obrigatória.

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
       
       func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error){
           p.Infof("received request to handle %s key with %d parameters", key, len(params))
           resp, err := http.Get("https://api.ipify.org")
           if err != nil {
               return nil, err
           }
              
           defer resp.Body.Close()
              
           body, err := ioutil.ReadAll(resp.Body)
           if err != nil {
               return nil, err
           }
              
           return string(body), nil    
       }
       
       func init() {
           plugin.RegisterMetrics(&impl, "Myip", "myip", "Return the external IP address of the host where agent is running.")
       }
       
       func main() {
           h, err := container.NewHandler(impl.Name())
           if err != nil {
               panic(fmt.Sprintf("failed to create plugin handler %s", err.Error()))
           }
           impl.Logger = &h
              
           err = h.Execute()
           if err != nil {
               panic(fmt.Sprintf("failed to execute plugin handler %s", err.Error()))
           }
       }

Parte 2: Compilando o plug-in

Nesta seção, você aprenderá a compilar o plug-in.

  1. Para criar arquivos Go para manipulação de dependências e fazer o download das dependências automaticamente, execute este script bash na CLI.
go mod init myip
       GOPROXY=direct go get git.zabbix.com/ap/plugin-support/plugin@branchname
       go mod tidy
       go build

Certifique-se de especificar o nome correto da ramificação, ou seja, substitua branchname (consulte a linha 2) por um dos seguintes:

  • release/* - para a ramificação de lançamento estável, em que "*" é a versão de lançamento (ou seja, 6.4)
  • master - para a ramificação master
  • <commit hash> - para a versão específica do commit (use o hash específico do commit)

A saída deve ser semelhante a esta:

go: criando um novo go.mod: módulo myip
       go: para adicionar requisitos e somas ao módulo:
           go mod tidy
       go: encontrando módulo para o pacote git.zabbix.com/ap/plugin-support/plugin/container
       go: encontrando módulo para o pacote git.zabbix.com/ap/plugin-support/plugin
       go: encontrado git.zabbix.com/ap/plugin-support/plugin em git.zabbix.com/ap/plugin-support v0.0.0-20220608100211-35b8bffd7ad0
       go: encontrado git.zabbix.com/ap/plugin-support/plugin/container em git.zabbix.com/ap/plugin-support v0.0.0-20220608100211-35b8bffd7ad0
  1. Crie um executável myip para o plug-in carregável.

  2. Especifique o caminho para o arquivo de configuração do plug-in no parâmetro Plugins.Myip.System.Path do arquivo de configuração do Zabbix Agent 2.

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

echo 'Plugins.Myip.System.Path=/usr/local/zabbix/go/plugins/myip/myip' > /etc/zabbix_agent2.d/plugins.d/myip.conf
  1. Teste a métrica:
zabbix_agent2 -t myip

A resposta deve conter um endereço IP externo de seu host.

Em caso de erro, verifique se o usuário zabbix tem permissões para acessar o diretório /usr/local/zabbix/go/plugins/myip.