diff --git a/pkg/datasource/functions.go b/pkg/datasource/functions.go index 94c1420..b7458f3 100644 --- a/pkg/datasource/functions.go +++ b/pkg/datasource/functions.go @@ -2,6 +2,7 @@ package datasource import ( "fmt" + "strconv" "github.com/alexanderzobnin/grafana-zabbix/pkg/gtime" "github.com/alexanderzobnin/grafana-zabbix/pkg/timeseries" @@ -18,6 +19,8 @@ var funcMap map[string]DataProcessingFunc func init() { funcMap = map[string]DataProcessingFunc{ "groupBy": applyGroupBy, + "scale": applyScale, + "offset": applyOffset, } } @@ -53,6 +56,28 @@ func applyGroupBy(series timeseries.TimeSeries, params ...string) (timeseries.Ti return s, nil } +func applyScale(series timeseries.TimeSeries, params ...string) (timeseries.TimeSeries, error) { + pFactor := params[0] + factor, err := strconv.ParseFloat(pFactor, 64) + if err != nil { + return nil, err + } + + transformFunc := timeseries.TransformScale(factor) + return series.Transform(transformFunc), nil +} + +func applyOffset(series timeseries.TimeSeries, params ...string) (timeseries.TimeSeries, error) { + pOffset := params[0] + offset, err := strconv.ParseFloat(pOffset, 64) + if err != nil { + return nil, err + } + + transformFunc := timeseries.TransformOffset(offset) + return series.Transform(transformFunc), nil +} + func getAggFunc(agg string) timeseries.AggFunc { switch agg { case "avg": diff --git a/pkg/timeseries/agg_functions.go b/pkg/timeseries/agg_functions.go new file mode 100644 index 0000000..bc0d2a4 --- /dev/null +++ b/pkg/timeseries/agg_functions.go @@ -0,0 +1,80 @@ +package timeseries + +import ( + "math" + "sort" +) + +func AggAvg(points []TimePoint) *float64 { + sum := AggSum(points) + avg := *sum / float64(len(points)) + return &avg +} + +func AggSum(points []TimePoint) *float64 { + var sum float64 = 0 + for _, p := range points { + if p.Value != nil { + sum += *p.Value + } + } + return &sum +} + +func AggMax(points []TimePoint) *float64 { + var max *float64 = nil + for _, p := range points { + if p.Value != nil { + if max == nil { + max = p.Value + } else if *p.Value > *max { + max = p.Value + } + } + } + return max +} + +func AggMin(points []TimePoint) *float64 { + var min *float64 = nil + for _, p := range points { + if p.Value != nil { + if min == nil { + min = p.Value + } else if *p.Value < *min { + min = p.Value + } + } + } + return min +} + +func AggCount(points []TimePoint) *float64 { + count := float64(len(points)) + return &count +} + +func AggFirst(points []TimePoint) *float64 { + return points[0].Value +} + +func AggLast(points []TimePoint) *float64 { + return points[len(points)-1].Value +} + +func AggMedian(points []TimePoint) *float64 { + values := make([]float64, 0) + for _, p := range points { + if p.Value != nil { + values = append(values, *p.Value) + } + } + if len(values) == 0 { + return nil + } + + values = sort.Float64Slice(values) + medianIndex := int(math.Floor(float64(len(values)) / 2)) + median := values[medianIndex] + return &median +} diff --git a/pkg/timeseries/models.go b/pkg/timeseries/models.go index 4a3b3c7..6cb583f 100644 --- a/pkg/timeseries/models.go +++ b/pkg/timeseries/models.go @@ -31,3 +31,5 @@ type TimeSeriesMeta struct { } type AggFunc = func(points []TimePoint) *float64 + +type TransformFunc = func(point TimePoint) TimePoint diff --git a/pkg/timeseries/timeseries.go b/pkg/timeseries/timeseries.go index 962be01..8eabba0 100644 --- a/pkg/timeseries/timeseries.go +++ b/pkg/timeseries/timeseries.go @@ -74,78 +74,11 @@ func (ts TimeSeries) GroupBy(interval time.Duration, aggFunc AggFunc) TimeSeries return groupedSeries } -func AggAvg(points []TimePoint) *float64 { - sum := AggSum(points) - avg := *sum / float64(len(points)) - return &avg -} - -func AggSum(points []TimePoint) *float64 { - var sum float64 = 0 - for _, p := range points { - if p.Value != nil { - sum += *p.Value - } +func (ts TimeSeries) Transform(transformFunc TransformFunc) TimeSeries { + for i, p := range ts { + ts[i] = transformFunc(p) } - return &sum -} - -func AggMax(points []TimePoint) *float64 { - var max *float64 = nil - for _, p := range points { - if p.Value != nil { - if max == nil { - max = p.Value - } else if *p.Value > *max { - max = p.Value - } - } - } - return max -} - -func AggMin(points []TimePoint) *float64 { - var min *float64 = nil - for _, p := range points { - if p.Value != nil { - if min == nil { - min = p.Value - } else if *p.Value < *min { - min = p.Value - } - } - } - return min -} - -func AggCount(points []TimePoint) *float64 { - count := float64(len(points)) - return &count -} - -func AggFirst(points []TimePoint) *float64 { - return points[0].Value -} - -func AggLast(points []TimePoint) *float64 { - return points[len(points)-1].Value -} - -func AggMedian(points []TimePoint) *float64 { - values := make([]float64, 0) - for _, p := range points { - if p.Value != nil { - values = append(values, *p.Value) - } - } - if len(values) == 0 { - return nil - } - - values = sort.Float64Slice(values) - medianIndex := int(math.Floor(float64(len(values)) / 2)) - median := values[medianIndex] - return &median + return ts } // Aligns point's time stamps according to provided interval. diff --git a/pkg/timeseries/transform_functions.go b/pkg/timeseries/transform_functions.go new file mode 100644 index 0000000..6e95d0f --- /dev/null +++ b/pkg/timeseries/transform_functions.go @@ -0,0 +1,29 @@ +package timeseries + +func TransformScale(factor float64) TransformFunc { + return func(point TimePoint) TimePoint { + return transformScale(point, factor) + } +} + +func TransformOffset(offset float64) TransformFunc { + return func(point TimePoint) TimePoint { + return transformOffset(point, offset) + } +} + +func transformScale(point TimePoint, factor float64) TimePoint { + if point.Value != nil { + newValue := *point.Value * factor + point.Value = &newValue + } + return point +} + +func transformOffset(point TimePoint, offset float64) TimePoint { + if point.Value != nil { + newValue := *point.Value + offset + point.Value = &newValue + } + return point +}