logs-analyzer/signoz/pkg/query-service/postprocess/gaps.go

74 lines
2.3 KiB
Go
Raw Permalink Normal View History

2024-09-02 22:47:30 +03:00
package postprocess
import (
"github.com/SigNoz/govaluate"
"go.signoz.io/signoz/pkg/query-service/common"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
)
func StepIntervalForFunction(params *v3.QueryRangeParamsV3, query string) int64 {
q := params.CompositeQuery.BuilderQueries[query]
if q.QueryName != q.Expression {
expression, _ := govaluate.NewEvaluableExpressionWithFunctions(q.Expression, EvalFuncs())
steps := []int64{}
for _, v := range expression.Vars() {
steps = append(steps, params.CompositeQuery.BuilderQueries[v].StepInterval)
}
return common.LCMList(steps)
}
return q.StepInterval
}
func fillGap(series *v3.Series, start, end, step int64) *v3.Series {
v := make(map[int64]float64)
for _, point := range series.Points {
v[point.Timestamp] = point.Value
}
// For all the values from start to end, find the timestamps
// that don't have value and add zero point
start = start - (start % (step * 1000))
for i := start; i <= end; i += step * 1000 {
if _, ok := v[i]; !ok {
v[i] = 0
}
}
newSeries := &v3.Series{
Labels: series.Labels,
LabelsArray: series.LabelsArray,
Points: make([]v3.Point, 0),
}
for i := start; i <= end; i += step * 1000 {
newSeries.Points = append(newSeries.Points, v3.Point{Timestamp: i, Value: v[i]})
}
return newSeries
}
// TODO(srikanthccv): can WITH FILL be perfect substitute for all cases https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier
func FillGaps(results []*v3.Result, params *v3.QueryRangeParamsV3) {
if params.CompositeQuery.PanelType != v3.PanelTypeGraph {
return
}
for _, result := range results {
// A `result` item in `results` contains the query result for individual query.
// If there are no series in the result, we add empty series and `fillGap` adds all zeros
if len(result.Series) == 0 {
result.Series = []*v3.Series{
{
Labels: make(map[string]string),
LabelsArray: make([]map[string]string, 0),
},
}
}
builderQueries := params.CompositeQuery.BuilderQueries
if builderQueries != nil {
// The values should be added at the intervals of `step`
step := StepIntervalForFunction(params, result.QueryName)
for idx := range result.Series {
result.Series[idx] = fillGap(result.Series[idx], params.Start, params.End, step)
}
}
}
}