@@ -16,7 +16,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrFunctionsNotSupported = errors.New("zabbix queries with functions are not supported")
|
||||
ErrNonMetricQueryNotSupported = errors.New("non-metrics queries are not supported")
|
||||
)
|
||||
|
||||
@@ -134,7 +133,7 @@ func (ds *ZabbixDatasource) QueryData(ctx context.Context, req *backend.QueryDat
|
||||
res.Frames = append(res.Frames, frames...)
|
||||
}
|
||||
} else {
|
||||
res.Error = ErrNonMetricQueryNotSupported
|
||||
res.Error = backend.DownstreamError(ErrNonMetricQueryNotSupported)
|
||||
}
|
||||
qdr.Responses[q.RefID] = res
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/gtime"
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/timeseries"
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/zabbix"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
)
|
||||
|
||||
const RANGE_VARIABLE_VALUE = "range_series"
|
||||
@@ -103,26 +104,26 @@ func applyFunctions(series []*timeseries.TimeSeriesData, functions []QueryFuncti
|
||||
for _, s := range series {
|
||||
result, err := applyFunc(s.TS, f.Params...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, backend.DownstreamError(err)
|
||||
}
|
||||
s.TS = result
|
||||
}
|
||||
} else if applyAggFunc, ok := aggFuncMap[f.Def.Name]; ok {
|
||||
result, err := applyAggFunc(series, f.Params...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, backend.DownstreamError(err)
|
||||
}
|
||||
series = result
|
||||
} else if applyFilterFunc, ok := filterFuncMap[f.Def.Name]; ok {
|
||||
result, err := applyFilterFunc(series, f.Params...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, backend.DownstreamError(err)
|
||||
}
|
||||
series = result
|
||||
} else if _, ok := skippedFuncMap[f.Def.Name]; ok {
|
||||
continue
|
||||
} else {
|
||||
err := errFunctionNotSupported(f.Def.Name)
|
||||
err := backend.DownstreamError(errFunctionNotSupported(f.Def.Name))
|
||||
return series, err
|
||||
}
|
||||
}
|
||||
@@ -135,7 +136,7 @@ func applyFunctionsPre(query *QueryModel, items []*zabbix.Item) error {
|
||||
if applyFunc, ok := timeFuncMap[f.Def.Name]; ok {
|
||||
err := applyFunc(query, items, f.Params...)
|
||||
if err != nil {
|
||||
return err
|
||||
return backend.DownstreamError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
128
pkg/datasource/functions_test.go
Normal file
128
pkg/datasource/functions_test.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package datasource
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/timeseries"
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/zabbix"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestApplyFunctionsFunction(t *testing.T) {
|
||||
f := new(float64)
|
||||
*f = 1.0
|
||||
series := []*timeseries.TimeSeriesData{
|
||||
{
|
||||
TS: timeseries.TimeSeries{
|
||||
{Time: time.Time{}, Value: f},
|
||||
{Time: time.Time{}, Value: f},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
functions []QueryFunction
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "unsupported function",
|
||||
functions: []QueryFunction{
|
||||
{
|
||||
Def: QueryFunctionDef{
|
||||
Name: "unsupportedFunction",
|
||||
},
|
||||
Params: []interface{}{},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "data processing function with params error",
|
||||
functions: []QueryFunction{
|
||||
{
|
||||
Def: QueryFunctionDef{
|
||||
Name: "groupBy",
|
||||
},
|
||||
Params: []interface {
|
||||
}{1},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "aggregate function with params error",
|
||||
functions: []QueryFunction{
|
||||
{
|
||||
Def: QueryFunctionDef{
|
||||
Name: "aggregateBy",
|
||||
},
|
||||
Params: []interface {
|
||||
}{1},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "filter function with params error",
|
||||
functions: []QueryFunction{
|
||||
{
|
||||
Def: QueryFunctionDef{
|
||||
Name: "top",
|
||||
},
|
||||
Params: []interface {
|
||||
}{"string"},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "skipped function should return no error",
|
||||
functions: []QueryFunction{
|
||||
{
|
||||
Def: QueryFunctionDef{
|
||||
Name: "setAlias",
|
||||
},
|
||||
Params: []interface {
|
||||
}{},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := applyFunctions(series, tt.functions)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err, "expected error for function")
|
||||
// Check if the error is a downstream error
|
||||
assert.Truef(t, backend.IsDownstreamError(err), "error is not a downstream error")
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// TestApplyFunctionsPreFunction tests the applyFunctionsPre function for error handling
|
||||
func TestApplyFunctionsPreFunction(t *testing.T) {
|
||||
query := QueryModel{
|
||||
Functions: []QueryFunction{
|
||||
{
|
||||
Def: QueryFunctionDef{
|
||||
Name: "timeShift",
|
||||
},
|
||||
Params: []interface{}{1},
|
||||
},
|
||||
}}
|
||||
|
||||
items := []*zabbix.Item{}
|
||||
err := applyFunctionsPre(&query, items)
|
||||
|
||||
assert.Error(t, err, "expected error for function")
|
||||
// Check if the error is a downstream error
|
||||
assert.Truef(t, backend.IsDownstreamError(err), "error is not a downstream error")
|
||||
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/timeseries"
|
||||
"github.com/alexanderzobnin/grafana-zabbix/pkg/zabbix"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
)
|
||||
|
||||
@@ -154,19 +155,19 @@ func getTrendPointValue(point zabbix.TrendPoint, valueType string) (float64, err
|
||||
|
||||
value, err := strconv.ParseFloat(valueStr, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error parsing trend value: %s", err)
|
||||
return 0, backend.DownstreamError(fmt.Errorf("error parsing trend value: %s", err))
|
||||
}
|
||||
return value, nil
|
||||
} else if valueType == "sum" {
|
||||
avgStr := point.ValueAvg
|
||||
avg, err := strconv.ParseFloat(avgStr, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error parsing trend value: %s", err)
|
||||
return 0, backend.DownstreamError(fmt.Errorf("error parsing trend value: %s", err))
|
||||
}
|
||||
countStr := point.Num
|
||||
count, err := strconv.ParseFloat(countStr, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error parsing trend value: %s", err)
|
||||
return 0, backend.DownstreamError(fmt.Errorf("error parsing trend value: %s", err))
|
||||
}
|
||||
if count > 0 {
|
||||
return avg * count, nil
|
||||
@@ -175,7 +176,7 @@ func getTrendPointValue(point zabbix.TrendPoint, valueType string) (float64, err
|
||||
}
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("failed to get trend value, unknown value type: %s", valueType)
|
||||
return 0, backend.DownstreamError(fmt.Errorf("failed to get trend value, unknown value type: %s", valueType))
|
||||
}
|
||||
|
||||
var fixedUpdateIntervalPattern = regexp.MustCompile(`^(\d+)([smhdw]?)$`)
|
||||
|
||||
Reference in New Issue
Block a user