package zabbix import ( "context" "sort" "strconv" "strings" "github.com/grafana/grafana-plugin-sdk-go/backend" ) func (ds *Zabbix) GetHistory(ctx context.Context, items []*Item, timeRange backend.TimeRange) (History, error) { history := History{} // Zabbix stores history in different tables and `history` param required for query. So in one query it's only // possible to get history for items with one type. In order to get history for items with multiple types (numeric unsigned and numeric float), // items should be grouped by the `value_type` field. groupedItemids := make(map[int][]string, 0) for _, item := range items { groupedItemids[item.ValueType] = append(groupedItemids[item.ValueType], item.ID) } for historyType, itemids := range groupedItemids { result, err := ds.getHistory(ctx, itemids, historyType, timeRange) if err != nil { return nil, err } history = append(history, result...) } return history, nil } func (ds *Zabbix) getHistory(ctx context.Context, itemids []string, historyType int, timeRange backend.TimeRange) (History, error) { params := ZabbixAPIParams{ "output": "extend", "itemids": itemids, "history": historyType, "time_from": timeRange.From.Unix(), "time_till": timeRange.To.Unix(), "sortfield": "clock", "sortorder": "ASC", } result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "history.get", Params: params}) if err != nil { return nil, err } var history History err = convertTo(result, &history) return history, err } func (ds *Zabbix) GetTrend(ctx context.Context, items []*Item, timeRange backend.TimeRange) (Trend, error) { itemids := make([]string, 0) for _, item := range items { itemids = append(itemids, item.ID) } return ds.getTrend(ctx, itemids, timeRange) } func (ds *Zabbix) getTrend(ctx context.Context, itemids []string, timeRange backend.TimeRange) (Trend, error) { params := ZabbixAPIParams{ "output": "extend", "itemids": itemids, "time_from": timeRange.From.Unix(), "time_till": timeRange.To.Unix(), "sortfield": "clock", "sortorder": "ASC", } result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "trend.get", Params: params}) if err != nil { return nil, err } var trend Trend err = convertTo(result, &trend) return trend, err } func (ds *Zabbix) GetItems( ctx context.Context, groupFilter string, hostFilter string, itemTagFilter string, itemFilter string, itemType string, showDisabled bool, ) ([]*Item, error) { var allItems []*Item hosts, err := ds.GetHosts(ctx, groupFilter, hostFilter) if err != nil { return nil, err } if len(hosts) == 0 { return allItems, nil } hostids := make([]string, 0) for _, host := range hosts { hostids = append(hostids, host.ID) } if isRegex(itemTagFilter) { tags, err := ds.GetItemTags(ctx, groupFilter, hostFilter, itemTagFilter) if err != nil { return nil, err } var tagStrs []string for _, t := range tags { tagStrs = append(tagStrs, itemTagToString(t)) } itemTagFilter = strings.Join(tagStrs, ",") } allItems, err = ds.GetAllItems(ctx, hostids, nil, itemType, showDisabled, itemTagFilter) if err != nil { return nil, err } return filterItemsByQuery(allItems, itemFilter) } func (ds *Zabbix) GetItemsBefore54( ctx context.Context, groupFilter string, hostFilter string, appFilter string, itemFilter string, itemType string, showDisabled bool, ) ([]*Item, error) { hosts, err := ds.GetHosts(ctx, groupFilter, hostFilter) if err != nil { return nil, err } hostids := make([]string, 0) for _, host := range hosts { hostids = append(hostids, host.ID) } apps, err := ds.GetApps(ctx, groupFilter, hostFilter, appFilter) if err != nil { return nil, err } appids := make([]string, 0) for _, app := range apps { appids = append(appids, app.ID) } var allItems []*Item if len(appids) > 0 { allItems, err = ds.GetAllItems(ctx, nil, appids, itemType, showDisabled, "") } else if appFilter == "" && len(hostids) > 0 { allItems, err = ds.GetAllItems(ctx, hostids, nil, itemType, showDisabled, "") } if err != nil { return nil, err } return filterItemsByQuery(allItems, itemFilter) } func filterItemsByQuery(items []*Item, filter string) ([]*Item, error) { re, err := parseFilter(filter) if err != nil { return nil, err } filteredItems := make([]*Item, 0) for _, i := range items { name := i.Name if re != nil { match, err := re.MatchString(name) if err != nil { return nil, err } if match { 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) ([]Application, error) { hosts, err := ds.GetHosts(ctx, groupFilter, hostFilter) if err != nil { return nil, err } hostids := make([]string, 0) for _, host := range hosts { hostids = append(hostids, host.ID) } allApps, err := ds.GetAllApps(ctx, hostids) if err != nil { return nil, err } return filterAppsByQuery(allApps, appFilter) } func filterAppsByQuery(items []Application, filter string) ([]Application, error) { re, err := parseFilter(filter) if err != nil { return nil, err } filteredItems := make([]Application, 0) for _, i := range items { name := i.Name if re != nil { match, err := re.MatchString(name) if err != nil { return nil, err } if match { filteredItems = append(filteredItems, i) } } else if name == filter { filteredItems = append(filteredItems, i) } } return filteredItems, nil } func (ds *Zabbix) GetItemTags(ctx context.Context, groupFilter string, hostFilter string, tagFilter string) ([]ItemTag, error) { hosts, err := ds.GetHosts(ctx, groupFilter, hostFilter) if err != nil { return nil, err } hostids := make([]string, 0) for _, host := range hosts { hostids = append(hostids, host.ID) } var allItems []*Item itemType := "num" showDisabled := false allItems, err = ds.GetAllItems(ctx, hostids, nil, itemType, showDisabled, "") if err != nil { return nil, err } var allTags []ItemTag tagsMap := make(map[string]ItemTag) for _, item := range allItems { for _, itemTag := range item.Tags { tagStr := itemTagToString(itemTag) tagsMap[tagStr] = itemTag } } for _, t := range tagsMap { allTags = append(allTags, t) } return filterTags(allTags, tagFilter) } func filterTags(items []ItemTag, filter string) ([]ItemTag, error) { re, err := parseFilter(filter) if err != nil { return nil, err } filteredItems := make([]ItemTag, 0) for _, i := range items { tagStr := itemTagToString(i) if re != nil { match, err := re.MatchString(tagStr) if err != nil { return nil, err } if match { filteredItems = append(filteredItems, i) } } else if tagStr == filter { filteredItems = append(filteredItems, i) } } return filteredItems, nil } 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 } groupids := make([]string, 0) for _, group := range groups { groupids = append(groupids, group.ID) } allHosts, err := ds.GetAllHosts(ctx, groupids) if err != nil { return nil, err } return filterHostsByQuery(allHosts, hostFilter) } func filterHostsByQuery(items []Host, filter string) ([]Host, error) { re, err := parseFilter(filter) if err != nil { return nil, err } filteredItems := make([]Host, 0) for _, i := range items { name := i.Name if re != nil { match, err := re.MatchString(name) if err != nil { return nil, err } if match { filteredItems = append(filteredItems, i) } } else if name == filter { filteredItems = append(filteredItems, i) } } return filteredItems, nil } func (ds *Zabbix) GetGroups(ctx context.Context, groupFilter string) ([]Group, error) { allGroups, err := ds.GetAllGroups(ctx) if err != nil { return nil, err } return filterGroupsByQuery(allGroups, groupFilter) } func filterGroupsByQuery(items []Group, filter string) ([]Group, error) { re, err := parseFilter(filter) if err != nil { return nil, err } filteredItems := make([]Group, 0) for _, i := range items { name := i.Name if re != nil { match, err := re.MatchString(name) if err != nil { return nil, err } if match { filteredItems = append(filteredItems, i) } } else if name == filter { filteredItems = append(filteredItems, i) } } return filteredItems, nil } func (ds *Zabbix) GetAllItems(ctx context.Context, hostids []string, appids []string, itemtype string, showDisabled bool, itemTagFilter string) ([]*Item, error) { params := ZabbixAPIParams{ "output": []string{"itemid", "name", "key_", "value_type", "hostid", "status", "state", "units", "valuemapid", "delay"}, "sortfield": "name", "webitems": true, "filter": map[string]interface{}{}, "selectHosts": []string{"hostid", "name"}, "hostids": hostids, "applicationids": appids, } filter := params["filter"].(map[string]interface{}) switch itemtype { case "num": filter["value_type"] = []int{0, 3} case "text": filter["value_type"] = []int{1, 2, 4} } if ds.version >= 54 { params["selectTags"] = "extend" if len(itemTagFilter) > 0 { allTags := strings.Split(itemTagFilter, ",") tagsParams := make([]map[string]string, 0) for _, tagStr := range allTags { tag := parseItemTag(tagStr) tagParam := map[string]string{ "tag": tag.Tag, "value": tag.Value, "operator": "1", } tagsParams = append(tagsParams, tagParam) } // tags order should be handled for higher cache hit ratio sort.Slice(tagsParams, func(i, j int) bool { if tagsParams[i]["tag"] != tagsParams[j]["tag"] { return tagsParams[i]["tag"] < tagsParams[j]["tag"] } return tagsParams[i]["value"] < tagsParams[j]["value"] }) params["tags"] = tagsParams params["evaltype"] = 2 } } if !showDisabled { params["monitored"] = true } result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "item.get", Params: params}) if err != nil { return nil, err } var items []*Item err = convertTo(result, &items) if err != nil { return nil, err } items = expandItems(items) return items, err } func (ds *Zabbix) GetItemsByIDs(ctx context.Context, itemids []string) ([]*Item, error) { params := ZabbixAPIParams{ "itemids": itemids, "output": []string{"itemid", "name", "key_", "value_type", "hostid", "status", "state", "units", "valuemapid", "delay"}, "webitems": true, "selectHosts": []string{"hostid", "name"}, } result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "item.get", Params: params}) if err != nil { return nil, err } var items []*Item err = convertTo(result, &items) if err != nil { return nil, err } items = expandItems(items) return items, err } func (ds *Zabbix) GetAllApps(ctx context.Context, hostids []string) ([]Application, error) { params := ZabbixAPIParams{ "output": "extend", "hostids": hostids, } 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) ([]Host, error) { params := ZabbixAPIParams{ "output": []string{"hostid", "name", "host"}, "sortfield": "name", "groupids": groupids, } 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) ([]Group, error) { params := ZabbixAPIParams{ "output": []string{"name", "groupid"}, "sortfield": "name", "with_hosts": true, } 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 (ds *Zabbix) GetValueMappings(ctx context.Context) ([]ValueMap, error) { params := ZabbixAPIParams{ "output": "extend", "selectMappings": "extend", } result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "valuemap.get", Params: params}) if err != nil { return nil, err } var valuemaps []ValueMap err = convertTo(result, &valuemaps) return valuemaps, err } func (ds *Zabbix) GetFullVersion(ctx context.Context) (string, error) { result, err := ds.request(ctx, "apiinfo.version", ZabbixAPIParams{}) if err != nil { return "", err } var version string err = convertTo(result, &version) if err != nil { return "", err } return version, nil } func (ds *Zabbix) GetVersion(ctx context.Context) (int, error) { fullStringVersion, err := ds.GetFullVersion(ctx) if err != nil { return 0, err } version := strings.Replace(fullStringVersion[0:3], ".", "", 1) versionNum, err := strconv.Atoi(version) return versionNum, err }