This is a translation of the original English documentation page. Help us make it better.

Créer un plugin (tutoriel)

Il s'agit d'un didacticiel étape par étape pour créer un plugin chargeable simple pour l'agent Zabbix 2.

Ce que vous allez créer

Au cours de ce didacticiel, vous ajouterez un nouveau plugin chargeable MyIP. Le plugin implémentera 1 métrique appelée myip, qui renvoie l'adresse IP externe de l'hôte sur lequel l'agent Zabbix 2 est exécuté.

Part 1: Writing the Go code

In this section you will learn how to write the plugin that adds a new metric to Zabbix agent 2.

  1. Create a new directory myip in /usr/local/zabbix/go/plugins/.

  2. Create the file main.go inside myip directory and define the name of your Go package.

Keep the file open to add more lines as described in the next steps.

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

package main
  1. Specify the packages to import. These are the packages that support the plugin.

/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. Define the plugin structure.
    Embed the plugin.Base structure to gain access to the standard plugin functionality.

/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. Implement plugin interface Export. The export interface performs a poll and returns a value.

/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. Add logging.
    The log messages will appear in the Zabbix agent 2 log. You can use one of the logging functions available to plugins: 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. Implement the core plugin logic. This logic fetches the response from the specified URL and reads it, then returns the IP address as a response and closes the request. In case of an error when executing the GET request or reading a response, the error is returned instead.

/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. Register the metric. Zabbix agent 2 initiates running init() function upon startup. This function will call plugin.RegisterMetrics(structure, plugin name, metric name, description) method to get the plugin data.

The plugin.RegisterMetrics method parameter description:

  • structure - a pointer to plugin implementation; grants access to the plugin structure, including list of available plugin interfaces (for example, &impl).
  • name - plugin name; must be unique (for example, "Myip").
  • metric name - metric name (for example, "myip"). This is the item key used to gather data from a plugin.
  • description - metric description; must start with a capital letter and end with a period (for example, ""Return the external IP address of the host where agent is running.").

The third and fourth parameters can be repeated multiple times in a row to register multiple metrics.

/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. Define the main function, which will implement Zabbix plugin handler to create and start the plugin. Defining the main() function is mandatory.

/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()))
                  }
              }

Part 2: building the plugin

  1. Execute this bash script to create go files for dependency handling, and to download the dependencies automatically:
go mod init myip
       GOPROXY=direct go mod tidy
       go build

You should receive an output similar to this:

go: creating new go.mod: module myip
       go: to add module requirements and sums:
           go mod tidy
       go: finding module for package git.zabbix.com/ap/plugin-support/plugin/container
       go: finding module for package git.zabbix.com/ap/plugin-support/plugin
       go: found git.zabbix.com/ap/plugin-support/plugin in git.zabbix.com/ap/plugin-support v0.0.0-20220608100211-35b8bffd7ad0
       go: found git.zabbix.com/ap/plugin-support/plugin/container in git.zabbix.com/ap/plugin-support v0.0.0-20220608100211-35b8bffd7ad0
  1. Create an executable myip, which is the loadable plugin.

  2. Specify the path to the plugin configuration file in Zabbix agent 2 configuration file. The path should be set in the Plugins.<PluginName>.System.Path parameter. Replace <PluginName> with the name of the plugin, defined in the code when calling plugin.RegisterMetrics() function (for this tutorial, Plugins.Myip.System.Path).

echo 'Plugins.Myip.System.Path=/usr/local/zabbix/go/plugins/myip/myip' > /etc/zabbix_agent2.d/plugins.d/myip.conf
  1. Now, everything is ready to test the metric:
zabbix_agent2 -t myip

The response should contain the external IP address of your host.

In case of an error, first make sure that the user zabbix has permissions to access /usr/local/zabbix/go/plugins/myip directory.