mirror of
https://github.com/grafana/grafana.git
synced 2025-08-01 13:32:12 +08:00
implement missing value fill functionality for postgres
This commit is contained in:
@ -4,6 +4,7 @@ import (
|
|||||||
"container/list"
|
"container/list"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
@ -198,6 +199,18 @@ func (e PostgresQueryEndpoint) transformToTimeSeries(query *tsdb.Query, rows *co
|
|||||||
return fmt.Errorf("Found no column named time")
|
return fmt.Errorf("Found no column named time")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fillMissing := query.Model.Get("fill").MustBool(false)
|
||||||
|
var fillInterval float64
|
||||||
|
fillValue := null.Float{}
|
||||||
|
if fillMissing {
|
||||||
|
fillInterval = query.Model.Get("fillInterval").MustFloat64() * 1000
|
||||||
|
if query.Model.Get("fillNULL").MustBool(false) == false {
|
||||||
|
fillValue.Float64 = query.Model.Get("fillValue").MustFloat64()
|
||||||
|
fillValue.Valid = true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var timestamp float64
|
var timestamp float64
|
||||||
var value null.Float
|
var value null.Float
|
||||||
@ -249,7 +262,34 @@ func (e PostgresQueryEndpoint) transformToTimeSeries(query *tsdb.Query, rows *co
|
|||||||
if metricIndex == -1 {
|
if metricIndex == -1 {
|
||||||
metric = col
|
metric = col
|
||||||
}
|
}
|
||||||
e.appendTimePoint(pointsBySeries, seriesByQueryOrder, metric, timestamp, value)
|
|
||||||
|
series, exist := pointsBySeries[metric]
|
||||||
|
if exist == false {
|
||||||
|
series = &tsdb.TimeSeries{Name: metric}
|
||||||
|
pointsBySeries[metric] = series
|
||||||
|
seriesByQueryOrder.PushBack(metric)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fillMissing {
|
||||||
|
var intervalStart float64
|
||||||
|
if exist == false {
|
||||||
|
intervalStart = float64(tsdbQuery.TimeRange.MustGetFrom().UnixNano() / 1e6)
|
||||||
|
} else {
|
||||||
|
intervalStart = series.Points[len(series.Points)-1][1].Float64 + fillInterval
|
||||||
|
}
|
||||||
|
|
||||||
|
// align interval start
|
||||||
|
intervalStart = math.Floor(intervalStart/fillInterval) * fillInterval
|
||||||
|
|
||||||
|
for i := intervalStart; i < timestamp; i += fillInterval {
|
||||||
|
series.Points = append(series.Points, tsdb.TimePoint{fillValue, null.FloatFrom(i)})
|
||||||
|
rowCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
series.Points = append(series.Points, tsdb.TimePoint{value, null.FloatFrom(timestamp)})
|
||||||
|
|
||||||
|
e.log.Debug("Rows", "metric", metric, "time", timestamp, "value", value)
|
||||||
rowCount++
|
rowCount++
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -258,20 +298,22 @@ func (e PostgresQueryEndpoint) transformToTimeSeries(query *tsdb.Query, rows *co
|
|||||||
for elem := seriesByQueryOrder.Front(); elem != nil; elem = elem.Next() {
|
for elem := seriesByQueryOrder.Front(); elem != nil; elem = elem.Next() {
|
||||||
key := elem.Value.(string)
|
key := elem.Value.(string)
|
||||||
result.Series = append(result.Series, pointsBySeries[key])
|
result.Series = append(result.Series, pointsBySeries[key])
|
||||||
|
|
||||||
|
if fillMissing {
|
||||||
|
series := pointsBySeries[key]
|
||||||
|
// fill in values from last fetched value till interval end
|
||||||
|
intervalStart := series.Points[len(series.Points)-1][1].Float64
|
||||||
|
intervalEnd := float64(tsdbQuery.TimeRange.MustGetTo().UnixNano() / 1e6)
|
||||||
|
|
||||||
|
// align interval start
|
||||||
|
intervalStart = math.Floor(intervalStart/fillInterval) * fillInterval
|
||||||
|
for i := intervalStart + fillInterval; i < intervalEnd; i += fillInterval {
|
||||||
|
series.Points = append(series.Points, tsdb.TimePoint{fillValue, null.FloatFrom(i)})
|
||||||
|
rowCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Meta.Set("rowCount", rowCount)
|
result.Meta.Set("rowCount", rowCount)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e PostgresQueryEndpoint) appendTimePoint(pointsBySeries map[string]*tsdb.TimeSeries, seriesByQueryOrder *list.List, metric string, timestamp float64, value null.Float) {
|
|
||||||
if series, exist := pointsBySeries[metric]; exist {
|
|
||||||
series.Points = append(series.Points, tsdb.TimePoint{value, null.FloatFrom(timestamp)})
|
|
||||||
} else {
|
|
||||||
series := &tsdb.TimeSeries{Name: metric}
|
|
||||||
series.Points = append(series.Points, tsdb.TimePoint{value, null.FloatFrom(timestamp)})
|
|
||||||
pointsBySeries[metric] = series
|
|
||||||
seriesByQueryOrder.PushBack(metric)
|
|
||||||
}
|
|
||||||
e.log.Debug("Rows", "metric", metric, "time", timestamp, "value", value)
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user