Support item tags, fixes #1258
This commit is contained in:
@@ -75,6 +75,7 @@ type QueryModel struct {
|
||||
Group QueryFilter `json:"group"`
|
||||
Host QueryFilter `json:"host"`
|
||||
Application QueryFilter `json:"application"`
|
||||
ItemTag QueryFilter `json:"itemTag"`
|
||||
Item QueryFilter `json:"item"`
|
||||
|
||||
// Item ID mode
|
||||
|
||||
@@ -47,9 +47,10 @@ func (ds *ZabbixDatasourceInstance) queryNumericItems(ctx context.Context, query
|
||||
groupFilter := query.Group.Filter
|
||||
hostFilter := query.Host.Filter
|
||||
appFilter := query.Application.Filter
|
||||
itemTagFilter := query.ItemTag.Filter
|
||||
itemFilter := query.Item.Filter
|
||||
|
||||
items, err := ds.zabbix.GetItems(ctx, groupFilter, hostFilter, appFilter, itemFilter, "num")
|
||||
items, err := ds.zabbix.GetItems(ctx, groupFilter, hostFilter, appFilter, itemTagFilter, itemFilter, "num")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package zabbix
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
)
|
||||
@@ -78,7 +80,7 @@ func (ds *Zabbix) getTrend(ctx context.Context, itemids []string, timeRange back
|
||||
return trend, err
|
||||
}
|
||||
|
||||
func (ds *Zabbix) GetItems(ctx context.Context, groupFilter string, hostFilter string, appFilter string, itemFilter string, itemType string) ([]*Item, error) {
|
||||
func (ds *Zabbix) GetItems(ctx context.Context, groupFilter string, hostFilter string, appFilter string, itemTagFilter string, itemFilter string, itemType string) ([]*Item, error) {
|
||||
hosts, err := ds.GetHosts(ctx, groupFilter, hostFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -90,7 +92,8 @@ func (ds *Zabbix) GetItems(ctx context.Context, groupFilter string, hostFilter s
|
||||
|
||||
apps, err := ds.GetApps(ctx, groupFilter, hostFilter, appFilter)
|
||||
// Apps not supported in Zabbix 5.4 and higher
|
||||
if isAppMethodNotFoundError(err) {
|
||||
isZabbix54orHigher := isAppMethodNotFoundError(err)
|
||||
if isZabbix54orHigher {
|
||||
apps = []Application{}
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
@@ -107,9 +110,50 @@ func (ds *Zabbix) GetItems(ctx context.Context, groupFilter string, hostFilter s
|
||||
allItems, err = ds.GetAllItems(ctx, nil, appids, itemType)
|
||||
}
|
||||
|
||||
if isZabbix54orHigher && itemTagFilter != "" {
|
||||
allItems, err = filterItemsByTag(allItems, itemTagFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return filterItemsByQuery(allItems, itemFilter)
|
||||
}
|
||||
|
||||
func filterItemsByTag(items []*Item, filter string) ([]*Item, error) {
|
||||
re, err := parseFilter(filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var filteredItems []*Item
|
||||
for _, i := range items {
|
||||
if len(i.Tags) == 0 && filter == "/.*/" {
|
||||
filteredItems = append(filteredItems, i)
|
||||
}
|
||||
|
||||
if len(i.Tags) > 0 {
|
||||
var tags []string
|
||||
for _, t := range i.Tags {
|
||||
tags = append(tags, itemTagToString(t))
|
||||
}
|
||||
for _, t := range tags {
|
||||
if re != nil {
|
||||
if re.MatchString(t) {
|
||||
filteredItems = append(filteredItems, i)
|
||||
break
|
||||
}
|
||||
} else if t == filter {
|
||||
filteredItems = append(filteredItems, i)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filteredItems, nil
|
||||
}
|
||||
|
||||
func filterItemsByQuery(items []*Item, filter string) ([]*Item, error) {
|
||||
re, err := parseFilter(filter)
|
||||
if err != nil {
|
||||
@@ -259,6 +303,10 @@ func (ds *Zabbix) GetAllItems(ctx context.Context, hostids []string, appids []st
|
||||
filter["value_type"] = []int{1, 2, 4}
|
||||
}
|
||||
|
||||
if ds.version >= 54 {
|
||||
params["selectTags"] = "extend"
|
||||
}
|
||||
|
||||
result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "item.get", Params: params})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -347,6 +395,23 @@ func (ds *Zabbix) GetAllGroups(ctx context.Context) ([]Group, error) {
|
||||
return groups, err
|
||||
}
|
||||
|
||||
func (ds *Zabbix) GetVersion(ctx context.Context) (int, error) {
|
||||
result, err := ds.request(ctx, "apiinfo.version", ZabbixAPIParams{})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var version string
|
||||
err = convertTo(result, &version)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
version = strings.Replace(version[0:3], ".", "", 1)
|
||||
versionNum, err := strconv.Atoi(version)
|
||||
return versionNum, err
|
||||
}
|
||||
|
||||
func isAppMethodNotFoundError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
|
||||
@@ -51,6 +51,7 @@ type Item struct {
|
||||
Delay string `json:"delay,omitempty"`
|
||||
Units string `json:"units,omitempty"`
|
||||
ValueMapID string `json:"valuemapid,omitempty"`
|
||||
Tags []ItemTag `json:"tags,omitempty"`
|
||||
}
|
||||
|
||||
type ItemHost struct {
|
||||
@@ -58,6 +59,11 @@ type ItemHost struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
type ItemTag struct {
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
type Trend []TrendPoint
|
||||
|
||||
type TrendPoint struct {
|
||||
|
||||
@@ -85,3 +85,11 @@ func parseFilter(filter string) (*regexp.Regexp, error) {
|
||||
|
||||
return regexp.Compile(pattern)
|
||||
}
|
||||
|
||||
func itemTagToString(tag ItemTag) string {
|
||||
if tag.Value != "" {
|
||||
return fmt.Sprintf("%s: %s", tag.Tag, tag.Value)
|
||||
} else {
|
||||
return tag.Tag
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,11 @@ import (
|
||||
// Zabbix is a wrapper for Zabbix API. It wraps Zabbix API queries and performs authentication, adds caching,
|
||||
// deduplication and other performance optimizations.
|
||||
type Zabbix struct {
|
||||
api *zabbixapi.ZabbixAPI
|
||||
dsInfo *backend.DataSourceInstanceSettings
|
||||
cache *ZabbixCache
|
||||
logger log.Logger
|
||||
api *zabbixapi.ZabbixAPI
|
||||
dsInfo *backend.DataSourceInstanceSettings
|
||||
cache *ZabbixCache
|
||||
version int
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
// New returns new instance of Zabbix client.
|
||||
@@ -49,6 +50,16 @@ func (ds *Zabbix) Request(ctx context.Context, apiReq *ZabbixAPIRequest) (*simpl
|
||||
var resultJson *simplejson.Json
|
||||
var err error
|
||||
|
||||
if ds.version == 0 {
|
||||
version, err := ds.GetVersion(ctx)
|
||||
if err != nil {
|
||||
ds.logger.Error("Error querying Zabbix version", "error", err)
|
||||
} else {
|
||||
ds.logger.Debug("Got Zabbix version", "version", version)
|
||||
ds.version = version
|
||||
}
|
||||
}
|
||||
|
||||
cachedResult, queryExistInCache := ds.cache.GetAPIRequest(apiReq)
|
||||
if !queryExistInCache {
|
||||
resultJson, err = ds.request(ctx, apiReq.Method, apiReq.Params)
|
||||
|
||||
Reference in New Issue
Block a user