From 4b294bd0be26220836c6a605fbeac9999a44fe37 Mon Sep 17 00:00:00 2001 From: shrank Date: Wed, 17 Apr 2024 10:37:17 -0700 Subject: [PATCH 1/5] added zabbix webhook --- go.mod | 53 ++++---- plugins/inputs/webhooks/sample.conf | 15 ++ plugins/inputs/webhooks/webhooks.go | 2 + plugins/inputs/webhooks/webhooks_test.go | 6 + plugins/inputs/webhooks/zabbix/README.md | 51 +++++++ .../inputs/webhooks/zabbix/zabbix_webhooks.go | 70 ++++++++++ .../webhooks/zabbix/zabbix_webhooks_events.go | 75 ++++++++++ .../zabbix_webhooks_events_json_test.go | 66 +++++++++ .../webhooks/zabbix/zabbix_webhooks_test.go | 128 ++++++++++++++++++ 9 files changed, 441 insertions(+), 25 deletions(-) create mode 100644 plugins/inputs/webhooks/zabbix/README.md create mode 100644 plugins/inputs/webhooks/zabbix/zabbix_webhooks.go create mode 100644 plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go create mode 100644 plugins/inputs/webhooks/zabbix/zabbix_webhooks_events_json_test.go create mode 100644 plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go diff --git a/go.mod b/go.mod index efcf323955f72..1eda5aa5f6143 100644 --- a/go.mod +++ b/go.mod @@ -229,7 +229,6 @@ require ( cloud.google.com/go/compute v1.23.4 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.6 // indirect - code.cloudfoundry.org/clock v1.0.0 // indirect dario.cat/mergo v1.0.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -254,20 +253,16 @@ require ( github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect - github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/alecthomas/participle v0.4.1 // indirect github.com/andybalholm/brotli v1.1.0 // indirect github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect github.com/apache/arrow/go/v14 v14.0.2 // indirect - github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/awnumar/memcall v0.2.0 // indirect github.com/aws/aws-sdk-go v1.45.25 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect - github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.7 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.7 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect @@ -283,22 +278,17 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 // indirect github.com/awslabs/kinesis-aggregation/go v0.0.0-20210630091500-54e17340d32f // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bitly/go-hostpool v0.1.0 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/bufbuild/protocompile v0.8.0 // indirect github.com/caio/go-tdigest/v4 v4.0.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cloudevents/sdk-go/v2 v2.15.2 github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 // indirect github.com/containerd/containerd v1.7.12 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/couchbase/gomemcached v0.1.3 // indirect - github.com/couchbase/goutils v0.1.0 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect - github.com/danieljoos/wincred v1.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dennwc/varint v1.0.0 // indirect github.com/devigned/tab v0.1.1 // indirect @@ -324,11 +314,8 @@ require ( github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect github.com/go-stack/stack v1.8.1 // indirect - github.com/goburrow/modbus v0.1.0 // indirect - github.com/goburrow/serial v0.1.1-0.20211022031912-bfb69110f8dd // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect - github.com/godbus/dbus/v5 v5.1.0 github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect @@ -346,7 +333,6 @@ require ( github.com/gorilla/schema v1.2.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect - github.com/grid-x/serial v0.0.0-20211107191517-583c7356b3aa // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect @@ -356,7 +342,6 @@ require ( github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/packer-plugin-sdk v0.3.2 // indirect github.com/hashicorp/serf v0.10.1 // indirect github.com/huandu/xstrings v1.3.3 // indirect @@ -366,7 +351,6 @@ require ( github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/puddle v1.3.0 // indirect - github.com/jaegertracing/jaeger v1.47.0 // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect github.com/jcmturner/gofork v1.7.6 // indirect @@ -388,8 +372,6 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-ieproxy v0.0.11 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mdlayher/genetlink v1.2.0 // indirect - github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/socket v0.4.1 // indirect github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 // indirect github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 // indirect @@ -410,7 +392,6 @@ require ( github.com/muhlemmer/gu v0.3.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect - github.com/naoina/go-stringutil v0.1.0 // indirect github.com/nats-io/jwt/v2 v2.5.3 // indirect github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect @@ -440,7 +421,6 @@ require ( github.com/signalfx/com_signalfx_metrics_protobuf v0.0.3 // indirect github.com/signalfx/gohistogram v0.0.0-20160107210732-1ccfd2ff5083 // indirect github.com/signalfx/sapm-proto v0.12.0 // indirect - github.com/sijms/go-ora/v2 v2.8.4 github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect @@ -453,13 +433,10 @@ require ( github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect github.com/vishvananda/netlink v1.2.1-beta.2 // indirect - github.com/vishvananda/netns v0.0.4 github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect - github.com/xdg/stringprep v1.0.3 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect @@ -482,10 +459,8 @@ require ( golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.19.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - golang.zx2c4.com/wireguard v0.0.0-20211209221555-9c9e7e272434 // indirect google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect - gopkg.in/fatih/pool.v2 v2.0.0 // indirect gopkg.in/fsnotify.v1 v1.4.7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect @@ -507,3 +482,31 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) + +require ( + code.cloudfoundry.org/clock v1.0.0 // indirect + github.com/Masterminds/semver/v3 v3.2.1 + github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3 // indirect + github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.7 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.7 // indirect + github.com/bitly/go-hostpool v0.1.0 // indirect + github.com/cloudevents/sdk-go/v2 v2.15.2 + github.com/couchbase/gomemcached v0.1.3 // indirect + github.com/couchbase/goutils v0.1.0 // indirect + github.com/danieljoos/wincred v1.2.0 // indirect + github.com/goburrow/modbus v0.1.0 // indirect + github.com/goburrow/serial v0.1.1-0.20211022031912-bfb69110f8dd // indirect + github.com/godbus/dbus/v5 v5.1.0 + github.com/grid-x/serial v0.0.0-20211107191517-583c7356b3aa // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/jaegertracing/jaeger v1.47.0 // indirect + github.com/mdlayher/genetlink v1.2.0 // indirect + github.com/mdlayher/netlink v1.7.2 // indirect + github.com/naoina/go-stringutil v0.1.0 // indirect + github.com/sijms/go-ora/v2 v2.8.4 + github.com/vishvananda/netns v0.0.4 + github.com/xdg/stringprep v1.0.3 // indirect + github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect + golang.zx2c4.com/wireguard v0.0.0-20211209221555-9c9e7e272434 // indirect + gopkg.in/fatih/pool.v2 v2.0.0 // indirect +) diff --git a/plugins/inputs/webhooks/sample.conf b/plugins/inputs/webhooks/sample.conf index 0e6cd4679f2c9..82c83fd6c9613 100644 --- a/plugins/inputs/webhooks/sample.conf +++ b/plugins/inputs/webhooks/sample.conf @@ -53,3 +53,18 @@ [inputs.webhooks.artifactory] path = "/artifactory" + + [inputs.webhooks.zabbix] + path = "/zabbix" + + ## ignore all text values + # ignore_text = true + + ## select the tag to create your metric names from + ## default is "component": + ## example: zabbix_component_health_network + # create_name_from_tag = "component" + + ## HTTP basic auth + #username = "" + #password = "" diff --git a/plugins/inputs/webhooks/webhooks.go b/plugins/inputs/webhooks/webhooks.go index fc5570a1b662d..bc8fd73ccb941 100644 --- a/plugins/inputs/webhooks/webhooks.go +++ b/plugins/inputs/webhooks/webhooks.go @@ -21,6 +21,7 @@ import ( "github.com/influxdata/telegraf/plugins/inputs/webhooks/papertrail" "github.com/influxdata/telegraf/plugins/inputs/webhooks/particle" "github.com/influxdata/telegraf/plugins/inputs/webhooks/rollbar" + "github.com/influxdata/telegraf/plugins/inputs/webhooks/zabbix" ) //go:embed sample.conf @@ -51,6 +52,7 @@ type Webhooks struct { Papertrail *papertrail.PapertrailWebhook `toml:"papertrail"` Particle *particle.ParticleWebhook `toml:"particle"` Artifactory *artifactory.ArtifactoryWebhook `toml:"artifactory"` + Zabbix *zabbix.ZabbixWebhook `toml:"zabbix"` Log telegraf.Logger `toml:"-"` diff --git a/plugins/inputs/webhooks/webhooks_test.go b/plugins/inputs/webhooks/webhooks_test.go index fe1c041d8dca8..201e93c7ce431 100644 --- a/plugins/inputs/webhooks/webhooks_test.go +++ b/plugins/inputs/webhooks/webhooks_test.go @@ -9,6 +9,7 @@ import ( "github.com/influxdata/telegraf/plugins/inputs/webhooks/papertrail" "github.com/influxdata/telegraf/plugins/inputs/webhooks/particle" "github.com/influxdata/telegraf/plugins/inputs/webhooks/rollbar" + "github.com/influxdata/telegraf/plugins/inputs/webhooks/zabbix" ) func TestAvailableWebhooks(t *testing.T) { @@ -47,4 +48,9 @@ func TestAvailableWebhooks(t *testing.T) { if !reflect.DeepEqual(wb.AvailableWebhooks(), expected) { t.Errorf("expected to be %v.\nGot %v", expected, wb.AvailableWebhooks()) } + wb.Zabbix = &zabbix.ZabbixWebhook{Path: "/zabbix"} + expected = append(expected, wb.Zabbix) + if !reflect.DeepEqual(wb.AvailableWebhooks(), expected) { + t.Errorf("expected to be %v.\nGot %v", expected, wb.AvailableWebhooks()) + } } diff --git a/plugins/inputs/webhooks/zabbix/README.md b/plugins/inputs/webhooks/zabbix/README.md new file mode 100644 index 0000000000000..613d88a5df77b --- /dev/null +++ b/plugins/inputs/webhooks/zabbix/README.md @@ -0,0 +1,51 @@ +# zabbix connector webhooks + +You should configure your Zabbix Connecotr to point at the `webhooks` service. `Data type` is `Item values` and you can use `Baisc` as `HTTP authentication`. + +## Events + +The titles of the following sections are links to the full payloads and details for each event. The body contains what information from the event is persisted. The format is as follows: + +```toml +# TAGS +* 'tagKey' = `tagValue` type +# FIELDS +* 'fieldKey' = `fieldValue` type +``` + +The tag values and field values show the place on the incoming JSON object where the data is sourced from. + +See [Zabbix Conectors](https://www.zabbix.com/documentation/current/en/manual/config/export/streaming) + +### `Zabbix Item Value` event + +**Metric Name** +The metric name is composed from a specific tag value, default is "component" + +Zabbix Tags: + `"component" = "health"` + `"component" = "network"` + +Metric Name: zabbix_component_health_network + +**Tags:** + +* 'item' = `item.name` string +* 'host_raw' = `item.host.host` string +* 'hostname' = `item.host.name` string +* 'houstgroups = `item.groups` string +* 'itemid' = `item.itemid` int + +Zabbix Tags are trasformed as follow: + +Zabbix Tags: + `"component" = "health"` + `"component" = "network"` + +Telegraf Tags: + 'tag_component' = `health,network` + +**Fields:** + +* 'value' = `item.value` int/float/string + diff --git a/plugins/inputs/webhooks/zabbix/zabbix_webhooks.go b/plugins/inputs/webhooks/zabbix/zabbix_webhooks.go new file mode 100644 index 0000000000000..d98cf056d1d2c --- /dev/null +++ b/plugins/inputs/webhooks/zabbix/zabbix_webhooks.go @@ -0,0 +1,70 @@ +package zabbix + +import ( + "encoding/json" + "bufio" + "net/http" + "fmt" + "strings" + "github.com/gorilla/mux" + + "github.com/influxdata/telegraf" + "github.com/influxdata/telegraf/plugins/common/auth" +) + +type ZabbixWebhook struct { + Path string + IgnoreText bool `toml:"ignore_text"` + CreateNameFrom string `toml:"create_name_from_tag"` + acc telegraf.Accumulator + log telegraf.Logger + auth.BasicAuth +} + +func (zb *ZabbixWebhook) Register(router *mux.Router, acc telegraf.Accumulator, log telegraf.Logger) { + router.HandleFunc(zb.Path, zb.eventHandler).Methods("POST") + zb.log = log + zb.log.Infof("Started the webhooks_zabbix on %s", zb.Path) + zb.acc = acc +} + +func (zb *ZabbixWebhook) eventHandler(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + + createNameFrom := "component" + if(zb.CreateNameFrom != "") { + createNameFrom = zb.CreateNameFrom + } + + + if !zb.Verify(r) { + w.WriteHeader(http.StatusUnauthorized) + return + } + + scanner := bufio.NewScanner(r.Body) + for scanner.Scan() { + var err error + line := []byte(scanner.Text()) + if(len(line) <= 10) { + continue + } + var item zabbix_item + err = json.Unmarshal(line, &item) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + fmt.Printf("Unmarshal Item faild: %s", err.Error()) + continue + } + if(!(item.Type == 0 || item.Type == 3) && zb.IgnoreText) { + continue + } + zb.acc.AddFields(strings.ToLower("zabbix_" + item.NameFromTag(createNameFrom)), item.Fields(), item.Tags(), item.Time()) + + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintln(w, "{\"response\": \"success\"}") +} + diff --git a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go new file mode 100644 index 0000000000000..0ba6ad07d7201 --- /dev/null +++ b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go @@ -0,0 +1,75 @@ +package zabbix + +import( + "strings" + "strconv" + "time" + "sort" +) + +type host struct { + Host string `json:"host"` + Name string `json:"name"` +} + +type tag struct { + Tag string `json:"tag"` + Value string `json:"value"` +} + +type zabbix_item struct { + Value any `json:"value"` + Itemname string `json:"name"` + Groups []string `json:"groups"` + Type int `json:"type"` + Host host `json:"host"` + ItemTags []tag `json:"item_tags"` + Itemid int `json:"itemid"` + Clock int64 `json:clock` + Ns int64 `json:ns` +} + +func (ni *zabbix_item) NameFromTag(t string) string { + var tags []string + for _, s := range ni.ItemTags { + if(strings.ToLower(s.Tag) == t) { + tags = append(tags, s.Value) + } + } + sort.Strings(tags) + return t + "_" + strings.Join(tags[:], "_") +} + +func (ni *zabbix_item) Tags() map[string]string { + res := map[string]string{ + "item": ni.Itemname, + "host_raw": ni.Host.Host, + "hostname": ni.Host.Name, + "hostgroups": strings.Join(ni.Groups[:], ","), + "itemid": strconv.Itoa(ni.Itemid), + } + for _, s := range ni.ItemTags { + var tag_name = "tag_" + s.Tag + if val, ok := res[tag_name]; ok{ + res[tag_name] = val + "," + s.Value + } else { + res[tag_name] = s.Value + } + } + return res +} + +func (ni *zabbix_item) Fields() map[string]interface{} { + if(ni.Type == 1 || ni.Type == 2 || ni.Type == 4) { + return map[string]interface{}{ + "text": ni.Value, + } + } + return map[string]interface{}{ + "value": ni.Value, + } +} + +func (ni *zabbix_item) Time() time.Time { + return time.Unix(ni.Clock, ni.Ns) +} \ No newline at end of file diff --git a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events_json_test.go b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events_json_test.go new file mode 100644 index 0000000000000..84166ac08f13e --- /dev/null +++ b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events_json_test.go @@ -0,0 +1,66 @@ +package zabbix + +import( + "strings" +) + +func ItemValueFloatJSON() string { + return strings.Replace(` + { + "host": { + "host": "10.248.65.148", + "name": "server1" + }, + "groups": [ + "UPS", + "SNMP" + ], + "item_tags": [ + { + "tag": "component", + "value": "health" + }, + { + "tag": "component", + "value": "network" + } + ], + "itemid": 54988, + "name": "ICMP: ICMP ping", + "clock": 1712352621, + "ns": 304061973, + "value": 1, + "type": 3 + }`,"\n"," ",-1) +} + + +func ItemValueTextJSON() string { + return strings.Replace(` + { + "host": { + "host": "10.248.65.148", + "name": "server1" + }, + "groups": [ + "UPS", + "SNMP" + ], + "item_tags": [ + { + "tag": "component", + "value": "health" + }, + { + "tag": "component", + "value": "network" + } + ], + "itemid": 54988, + "name": "ICMP: ICMP ping", + "clock": 1712352621, + "ns": 304061973, + "value": "up", + "type": 4 + }`,"\n"," ",-1) +} diff --git a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go new file mode 100644 index 0000000000000..c46762fe794d3 --- /dev/null +++ b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go @@ -0,0 +1,128 @@ +package zabbix + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/influxdata/telegraf/testutil" +) + +func postWebhooks(zb *ZabbixWebhook, eventBody string) *httptest.ResponseRecorder { + req, _ := http.NewRequest("POST", "/", strings.NewReader(eventBody)) + w := httptest.NewRecorder() + w.Code = 500 + + zb.eventHandler(w, req) + + return w +} + +func TestFloatItem(t *testing.T) { + var acc testutil.Accumulator + zb := &ZabbixWebhook{Path: "/zabbix", acc: &acc} + resp := postWebhooks(zb, ItemValueFloatJSON()) + if resp.Code != http.StatusOK { + t.Errorf("POST new_item returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK) + } + + fields := map[string]interface{}{ + "value": 1.0, + } + + tags := map[string]string{ + "item": "ICMP: ICMP ping", + "host_raw": "10.248.65.148", + "hostgroups": "UPS,SNMP", + "hostname": "server1", + "tag_component": "health,network", + "itemid": "54988", + } + + acc.AssertContainsTaggedFields(t, "zabbix_component_health_network", fields, tags) +} + + +func TestStringItem(t *testing.T) { + var acc testutil.Accumulator + zb := &ZabbixWebhook{Path: "/zabbix", acc: &acc} + resp := postWebhooks(zb, ItemValueTextJSON()) + if resp.Code != http.StatusOK { + t.Errorf("POST new_item returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK) + } + + fields := map[string]interface{}{ + "text": "up", + } + + tags := map[string]string{ + "item": "ICMP: ICMP ping", + "host_raw": "10.248.65.148", + "hostname": "server1", + "hostgroups": "UPS,SNMP", + "tag_component": "health,network", + "itemid": "54988", + } + + acc.AssertContainsTaggedFields(t, "zabbix_component_health_network", fields, tags) +} + + +func TestMultibleItems(t *testing.T) { + var acc testutil.Accumulator + zb := &ZabbixWebhook{Path: "/zabbix", acc: &acc} + resp := postWebhooks(zb, ItemValueFloatJSON() +"\n" + ItemValueTextJSON()) + if resp.Code != http.StatusOK { + t.Errorf("POST new_item returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK) + } + + fields := map[string]interface{}{ + "value": 1.0, + } + + tags := map[string]string{ + "item": "ICMP: ICMP ping", + "host_raw": "10.248.65.148", + "hostgroups": "UPS,SNMP", + "hostname": "server1", + "tag_component": "health,network", + "itemid": "54988", + } + + acc.AssertContainsTaggedFields(t, "zabbix_component_health_network", fields, tags) + + fields = map[string]interface{}{ + "text": "up", + } + acc.AssertContainsTaggedFields(t, "zabbix_component_health_network", fields, tags) +} + +func TestIgnoreTextItems(t *testing.T) { + var acc testutil.Accumulator + zb := &ZabbixWebhook{Path: "/zabbix", IgnoreText: true, acc: &acc} + resp := postWebhooks(zb, ItemValueFloatJSON() +"\n" + ItemValueTextJSON()) + if resp.Code != http.StatusOK { + t.Errorf("POST new_item returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK) + } + + fields := map[string]interface{}{ + "value": 1.0, + } + + tags := map[string]string{ + "item": "ICMP: ICMP ping", + "host_raw": "10.248.65.148", + "hostgroups": "UPS,SNMP", + "hostname": "server1", + "tag_component": "health,network", + "itemid": "54988", + } + + acc.AssertContainsTaggedFields(t, "zabbix_component_health_network", fields, tags) + + fields = map[string]interface{}{ + "text": "up", + } + acc.AssertDoesNotContainsTaggedFields(t, "zabbix_component_health_network", fields, tags) +} From be89ea75252d9e5cb9d90b0ad97964d879bc0fe4 Mon Sep 17 00:00:00 2001 From: shrank Date: Fri, 19 Apr 2024 12:07:10 -0700 Subject: [PATCH 2/5] reverted go.mod --- go.mod | 53 +++++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 1eda5aa5f6143..efcf323955f72 100644 --- a/go.mod +++ b/go.mod @@ -229,6 +229,7 @@ require ( cloud.google.com/go/compute v1.23.4 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.6 // indirect + code.cloudfoundry.org/clock v1.0.0 // indirect dario.cat/mergo v1.0.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -253,16 +254,20 @@ require ( github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect + github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/alecthomas/participle v0.4.1 // indirect github.com/andybalholm/brotli v1.1.0 // indirect github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect github.com/apache/arrow/go/v14 v14.0.2 // indirect + github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/awnumar/memcall v0.2.0 // indirect github.com/aws/aws-sdk-go v1.45.25 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect + github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.7 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.7 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect @@ -278,17 +283,22 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 // indirect github.com/awslabs/kinesis-aggregation/go v0.0.0-20210630091500-54e17340d32f // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bitly/go-hostpool v0.1.0 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/bufbuild/protocompile v0.8.0 // indirect github.com/caio/go-tdigest/v4 v4.0.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cloudevents/sdk-go/v2 v2.15.2 github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 // indirect github.com/containerd/containerd v1.7.12 // indirect github.com/containerd/log v0.1.0 // indirect + github.com/couchbase/gomemcached v0.1.3 // indirect + github.com/couchbase/goutils v0.1.0 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/danieljoos/wincred v1.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dennwc/varint v1.0.0 // indirect github.com/devigned/tab v0.1.1 // indirect @@ -314,8 +324,11 @@ require ( github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect github.com/go-stack/stack v1.8.1 // indirect + github.com/goburrow/modbus v0.1.0 // indirect + github.com/goburrow/serial v0.1.1-0.20211022031912-bfb69110f8dd // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/godbus/dbus/v5 v5.1.0 github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect @@ -333,6 +346,7 @@ require ( github.com/gorilla/schema v1.2.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect + github.com/grid-x/serial v0.0.0-20211107191517-583c7356b3aa // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect @@ -342,6 +356,7 @@ require ( github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/packer-plugin-sdk v0.3.2 // indirect github.com/hashicorp/serf v0.10.1 // indirect github.com/huandu/xstrings v1.3.3 // indirect @@ -351,6 +366,7 @@ require ( github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/puddle v1.3.0 // indirect + github.com/jaegertracing/jaeger v1.47.0 // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect github.com/jcmturner/gofork v1.7.6 // indirect @@ -372,6 +388,8 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-ieproxy v0.0.11 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mdlayher/genetlink v1.2.0 // indirect + github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/socket v0.4.1 // indirect github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 // indirect github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 // indirect @@ -392,6 +410,7 @@ require ( github.com/muhlemmer/gu v0.3.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect + github.com/naoina/go-stringutil v0.1.0 // indirect github.com/nats-io/jwt/v2 v2.5.3 // indirect github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect @@ -421,6 +440,7 @@ require ( github.com/signalfx/com_signalfx_metrics_protobuf v0.0.3 // indirect github.com/signalfx/gohistogram v0.0.0-20160107210732-1ccfd2ff5083 // indirect github.com/signalfx/sapm-proto v0.12.0 // indirect + github.com/sijms/go-ora/v2 v2.8.4 github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect @@ -433,10 +453,13 @@ require ( github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect github.com/vishvananda/netlink v1.2.1-beta.2 // indirect + github.com/vishvananda/netns v0.0.4 github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/xdg/stringprep v1.0.3 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect @@ -459,8 +482,10 @@ require ( golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.19.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect + golang.zx2c4.com/wireguard v0.0.0-20211209221555-9c9e7e272434 // indirect google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect + gopkg.in/fatih/pool.v2 v2.0.0 // indirect gopkg.in/fsnotify.v1 v1.4.7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect @@ -482,31 +507,3 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) - -require ( - code.cloudfoundry.org/clock v1.0.0 // indirect - github.com/Masterminds/semver/v3 v3.2.1 - github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3 // indirect - github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.13.7 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.7 // indirect - github.com/bitly/go-hostpool v0.1.0 // indirect - github.com/cloudevents/sdk-go/v2 v2.15.2 - github.com/couchbase/gomemcached v0.1.3 // indirect - github.com/couchbase/goutils v0.1.0 // indirect - github.com/danieljoos/wincred v1.2.0 // indirect - github.com/goburrow/modbus v0.1.0 // indirect - github.com/goburrow/serial v0.1.1-0.20211022031912-bfb69110f8dd // indirect - github.com/godbus/dbus/v5 v5.1.0 - github.com/grid-x/serial v0.0.0-20211107191517-583c7356b3aa // indirect - github.com/hashicorp/golang-lru v1.0.2 // indirect - github.com/jaegertracing/jaeger v1.47.0 // indirect - github.com/mdlayher/genetlink v1.2.0 // indirect - github.com/mdlayher/netlink v1.7.2 // indirect - github.com/naoina/go-stringutil v0.1.0 // indirect - github.com/sijms/go-ora/v2 v2.8.4 - github.com/vishvananda/netns v0.0.4 - github.com/xdg/stringprep v1.0.3 // indirect - github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - golang.zx2c4.com/wireguard v0.0.0-20211209221555-9c9e7e272434 // indirect - gopkg.in/fatih/pool.v2 v2.0.0 // indirect -) From 1a7ca814026328d0a2a5c31c49134f3cbff38286 Mon Sep 17 00:00:00 2001 From: shrank Date: Fri, 19 Apr 2024 12:18:10 -0700 Subject: [PATCH 3/5] ran gofmt --- plugins/inputs/webhooks/webhooks.go | 2 +- .../inputs/webhooks/zabbix/zabbix_webhooks.go | 30 +++++------ .../webhooks/zabbix/zabbix_webhooks_events.go | 42 +++++++-------- .../zabbix_webhooks_events_json_test.go | 7 ++- .../webhooks/zabbix/zabbix_webhooks_test.go | 54 +++++++++---------- 5 files changed, 65 insertions(+), 70 deletions(-) diff --git a/plugins/inputs/webhooks/webhooks.go b/plugins/inputs/webhooks/webhooks.go index bc8fd73ccb941..b08f2b25babbf 100644 --- a/plugins/inputs/webhooks/webhooks.go +++ b/plugins/inputs/webhooks/webhooks.go @@ -52,7 +52,7 @@ type Webhooks struct { Papertrail *papertrail.PapertrailWebhook `toml:"papertrail"` Particle *particle.ParticleWebhook `toml:"particle"` Artifactory *artifactory.ArtifactoryWebhook `toml:"artifactory"` - Zabbix *zabbix.ZabbixWebhook `toml:"zabbix"` + Zabbix *zabbix.ZabbixWebhook `toml:"zabbix"` Log telegraf.Logger `toml:"-"` diff --git a/plugins/inputs/webhooks/zabbix/zabbix_webhooks.go b/plugins/inputs/webhooks/zabbix/zabbix_webhooks.go index d98cf056d1d2c..2848c3eacf6ae 100644 --- a/plugins/inputs/webhooks/zabbix/zabbix_webhooks.go +++ b/plugins/inputs/webhooks/zabbix/zabbix_webhooks.go @@ -1,23 +1,23 @@ package zabbix import ( - "encoding/json" "bufio" - "net/http" + "encoding/json" "fmt" - "strings" "github.com/gorilla/mux" + "net/http" + "strings" "github.com/influxdata/telegraf" "github.com/influxdata/telegraf/plugins/common/auth" ) type ZabbixWebhook struct { - Path string - IgnoreText bool `toml:"ignore_text"` + Path string + IgnoreText bool `toml:"ignore_text"` CreateNameFrom string `toml:"create_name_from_tag"` - acc telegraf.Accumulator - log telegraf.Logger + acc telegraf.Accumulator + log telegraf.Logger auth.BasicAuth } @@ -32,21 +32,20 @@ func (zb *ZabbixWebhook) eventHandler(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() createNameFrom := "component" - if(zb.CreateNameFrom != "") { + if zb.CreateNameFrom != "" { createNameFrom = zb.CreateNameFrom } - if !zb.Verify(r) { w.WriteHeader(http.StatusUnauthorized) return } - + scanner := bufio.NewScanner(r.Body) for scanner.Scan() { - var err error + var err error line := []byte(scanner.Text()) - if(len(line) <= 10) { + if len(line) <= 10 { continue } var item zabbix_item @@ -56,15 +55,14 @@ func (zb *ZabbixWebhook) eventHandler(w http.ResponseWriter, r *http.Request) { fmt.Printf("Unmarshal Item faild: %s", err.Error()) continue } - if(!(item.Type == 0 || item.Type == 3) && zb.IgnoreText) { + if !(item.Type == 0 || item.Type == 3) && zb.IgnoreText { continue } - zb.acc.AddFields(strings.ToLower("zabbix_" + item.NameFromTag(createNameFrom)), item.Fields(), item.Tags(), item.Time()) + zb.acc.AddFields(strings.ToLower("zabbix_"+item.NameFromTag(createNameFrom)), item.Fields(), item.Tags(), item.Time()) } - + w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) fmt.Fprintln(w, "{\"response\": \"success\"}") } - diff --git a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go index 0ba6ad07d7201..784d3d9e2f3c8 100644 --- a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go +++ b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go @@ -1,10 +1,10 @@ package zabbix -import( - "strings" +import ( + "sort" "strconv" + "strings" "time" - "sort" ) type host struct { @@ -13,26 +13,26 @@ type host struct { } type tag struct { - Tag string `json:"tag"` + Tag string `json:"tag"` Value string `json:"value"` } type zabbix_item struct { - Value any `json:"value"` - Itemname string `json:"name"` - Groups []string `json:"groups"` - Type int `json:"type"` - Host host `json:"host"` - ItemTags []tag `json:"item_tags"` - Itemid int `json:"itemid"` - Clock int64 `json:clock` - Ns int64 `json:ns` + Value any `json:"value"` + Itemname string `json:"name"` + Groups []string `json:"groups"` + Type int `json:"type"` + Host host `json:"host"` + ItemTags []tag `json:"item_tags"` + Itemid int `json:"itemid"` + Clock int64 `json:clock` + Ns int64 `json:ns` } func (ni *zabbix_item) NameFromTag(t string) string { var tags []string for _, s := range ni.ItemTags { - if(strings.ToLower(s.Tag) == t) { + if strings.ToLower(s.Tag) == t { tags = append(tags, s.Value) } } @@ -42,15 +42,15 @@ func (ni *zabbix_item) NameFromTag(t string) string { func (ni *zabbix_item) Tags() map[string]string { res := map[string]string{ - "item": ni.Itemname, + "item": ni.Itemname, "host_raw": ni.Host.Host, - "hostname": ni.Host.Name, - "hostgroups": strings.Join(ni.Groups[:], ","), - "itemid": strconv.Itoa(ni.Itemid), + "hostname": ni.Host.Name, + "hostgroups": strings.Join(ni.Groups[:], ","), + "itemid": strconv.Itoa(ni.Itemid), } for _, s := range ni.ItemTags { var tag_name = "tag_" + s.Tag - if val, ok := res[tag_name]; ok{ + if val, ok := res[tag_name]; ok { res[tag_name] = val + "," + s.Value } else { res[tag_name] = s.Value @@ -60,7 +60,7 @@ func (ni *zabbix_item) Tags() map[string]string { } func (ni *zabbix_item) Fields() map[string]interface{} { - if(ni.Type == 1 || ni.Type == 2 || ni.Type == 4) { + if ni.Type == 1 || ni.Type == 2 || ni.Type == 4 { return map[string]interface{}{ "text": ni.Value, } @@ -72,4 +72,4 @@ func (ni *zabbix_item) Fields() map[string]interface{} { func (ni *zabbix_item) Time() time.Time { return time.Unix(ni.Clock, ni.Ns) -} \ No newline at end of file +} diff --git a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events_json_test.go b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events_json_test.go index 84166ac08f13e..227f9af194535 100644 --- a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events_json_test.go +++ b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events_json_test.go @@ -1,6 +1,6 @@ package zabbix -import( +import ( "strings" ) @@ -31,10 +31,9 @@ func ItemValueFloatJSON() string { "ns": 304061973, "value": 1, "type": 3 - }`,"\n"," ",-1) + }`, "\n", " ", -1) } - func ItemValueTextJSON() string { return strings.Replace(` { @@ -62,5 +61,5 @@ func ItemValueTextJSON() string { "ns": 304061973, "value": "up", "type": 4 - }`,"\n"," ",-1) + }`, "\n", " ", -1) } diff --git a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go index c46762fe794d3..29794260a8000 100644 --- a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go +++ b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go @@ -32,18 +32,17 @@ func TestFloatItem(t *testing.T) { } tags := map[string]string{ - "item": "ICMP: ICMP ping", - "host_raw": "10.248.65.148", - "hostgroups": "UPS,SNMP", - "hostname": "server1", - "tag_component": "health,network", - "itemid": "54988", + "item": "ICMP: ICMP ping", + "host_raw": "10.248.65.148", + "hostgroups": "UPS,SNMP", + "hostname": "server1", + "tag_component": "health,network", + "itemid": "54988", } acc.AssertContainsTaggedFields(t, "zabbix_component_health_network", fields, tags) } - func TestStringItem(t *testing.T) { var acc testutil.Accumulator zb := &ZabbixWebhook{Path: "/zabbix", acc: &acc} @@ -57,22 +56,21 @@ func TestStringItem(t *testing.T) { } tags := map[string]string{ - "item": "ICMP: ICMP ping", - "host_raw": "10.248.65.148", - "hostname": "server1", - "hostgroups": "UPS,SNMP", - "tag_component": "health,network", - "itemid": "54988", + "item": "ICMP: ICMP ping", + "host_raw": "10.248.65.148", + "hostname": "server1", + "hostgroups": "UPS,SNMP", + "tag_component": "health,network", + "itemid": "54988", } acc.AssertContainsTaggedFields(t, "zabbix_component_health_network", fields, tags) } - func TestMultibleItems(t *testing.T) { var acc testutil.Accumulator zb := &ZabbixWebhook{Path: "/zabbix", acc: &acc} - resp := postWebhooks(zb, ItemValueFloatJSON() +"\n" + ItemValueTextJSON()) + resp := postWebhooks(zb, ItemValueFloatJSON()+"\n"+ItemValueTextJSON()) if resp.Code != http.StatusOK { t.Errorf("POST new_item returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK) } @@ -82,12 +80,12 @@ func TestMultibleItems(t *testing.T) { } tags := map[string]string{ - "item": "ICMP: ICMP ping", - "host_raw": "10.248.65.148", - "hostgroups": "UPS,SNMP", - "hostname": "server1", - "tag_component": "health,network", - "itemid": "54988", + "item": "ICMP: ICMP ping", + "host_raw": "10.248.65.148", + "hostgroups": "UPS,SNMP", + "hostname": "server1", + "tag_component": "health,network", + "itemid": "54988", } acc.AssertContainsTaggedFields(t, "zabbix_component_health_network", fields, tags) @@ -101,7 +99,7 @@ func TestMultibleItems(t *testing.T) { func TestIgnoreTextItems(t *testing.T) { var acc testutil.Accumulator zb := &ZabbixWebhook{Path: "/zabbix", IgnoreText: true, acc: &acc} - resp := postWebhooks(zb, ItemValueFloatJSON() +"\n" + ItemValueTextJSON()) + resp := postWebhooks(zb, ItemValueFloatJSON()+"\n"+ItemValueTextJSON()) if resp.Code != http.StatusOK { t.Errorf("POST new_item returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK) } @@ -111,12 +109,12 @@ func TestIgnoreTextItems(t *testing.T) { } tags := map[string]string{ - "item": "ICMP: ICMP ping", - "host_raw": "10.248.65.148", - "hostgroups": "UPS,SNMP", - "hostname": "server1", - "tag_component": "health,network", - "itemid": "54988", + "item": "ICMP: ICMP ping", + "host_raw": "10.248.65.148", + "hostgroups": "UPS,SNMP", + "hostname": "server1", + "tag_component": "health,network", + "itemid": "54988", } acc.AssertContainsTaggedFields(t, "zabbix_component_health_network", fields, tags) From bac8f7422201cb7006844dc59bf789bf6908af8b Mon Sep 17 00:00:00 2001 From: shrank Date: Fri, 19 Apr 2024 13:27:45 -0700 Subject: [PATCH 4/5] sort tags and hostgroups --- .../webhooks/zabbix/zabbix_webhooks_events.go | 13 ++++++++++--- .../inputs/webhooks/zabbix/zabbix_webhooks_test.go | 8 ++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go index 784d3d9e2f3c8..bf3d0968dc13c 100644 --- a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go +++ b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go @@ -41,6 +41,7 @@ func (ni *zabbix_item) NameFromTag(t string) string { } func (ni *zabbix_item) Tags() map[string]string { + sort.Strings(ni.Groups) res := map[string]string{ "item": ni.Itemname, "host_raw": ni.Host.Host, @@ -48,14 +49,20 @@ func (ni *zabbix_item) Tags() map[string]string { "hostgroups": strings.Join(ni.Groups[:], ","), "itemid": strconv.Itoa(ni.Itemid), } + tag_map := map[string][]string{} for _, s := range ni.ItemTags { var tag_name = "tag_" + s.Tag - if val, ok := res[tag_name]; ok { - res[tag_name] = val + "," + s.Value + if _, ok := tag_map[tag_name]; ok { + tag_map[tag_name] = append(tag_map[tag_name], s.Value) } else { - res[tag_name] = s.Value + tag_map[tag_name] = []string{s.Value} } } + for k, v := range tag_map { + sort.Strings(v) + res[k] = strings.Join(v[:], ",") + } + return res } diff --git a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go index 29794260a8000..ab293fb41c7e9 100644 --- a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go +++ b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_test.go @@ -34,7 +34,7 @@ func TestFloatItem(t *testing.T) { tags := map[string]string{ "item": "ICMP: ICMP ping", "host_raw": "10.248.65.148", - "hostgroups": "UPS,SNMP", + "hostgroups": "SNMP,UPS", "hostname": "server1", "tag_component": "health,network", "itemid": "54988", @@ -59,7 +59,7 @@ func TestStringItem(t *testing.T) { "item": "ICMP: ICMP ping", "host_raw": "10.248.65.148", "hostname": "server1", - "hostgroups": "UPS,SNMP", + "hostgroups": "SNMP,UPS", "tag_component": "health,network", "itemid": "54988", } @@ -82,7 +82,7 @@ func TestMultibleItems(t *testing.T) { tags := map[string]string{ "item": "ICMP: ICMP ping", "host_raw": "10.248.65.148", - "hostgroups": "UPS,SNMP", + "hostgroups": "SNMP,UPS", "hostname": "server1", "tag_component": "health,network", "itemid": "54988", @@ -111,7 +111,7 @@ func TestIgnoreTextItems(t *testing.T) { tags := map[string]string{ "item": "ICMP: ICMP ping", "host_raw": "10.248.65.148", - "hostgroups": "UPS,SNMP", + "hostgroups": "SNMP,UPS", "hostname": "server1", "tag_component": "health,network", "itemid": "54988", From 3817813403427b6188ade5b04630eb7e60167be3 Mon Sep 17 00:00:00 2001 From: shrank Date: Fri, 19 Apr 2024 13:28:30 -0700 Subject: [PATCH 5/5] ran gofmt --- plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go index bf3d0968dc13c..aa99b0160a753 100644 --- a/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go +++ b/plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go @@ -62,7 +62,7 @@ func (ni *zabbix_item) Tags() map[string]string { sort.Strings(v) res[k] = strings.Join(v[:], ",") } - + return res }