Skip to content

Commit

Permalink
Support item tags, fixes #1258
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderzobnin committed Aug 9, 2021
1 parent c6441cc commit 9159738
Show file tree
Hide file tree
Showing 15 changed files with 565 additions and 355 deletions.
1 change: 1 addition & 0 deletions pkg/datasource/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion pkg/datasource/zabbix.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
69 changes: 67 additions & 2 deletions pkg/zabbix/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package zabbix

import (
"context"
"strconv"
"strings"

"github.com/grafana/grafana-plugin-sdk-go/backend"
)
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions pkg/zabbix/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,19 @@ 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 {
ID string `json:"hostid,omitempty"`
Name string `json:"name,omitempty"`
}

type ItemTag struct {
Tag string `json:"tag,omitempty"`
Value string `json:"value,omitempty"`
}

type Trend []TrendPoint

type TrendPoint struct {
Expand Down
8 changes: 8 additions & 0 deletions pkg/zabbix/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
19 changes: 15 additions & 4 deletions pkg/zabbix/zabbix.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/datasource-zabbix/datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
resultPromise = this.zabbix.getApps(queryModel.group, queryModel.host, queryModel.application);
break;
case VariableQueryTypes.Item:
resultPromise = this.zabbix.getItems(queryModel.group, queryModel.host, queryModel.application, queryModel.item);
resultPromise = this.zabbix.getItems(queryModel.group, queryModel.host, queryModel.application, null, queryModel.item);
break;
case VariableQueryTypes.ItemValues:
const range = options?.range;
Expand Down
13 changes: 12 additions & 1 deletion src/datasource-zabbix/migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function isGrafana2target(target) {
if (!target.mode || target.mode === 0 || target.mode === 2) {
if ((target.hostFilter || target.itemFilter || target.downsampleFunction ||
(target.host && target.host.host)) &&
(target.item.filter === undefined && target.host.filter === undefined)) {
(target.item.filter === undefined && target.host.filter === undefined)) {
return true;
} else {
return false;
Expand Down Expand Up @@ -68,6 +68,15 @@ function migrateProblemSort(target) {
}
}

function migrateApplications(target) {
if (!target.itemTag) {
target.itemTag = { filter: '' };
if (target.application?.filter) {
target.itemTag.filter = `Application: ${target.application?.filter}`;
}
}
}

export function migrate(target) {
target.resultFormat = target.resultFormat || 'time_series';
target = fixTargetGroup(target);
Expand All @@ -78,6 +87,7 @@ export function migrate(target) {
migrateQueryType(target);
migrateSLA(target);
migrateProblemSort(target);
migrateApplications(target);
return target;
}

Expand All @@ -97,6 +107,7 @@ function convertToRegex(str) {
}

export const DS_CONFIG_SCHEMA = 2;

export function migrateDSConfig(jsonData) {
if (!jsonData) {
jsonData = {};
Expand Down
Loading

0 comments on commit 9159738

Please sign in to comment.