feat: 将 zabbix agent 作为集成

This commit is contained in:
Liam Chan 2024-08-23 10:37:24 +08:00
parent bdc56bbce5
commit 37e6813d6f
4 changed files with 141 additions and 17 deletions

View File

@ -9,3 +9,4 @@ integrations:
zabbix_agent:
plugin:
name: "Onvif"
version: "1.0.0"

View File

@ -6,4 +6,5 @@ type IntegrationConfig struct {
type PluginConfig struct {
Name string `mapstructure:"name"`
Version string `mapstructure:"version"`
}

View File

@ -0,0 +1,68 @@
package plugin
import (
"context"
"fmt"
"golang.zabbix.com/sdk/errs"
"io"
"net/http"
"onvif-agent/config"
"strings"
)
// HandlerFunc describes the signature all metric handler functions must have.
type HandlerFunc func(
ctx context.Context,
metricParams map[string]string,
extraParams ...string,
) (any, error)
// Handler hold client and syscall implementation for request functions.
type Handler struct {
client *http.Client
}
func (h *Handler) GetPluginVersion(_ context.Context, _ map[string]string, _ ...string) (any, error) {
return config.Conf.Integrations.ZabbixAgent.Plugin.Version, nil
}
func (h *Handler) HTTPClient(ctx context.Context, params map[string]string, _ ...string) (any, error) {
method := params["method"]
if method == "" {
method = http.MethodGet
}
url := params["url"]
if !strings.HasPrefix(url, "http") {
url = fmt.Sprintf("http://localhost:%d/%s", config.Conf.Server.Port, url)
}
body := params["body"]
//req, err := http.NewRequestWithContext(ctx, method, "https://api.imbytecat.com/ip", http.NoBody)
req, err := http.NewRequestWithContext(ctx, method, "https://api.imbytecat.com/ip", strings.NewReader(body))
if err != nil {
return nil, errs.Wrapf(err, "failed to create request")
}
resp, err := h.client.Do(req)
if err != nil {
return nil, errs.Wrapf(err, "failed to send the request")
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errs.Wrapf(err, "failed to read the response")
}
return string(data), nil
}
// NewHandler creates a new handler with initialized clients for system and tcp calls.
func NewHandler() *Handler {
return &Handler{
client: http.DefaultClient,
}
}

View File

@ -1,19 +1,28 @@
package plugin
import (
"context"
"golang.zabbix.com/sdk/errs"
"golang.zabbix.com/sdk/metric"
"golang.zabbix.com/sdk/plugin"
"golang.zabbix.com/sdk/plugin/container"
"golang.zabbix.com/sdk/zbxerr"
"onvif-agent/config"
"time"
)
var (
PluginName = config.Conf.Integrations.ZabbixAgent.Plugin.Name
)
var Name = config.Conf.Integrations.ZabbixAgent.Plugin.Name
type metricKey string
type metricBinding struct {
metric *metric.Metric
handler HandlerFunc
}
type zabbixAgentPlugin struct {
plugin.Base
metrics map[metricKey]*metricBinding
}
// Launch launches the plugin. Blocks until plugin execution has finished.
@ -25,7 +34,7 @@ func Launch() error {
return err
}
h, err := container.NewHandler(PluginName)
h, err := container.NewHandler(Name)
if err != nil {
return errs.Wrap(err, "failed to create new handler")
}
@ -40,20 +49,65 @@ func Launch() error {
return nil
}
// Export collects all the metrics.
func (p *zabbixAgentPlugin) Export(key string, rawParams []string, _ plugin.ContextProvider) (any, error) {
b, ok := p.metrics[metricKey(key)]
if !ok {
return nil, errs.Wrapf(zbxerr.ErrorUnsupportedMetric, "unknown metric %q", key)
}
metricParams, extraParams, _, err := b.metric.EvalParams(rawParams, nil)
if err != nil {
return nil, errs.Wrap(err, "failed to evaluate metric parameters")
}
ctx, cancel := context.WithTimeout(
context.Background(),
30*time.Second, // TODO: make configurable
)
defer cancel()
res, err := b.handler(ctx, metricParams, extraParams...)
if err != nil {
return nil, errs.Wrap(err, "failed to execute handler")
}
return res, nil
}
func (p *zabbixAgentPlugin) registerMetrics() error {
metricSet := metric.MetricSet{
"onvif.client": metric.New(
h := NewHandler()
p.metrics = map[metricKey]*metricBinding{
"onvif.version": {
metric: metric.New(
"ONVIF plugin version",
nil,
false,
),
handler: h.GetPluginVersion,
},
"onvif.client": {
metric: metric.New(
"ONVIF client",
[]*metric.Param{
metric.NewParam("method", "HTTP method"),
metric.NewParam("url", "URL"),
metric.NewParam("data", "Request data"),
metric.NewParam("method", "HTTP request method."),
metric.NewParam("url", "HTTP request URL."),
metric.NewParam("body", "HTTP request body."),
},
false,
),
handler: h.HTTPClient,
},
}
err := plugin.RegisterMetrics(p, PluginName, metricSet.List()...)
metricSet := metric.MetricSet{}
for k, m := range p.metrics {
metricSet[string(k)] = m.metric
}
err := plugin.RegisterMetrics(p, Name, metricSet.List()...)
if err != nil {
return errs.Wrap(err, "failed to register metrics")
}