From 37573e0152de80dcfd2f9504642150b60748b355 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Mon, 24 May 2021 10:46:28 +0300 Subject: [PATCH] Refactor filters --- Makefile | 2 +- pkg/zabbix/methods.go | 180 ++++++++++++++++------------ pkg/zabbix/models.go | 16 +++ pkg/zabbix/type_converters.go | 21 ++++ src/datasource-zabbix/datasource.ts | 2 +- 5 files changed, 144 insertions(+), 77 deletions(-) create mode 100644 pkg/zabbix/type_converters.go diff --git a/Makefile b/Makefile index ad22d53..a1ed441 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ build-frontend: build-backend: env GOOS=linux go build -o ./dist/zabbix-plugin_linux_amd64 ./pkg build-debug: - env GOOS=linux go build -gcflags=all="-N -l" -o ./dist/zabbix-plugin_linux_amd64 ./pkg + env GOOS=linux go build -gcflags="all=-N -l" -o ./dist/zabbix-plugin_linux_amd64 ./pkg # Build for specific platform build-backend-windows: extension = .exe diff --git a/pkg/zabbix/methods.go b/pkg/zabbix/methods.go index ca98b72..9c7e2c1 100644 --- a/pkg/zabbix/methods.go +++ b/pkg/zabbix/methods.go @@ -2,170 +2,172 @@ package zabbix import ( "context" - "encoding/json" - - "github.com/bitly/go-simplejson" ) -func (ds *Zabbix) GetItems(ctx context.Context, groupFilter string, hostFilter string, appFilter string, itemFilter string, itemType string) (Items, error) { +func (ds *Zabbix) GetItems(ctx context.Context, groupFilter string, hostFilter string, appFilter string, itemFilter string, itemType string) ([]Item, error) { hosts, err := ds.GetHosts(ctx, groupFilter, hostFilter) if err != nil { return nil, err } var hostids []string - for _, k := range hosts { - hostids = append(hostids, k["hostid"].(string)) + for _, host := range hosts { + hostids = append(hostids, host.ID) } apps, err := ds.GetApps(ctx, groupFilter, hostFilter, appFilter) // Apps not supported in Zabbix 5.4 and higher if isAppMethodNotFoundError(err) { - apps = []map[string]interface{}{} + apps = []Application{} } else if err != nil { return nil, err } var appids []string - for _, l := range apps { - appids = append(appids, l["applicationid"].(string)) + for _, app := range apps { + appids = append(appids, app.ID) } - var allItems *simplejson.Json + var allItems []Item if len(hostids) > 0 { allItems, err = ds.GetAllItems(ctx, hostids, nil, itemType) } else if len(appids) > 0 { allItems, err = ds.GetAllItems(ctx, nil, appids, itemType) } - var items Items + return filterItemsByQuery(allItems, itemFilter) +} - if allItems == nil { - items = Items{} - } else { - itemsJSON, err := allItems.MarshalJSON() - if err != nil { - return nil, err - } - - err = json.Unmarshal(itemsJSON, &items) - if err != nil { - return nil, err - } - } - - re, err := parseFilter(itemFilter) +func filterItemsByQuery(items []Item, filter string) ([]Item, error) { + re, err := parseFilter(filter) if err != nil { return nil, err } - filteredItems := Items{} - for _, item := range items { - itemName := item.ExpandItem() - if item.Status == "0" { - if re != nil { - if re.MatchString(itemName) { - filteredItems = append(filteredItems, item) - } - } else if itemName == itemFilter { - filteredItems = append(filteredItems, item) + var filteredItems []Item + for _, i := range items { + name := i.Name + if re != nil { + if re.MatchString(name) { + filteredItems = append(filteredItems, i) } + } else if name == filter { + filteredItems = append(filteredItems, i) } + } + return filteredItems, nil } -func (ds *Zabbix) GetApps(ctx context.Context, groupFilter string, hostFilter string, appFilter string) ([]map[string]interface{}, error) { +func (ds *Zabbix) GetApps(ctx context.Context, groupFilter string, hostFilter string, appFilter string) ([]Application, error) { hosts, err := ds.GetHosts(ctx, groupFilter, hostFilter) if err != nil { return nil, err } var hostids []string - for _, k := range hosts { - hostids = append(hostids, k["hostid"].(string)) + for _, host := range hosts { + hostids = append(hostids, host.ID) } allApps, err := ds.GetAllApps(ctx, hostids) if err != nil { return nil, err } - re, err := parseFilter(appFilter) + return filterAppsByQuery(allApps, appFilter) +} + +func filterAppsByQuery(items []Application, filter string) ([]Application, error) { + re, err := parseFilter(filter) if err != nil { return nil, err } - var apps []map[string]interface{} - for _, i := range allApps.MustArray() { - name := i.(map[string]interface{})["name"].(string) + var filteredItems []Application + for _, i := range items { + name := i.Name if re != nil { if re.MatchString(name) { - apps = append(apps, i.(map[string]interface{})) + filteredItems = append(filteredItems, i) } - } else if name == appFilter { - apps = append(apps, i.(map[string]interface{})) + } else if name == filter { + filteredItems = append(filteredItems, i) } + } - return apps, nil + + return filteredItems, nil } -func (ds *Zabbix) GetHosts(ctx context.Context, groupFilter string, hostFilter string) ([]map[string]interface{}, error) { +func (ds *Zabbix) GetHosts(ctx context.Context, groupFilter string, hostFilter string) ([]Host, error) { groups, err := ds.GetGroups(ctx, groupFilter) if err != nil { return nil, err } var groupids []string - for _, k := range groups { - groupids = append(groupids, k["groupid"].(string)) + for _, group := range groups { + groupids = append(groupids, group.ID) } allHosts, err := ds.GetAllHosts(ctx, groupids) if err != nil { return nil, err } - re, err := parseFilter(hostFilter) + return filterHostsByQuery(allHosts, hostFilter) +} + +func filterHostsByQuery(items []Host, filter string) ([]Host, error) { + re, err := parseFilter(filter) if err != nil { return nil, err } - var hosts []map[string]interface{} - for _, i := range allHosts.MustArray() { - name := i.(map[string]interface{})["name"].(string) + var filteredItems []Host + for _, i := range items { + name := i.Name if re != nil { if re.MatchString(name) { - hosts = append(hosts, i.(map[string]interface{})) + filteredItems = append(filteredItems, i) } - } else if name == hostFilter { - hosts = append(hosts, i.(map[string]interface{})) + } else if name == filter { + filteredItems = append(filteredItems, i) } } - return hosts, nil + return filteredItems, nil } -func (ds *Zabbix) GetGroups(ctx context.Context, groupFilter string) ([]map[string]interface{}, error) { +func (ds *Zabbix) GetGroups(ctx context.Context, groupFilter string) ([]Group, error) { allGroups, err := ds.GetAllGroups(ctx) if err != nil { return nil, err } - re, err := parseFilter(groupFilter) + + return filterGroupsByQuery(allGroups, groupFilter) +} + +func filterGroupsByQuery(items []Group, filter string) ([]Group, error) { + re, err := parseFilter(filter) if err != nil { return nil, err } - var groups []map[string]interface{} - for _, i := range allGroups.MustArray() { - name := i.(map[string]interface{})["name"].(string) + var filteredItems []Group + for _, i := range items { + name := i.Name if re != nil { if re.MatchString(name) { - groups = append(groups, i.(map[string]interface{})) + filteredItems = append(filteredItems, i) } - } else if name == groupFilter { - groups = append(groups, i.(map[string]interface{})) + } else if name == filter { + filteredItems = append(filteredItems, i) } + } - return groups, nil + + return filteredItems, nil } -func (ds *Zabbix) GetAllItems(ctx context.Context, hostids []string, appids []string, itemtype string) (*simplejson.Json, error) { +func (ds *Zabbix) GetAllItems(ctx context.Context, hostids []string, appids []string, itemtype string) ([]Item, error) { params := ZabbixAPIParams{ "output": []string{"itemid", "name", "key_", "value_type", "hostid", "status", "state"}, "sortfield": "name", @@ -183,36 +185,64 @@ func (ds *Zabbix) GetAllItems(ctx context.Context, hostids []string, appids []st filter["value_type"] = []int{1, 2, 4} } - return ds.Request(ctx, &ZabbixAPIRequest{Method: "item.get", Params: params}) + result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "item.get", Params: params}) + if err != nil { + return nil, err + } + + var items []Item + err = convertTo(result, items) + return items, err } -func (ds *Zabbix) GetAllApps(ctx context.Context, hostids []string) (*simplejson.Json, error) { +func (ds *Zabbix) GetAllApps(ctx context.Context, hostids []string) ([]Application, error) { params := ZabbixAPIParams{ "output": "extend", "hostids": hostids, } - return ds.Request(ctx, &ZabbixAPIRequest{Method: "application.get", Params: params}) + result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "application.get", Params: params}) + if err != nil { + return nil, err + } + + var apps []Application + err = convertTo(result, apps) + return apps, err } -func (ds *Zabbix) GetAllHosts(ctx context.Context, groupids []string) (*simplejson.Json, error) { +func (ds *Zabbix) GetAllHosts(ctx context.Context, groupids []string) ([]Host, error) { params := ZabbixAPIParams{ "output": []string{"name", "host"}, "sortfield": "name", "groupids": groupids, } - return ds.Request(ctx, &ZabbixAPIRequest{Method: "host.get", Params: params}) + result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "host.get", Params: params}) + if err != nil { + return nil, err + } + + var hosts []Host + err = convertTo(result, hosts) + return hosts, err } -func (ds *Zabbix) GetAllGroups(ctx context.Context) (*simplejson.Json, error) { +func (ds *Zabbix) GetAllGroups(ctx context.Context) ([]Group, error) { params := ZabbixAPIParams{ "output": []string{"name"}, "sortfield": "name", "real_hosts": true, } - return ds.Request(ctx, &ZabbixAPIRequest{Method: "hostgroup.get", Params: params}) + result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "hostgroup.get", Params: params}) + if err != nil { + return nil, err + } + + var groups []Group + err = convertTo(result, groups) + return groups, err } func isAppMethodNotFoundError(err error) bool { diff --git a/pkg/zabbix/models.go b/pkg/zabbix/models.go index 707f416..8d98a74 100644 --- a/pkg/zabbix/models.go +++ b/pkg/zabbix/models.go @@ -74,3 +74,19 @@ type HistoryPoint struct { Value float64 `json:"value,omitempty,string"` NS int64 `json:"ns,omitempty,string"` } + +type Group struct { + Name string `json:"name"` + ID string `json:"groupid"` +} + +type Host struct { + Name string `json:"name"` + Host string `json:"host"` + ID string `json:"hostid"` +} + +type Application struct { + Name string `json:"name"` + ID string `json:"applicationid"` +} diff --git a/pkg/zabbix/type_converters.go b/pkg/zabbix/type_converters.go new file mode 100644 index 0000000..9640d2a --- /dev/null +++ b/pkg/zabbix/type_converters.go @@ -0,0 +1,21 @@ +package zabbix + +import ( + "encoding/json" + + "github.com/bitly/go-simplejson" +) + +func convertTo(value *simplejson.Json, result interface{}) error { + valueJSON, err := value.MarshalJSON() + if err != nil { + return err + } + + err = json.Unmarshal(valueJSON, result) + if err != nil { + return err + } + + return nil +} diff --git a/src/datasource-zabbix/datasource.ts b/src/datasource-zabbix/datasource.ts index 94ac547..3d81b37 100644 --- a/src/datasource-zabbix/datasource.ts +++ b/src/datasource-zabbix/datasource.ts @@ -18,7 +18,7 @@ import { ZabbixMetricsQuery, ZabbixDSOptions, VariableQueryTypes, ShowProblemTyp import { getBackendSrv, getTemplateSrv, toDataQueryResponse } from '@grafana/runtime'; import { DataFrame, DataQueryRequest, DataQueryResponse, DataSourceApi, DataSourceInstanceSettings, FieldType, isDataFrame, LoadingState } from '@grafana/data'; -const ENABLE_BACKEND_QUERIES = false; +const ENABLE_BACKEND_QUERIES = true; export class ZabbixDatasource extends DataSourceApi { name: string;