package datasource import ( "time" "github.com/alexanderzobnin/grafana-zabbix/pkg/zabbix" "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/data" "golang.org/x/net/context" ) // ZabbixAPIQuery handles query requests to Zabbix API func (ds *ZabbixDatasourceInstance) ZabbixAPIQuery(ctx context.Context, apiReq *zabbix.ZabbixAPIRequest) (*ZabbixAPIResourceResponse, error) { resultJson, err := ds.zabbix.Request(ctx, apiReq) if err != nil { return nil, err } result := resultJson.Interface() return BuildAPIResponse(&result) } func BuildAPIResponse(responseData *interface{}) (*ZabbixAPIResourceResponse, error) { return &ZabbixAPIResourceResponse{ Result: *responseData, }, nil } // TestConnection checks authentication and version of the Zabbix API and returns that info func (ds *ZabbixDatasourceInstance) TestConnection(ctx context.Context) (string, error) { _, err := ds.zabbix.GetAllGroups(ctx) if err != nil { return "", err } response, err := ds.zabbix.Request(ctx, &zabbix.ZabbixAPIRequest{Method: "apiinfo.version"}) if err != nil { return "", err } resultByte, _ := response.MarshalJSON() return string(resultByte), nil } func (ds *ZabbixDatasourceInstance) queryNumericItems(ctx context.Context, query *QueryModel) ([]*data.Frame, error) { groupFilter := query.Group.Filter hostFilter := query.Host.Filter appFilter := query.Application.Filter itemFilter := query.Item.Filter items, err := ds.zabbix.GetItems(ctx, groupFilter, hostFilter, appFilter, itemFilter, "num") if err != nil { return nil, err } frames, err := ds.queryNumericDataForItems(ctx, query, items) if err != nil { return nil, err } return frames, nil } func (ds *ZabbixDatasourceInstance) queryNumericDataForItems(ctx context.Context, query *QueryModel, items []*zabbix.Item) ([]*data.Frame, error) { valueType := ds.getTrendValueType(query) consolidateBy := ds.getConsolidateBy(query) if consolidateBy == "" { consolidateBy = valueType } err := applyFunctionsPre(query, items) if err != nil { return nil, err } history, err := ds.getHistotyOrTrend(ctx, query, items, valueType) if err != nil { return nil, err } series := convertHistoryToTimeSeries(history, items) series, err = applyFunctions(series, query.Functions) if err != nil { return nil, err } frames := convertTimeSeriesToDataFrames(series) return frames, nil } func (ds *ZabbixDatasourceInstance) getTrendValueType(query *QueryModel) string { trendValue := "avg" for _, fn := range query.Functions { if fn.Def.Name == "trendValue" && len(fn.Params) > 0 { trendValue = fn.Params[0].(string) } } return trendValue } func (ds *ZabbixDatasourceInstance) getConsolidateBy(query *QueryModel) string { consolidateBy := "avg" for _, fn := range query.Functions { if fn.Def.Name == "consolidateBy" && len(fn.Params) > 0 { consolidateBy = fn.Params[0].(string) } } return consolidateBy } func (ds *ZabbixDatasourceInstance) getHistotyOrTrend(ctx context.Context, query *QueryModel, items []*zabbix.Item, trendValueType string) (zabbix.History, error) { timeRange := query.TimeRange useTrend := ds.isUseTrend(timeRange) if useTrend { result, err := ds.zabbix.GetTrend(ctx, items, timeRange) if err != nil { return nil, err } return convertTrendToHistory(result, trendValueType) } return ds.zabbix.GetHistory(ctx, items, timeRange) } func (ds *ZabbixDatasourceInstance) isUseTrend(timeRange backend.TimeRange) bool { if !ds.Settings.Trends { return false } trendsFrom := ds.Settings.TrendsFrom trendsRange := ds.Settings.TrendsRange fromSec := timeRange.From.Unix() toSec := timeRange.To.Unix() rangeSec := float64(toSec - fromSec) if (fromSec < time.Now().Add(-trendsFrom).Unix()) || (rangeSec > trendsRange.Seconds()) { return true } return false }