Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zabbix #16513

Closed
wants to merge 6 commits into from
Closed

Zabbix #16513

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions plugins/inputs/webhooks/sample.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ""
2 changes: 2 additions & 0 deletions plugins/inputs/webhooks/webhooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -43,6 +44,7 @@ type Webhooks struct {
Papertrail *papertrail.Webhook `toml:"papertrail"`
Particle *particle.Webhook `toml:"particle"`
Rollbar *rollbar.Webhook `toml:"rollbar"`
Zabbix *zabbix.ZabbixWebhook `toml:"zabbix"`

Log telegraf.Logger `toml:"-"`

Expand Down
6 changes: 6 additions & 0 deletions plugins/inputs/webhooks/webhooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,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) {
Expand Down Expand Up @@ -61,4 +62,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())
}
}
51 changes: 51 additions & 0 deletions plugins/inputs/webhooks/zabbix/README.md
Original file line number Diff line number Diff line change
@@ -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

68 changes: 68 additions & 0 deletions plugins/inputs/webhooks/zabbix/zabbix_webhooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package zabbix

import (
"bufio"
"encoding/json"
"fmt"
"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"`
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\"}")
}
82 changes: 82 additions & 0 deletions plugins/inputs/webhooks/zabbix/zabbix_webhooks_events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package zabbix

import (
"sort"
"strconv"
"strings"
"time"
)

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 {
sort.Strings(ni.Groups)
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),
}
tag_map := map[string][]string{}
for _, s := range ni.ItemTags {
var tag_name = "tag_" + s.Tag
if _, ok := tag_map[tag_name]; ok {
tag_map[tag_name] = append(tag_map[tag_name], s.Value)
} else {
tag_map[tag_name] = []string{s.Value}
}
}
for k, v := range tag_map {
sort.Strings(v)
res[k] = strings.Join(v[:], ",")
}

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)
}
65 changes: 65 additions & 0 deletions plugins/inputs/webhooks/zabbix/zabbix_webhooks_events_json_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
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)
}
Loading
Loading