1package mathexp 2 3import ( 4 "fmt" 5 "time" 6 7 "github.com/grafana/grafana-plugin-sdk-go/data" 8) 9 10// Resample turns the Series into a Number based on the given reduction function 11func (s Series) Resample(refID string, interval time.Duration, downsampler string, upsampler string, from, to time.Time) (Series, error) { 12 newSeriesLength := int(float64(to.Sub(from).Nanoseconds()) / float64(interval.Nanoseconds())) 13 if newSeriesLength <= 0 { 14 return s, fmt.Errorf("the series cannot be sampled further; the time range is shorter than the interval") 15 } 16 resampled := NewSeries(refID, s.GetLabels(), newSeriesLength+1) 17 bookmark := 0 18 var lastSeen *float64 19 idx := 0 20 t := from 21 for !t.After(to) && idx <= newSeriesLength { 22 vals := make([]*float64, 0) 23 sIdx := bookmark 24 for { 25 if sIdx == s.Len() { 26 break 27 } 28 st, v := s.GetPoint(sIdx) 29 if st.After(t) { 30 break 31 } 32 bookmark++ 33 sIdx++ 34 lastSeen = v 35 vals = append(vals, v) 36 } 37 var value *float64 38 if len(vals) == 0 { // upsampling 39 switch upsampler { 40 case "pad": 41 if lastSeen != nil { 42 value = lastSeen 43 } else { 44 value = nil 45 } 46 case "backfilling": 47 if sIdx == s.Len() { // no vals left 48 value = nil 49 } else { 50 _, value = s.GetPoint(sIdx) 51 } 52 case "fillna": 53 value = nil 54 default: 55 return s, fmt.Errorf("upsampling %v not implemented", upsampler) 56 } 57 } else { // downsampling 58 fVec := data.NewField("", s.GetLabels(), vals) 59 ff := Float64Field(*fVec) 60 var tmp *float64 61 switch downsampler { 62 case "sum": 63 tmp = Sum(&ff) 64 case "mean": 65 tmp = Avg(&ff) 66 case "min": 67 tmp = Min(&ff) 68 case "max": 69 tmp = Max(&ff) 70 default: 71 return s, fmt.Errorf("downsampling %v not implemented", downsampler) 72 } 73 value = tmp 74 } 75 if err := resampled.SetPoint(idx, t, value); err != nil { 76 return resampled, err 77 } 78 t = t.Add(interval) 79 idx++ 80 } 81 return resampled, nil 82} 83