Refactor history/trend queries

This commit is contained in:
Alexander Zobnin
2021-05-24 15:31:56 +03:00
parent 94b5c88366
commit e7a386cf8a
3 changed files with 109 additions and 51 deletions

View File

@@ -2,6 +2,7 @@ package datasource
import (
"fmt"
"strconv"
"time"
"github.com/alexanderzobnin/grafana-zabbix/pkg/zabbix"
@@ -9,7 +10,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/data"
)
func convertHistoryToDataFrame(history History, items zabbix.Items) *data.Frame {
func convertHistoryToDataFrame(history zabbix.History, items zabbix.Items) *data.Frame {
timeFileld := data.NewFieldFromFieldType(data.FieldTypeTime, 0)
timeFileld.Name = "time"
frame := data.NewFrame("History", timeFileld)
@@ -48,3 +49,29 @@ func convertHistoryToDataFrame(history History, items zabbix.Items) *data.Frame
}
return wideFrame
}
func convertTrendToHistory(trend zabbix.Trend, valueType string) (zabbix.History, error) {
history := make([]zabbix.HistoryPoint, 0)
for _, point := range trend {
valueStr := point.ValueAvg
switch valueType {
case "min":
valueStr = point.ValueMin
case "max":
valueStr = point.ValueMax
}
value, err := strconv.ParseFloat(valueStr, 64)
if err != nil {
return nil, fmt.Errorf("error parsing trend value: %s", err)
}
history = append(history, zabbix.HistoryPoint{
ItemID: point.ItemID,
Clock: point.Clock,
Value: value,
})
}
return history, nil
}

View File

@@ -1,12 +1,9 @@
package datasource
import (
"encoding/json"
"fmt"
"time"
"github.com/alexanderzobnin/grafana-zabbix/pkg/zabbix"
simplejson "github.com/bitly/go-simplejson"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
"golang.org/x/net/context"
@@ -71,7 +68,7 @@ func (ds *ZabbixDatasourceInstance) queryNumericDataForItems(ctx context.Context
consolidateBy = valueType
}
history, err := ds.getHistotyOrTrend(ctx, query, items)
history, err := ds.getHistotyOrTrend(ctx, query, items, valueType)
if err != nil {
return nil, err
}
@@ -103,59 +100,19 @@ func (ds *ZabbixDatasourceInstance) getConsolidateBy(query *QueryModel) string {
return consolidateBy
}
func (ds *ZabbixDatasourceInstance) getHistotyOrTrend(ctx context.Context, query *QueryModel, items zabbix.Items) (History, error) {
func (ds *ZabbixDatasourceInstance) getHistotyOrTrend(ctx context.Context, query *QueryModel, items zabbix.Items, trendValueType string) (zabbix.History, error) {
timeRange := query.TimeRange
useTrend := ds.isUseTrend(timeRange)
allHistory := History{}
groupedItems := map[int]zabbix.Items{}
for _, j := range items {
groupedItems[j.ValueType] = append(groupedItems[j.ValueType], j)
}
for k, l := range groupedItems {
var itemids []string
for _, m := range l {
itemids = append(itemids, m.ID)
}
params := zabbix.ZabbixAPIParams{
"output": "extend",
"sortfield": "clock",
"sortorder": "ASC",
"itemids": itemids,
"time_from": timeRange.From.Unix(),
"time_till": timeRange.To.Unix(),
}
var response *simplejson.Json
var err error
if useTrend {
response, err = ds.zabbix.Request(ctx, &zabbix.ZabbixAPIRequest{Method: "trend.get", Params: params})
} else {
params["history"] = &k
response, err = ds.zabbix.Request(ctx, &zabbix.ZabbixAPIRequest{Method: "history.get", Params: params})
}
result, err := ds.zabbix.GetTrend(ctx, items, timeRange)
if err != nil {
return nil, err
}
pointJSON, err := response.MarshalJSON()
if err != nil {
return nil, fmt.Errorf("Internal error parsing response JSON: %w", err)
return convertTrendToHistory(result, trendValueType)
}
history := History{}
err = json.Unmarshal(pointJSON, &history)
if err != nil {
ds.logger.Error("Error handling history response", "error", err.Error())
} else {
allHistory = append(allHistory, history...)
}
}
return allHistory, nil
return ds.zabbix.GetHistory(ctx, items, timeRange)
}
func (ds *ZabbixDatasourceInstance) isUseTrend(timeRange backend.TimeRange) bool {

View File

@@ -2,8 +2,82 @@ package zabbix
import (
"context"
"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 multple 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, appFilter string, itemFilter string, itemType string) ([]Item, error) {
hosts, err := ds.GetHosts(ctx, groupFilter, hostFilter)
if err != nil {