Crea un plugin (tutorial)
Questo è un tutorial passo passo per creare un semplice plugin caricabile per l'agente Zabbix 2.
Cosa creerai
Durante questo tutorial, aggiungerai un nuovo plugin caricabile MyIP. Il plugin implementerà 1 metrica chiamata myip, che restituisce l'indirizzo IP esterno dell'host su cui è in esecuzione l'agente Zabbix 2.
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.
-
Create a new directory myip in /usr/local/zabbix/go/plugins/.
-
Create the file
main.goinside 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
- 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"
)
- 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
- 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)
- 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))
}
- 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
}
- 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.")
}
- 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
- 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
-
Create an executable myip, which is the loadable plugin.
-
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
- 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.