loki: simplify interval calculation (#41857)
This commit is contained in:
+7
-17
@@ -18,7 +18,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
|
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
|
||||||
"github.com/grafana/loki/pkg/logcli/client"
|
"github.com/grafana/loki/pkg/logcli/client"
|
||||||
"github.com/grafana/loki/pkg/loghttp"
|
"github.com/grafana/loki/pkg/loghttp"
|
||||||
"github.com/grafana/loki/pkg/logproto"
|
"github.com/grafana/loki/pkg/logproto"
|
||||||
@@ -29,17 +28,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
intervalCalculator intervalv2.Calculator
|
im instancemgmt.InstanceManager
|
||||||
im instancemgmt.InstanceManager
|
plog log.Logger
|
||||||
plog log.Logger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvideService(httpClientProvider httpclient.Provider, registrar plugins.CoreBackendRegistrar) (*Service, error) {
|
func ProvideService(httpClientProvider httpclient.Provider, registrar plugins.CoreBackendRegistrar) (*Service, error) {
|
||||||
im := datasource.NewInstanceManager(newInstanceSettings(httpClientProvider))
|
im := datasource.NewInstanceManager(newInstanceSettings(httpClientProvider))
|
||||||
s := &Service{
|
s := &Service{
|
||||||
im: im,
|
im: im,
|
||||||
intervalCalculator: intervalv2.NewCalculator(),
|
plog: log.New("tsdb.loki"),
|
||||||
plog: log.New("tsdb.loki"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
factory := coreplugin.New(backend.ServeOpts{
|
factory := coreplugin.New(backend.ServeOpts{
|
||||||
@@ -131,7 +128,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
queries, err := s.parseQuery(dsInfo, req)
|
queries, err := parseQuery(dsInfo, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
@@ -183,7 +180,7 @@ func formatLegend(metric model.Metric, query *lokiQuery) string {
|
|||||||
return string(result)
|
return string(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) parseQuery(dsInfo *datasourceInfo, queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) {
|
func parseQuery(dsInfo *datasourceInfo, queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) {
|
||||||
qs := []*lokiQuery{}
|
qs := []*lokiQuery{}
|
||||||
for _, query := range queryContext.Queries {
|
for _, query := range queryContext.Queries {
|
||||||
model := &ResponseModel{}
|
model := &ResponseModel{}
|
||||||
@@ -195,19 +192,12 @@ func (s *Service) parseQuery(dsInfo *datasourceInfo, queryContext *backend.Query
|
|||||||
start := query.TimeRange.From
|
start := query.TimeRange.From
|
||||||
end := query.TimeRange.To
|
end := query.TimeRange.To
|
||||||
|
|
||||||
dsInterval, err := intervalv2.GetIntervalFrom(dsInfo.TimeInterval, model.Interval, int64(model.IntervalMS), time.Second)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse Interval: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
interval := s.intervalCalculator.Calculate(query.TimeRange, dsInterval, query.MaxDataPoints)
|
|
||||||
|
|
||||||
var resolution int64 = 1
|
var resolution int64 = 1
|
||||||
if model.Resolution >= 1 && model.Resolution <= 5 || model.Resolution == 10 {
|
if model.Resolution >= 1 && model.Resolution <= 5 || model.Resolution == 10 {
|
||||||
resolution = model.Resolution
|
resolution = model.Resolution
|
||||||
}
|
}
|
||||||
|
|
||||||
step := time.Duration(int64(interval.Value) * resolution)
|
step := time.Duration(int64(query.Interval) * resolution)
|
||||||
|
|
||||||
qs = append(qs, &lokiQuery{
|
qs = append(qs, &lokiQuery{
|
||||||
Expr: model.Expr,
|
Expr: model.Expr,
|
||||||
|
|||||||
+22
-35
@@ -8,7 +8,6 @@ import (
|
|||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
|
||||||
"github.com/grafana/loki/pkg/loghttp"
|
"github.com/grafana/loki/pkg/loghttp"
|
||||||
p "github.com/prometheus/common/model"
|
p "github.com/prometheus/common/model"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -57,24 +56,18 @@ func TestLoki(t *testing.T) {
|
|||||||
From: time.Now().Add(-30 * time.Second),
|
From: time.Now().Add(-30 * time.Second),
|
||||||
To: time.Now(),
|
To: time.Now(),
|
||||||
},
|
},
|
||||||
},
|
Interval: time.Second * 30,
|
||||||
},
|
|
||||||
}
|
|
||||||
service := &Service{
|
|
||||||
intervalCalculator: mockCalculator{
|
|
||||||
interval: intervalv2.Interval{
|
|
||||||
Value: time.Second * 30,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
dsInfo := &datasourceInfo{}
|
dsInfo := &datasourceInfo{}
|
||||||
models, err := service.parseQuery(dsInfo, queryContext)
|
models, err := parseQuery(dsInfo, queryContext)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, time.Second*30, models[0].Step)
|
require.Equal(t, time.Second*30, models[0].Step)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("parsing query model without step parameter", func(t *testing.T) {
|
t.Run("parsing query model without step parameter", func(t *testing.T) {
|
||||||
queryContext := &backend.QueryDataRequest{
|
queryContext1 := &backend.QueryDataRequest{
|
||||||
Queries: []backend.DataQuery{
|
Queries: []backend.DataQuery{
|
||||||
{
|
{
|
||||||
JSON: []byte(`
|
JSON: []byte(`
|
||||||
@@ -88,29 +81,35 @@ func TestLoki(t *testing.T) {
|
|||||||
From: time.Now().Add(-48 * time.Hour),
|
From: time.Now().Add(-48 * time.Hour),
|
||||||
To: time.Now(),
|
To: time.Now(),
|
||||||
},
|
},
|
||||||
},
|
Interval: time.Minute * 2,
|
||||||
},
|
|
||||||
}
|
|
||||||
service := &Service{
|
|
||||||
intervalCalculator: mockCalculator{
|
|
||||||
interval: intervalv2.Interval{
|
|
||||||
Value: time.Minute * 2,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
dsInfo := &datasourceInfo{}
|
dsInfo := &datasourceInfo{}
|
||||||
models, err := service.parseQuery(dsInfo, queryContext)
|
models, err := parseQuery(dsInfo, queryContext1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, time.Minute*2, models[0].Step)
|
require.Equal(t, time.Minute*2, models[0].Step)
|
||||||
|
|
||||||
service = &Service{
|
queryContext2 := &backend.QueryDataRequest{
|
||||||
intervalCalculator: mockCalculator{
|
Queries: []backend.DataQuery{
|
||||||
interval: intervalv2.Interval{
|
{
|
||||||
Value: time.Second * 2,
|
JSON: []byte(`
|
||||||
|
{
|
||||||
|
"expr": "go_goroutines",
|
||||||
|
"format": "time_series",
|
||||||
|
"refId": "A"
|
||||||
|
}`,
|
||||||
|
),
|
||||||
|
TimeRange: backend.TimeRange{
|
||||||
|
From: time.Now().Add(-48 * time.Hour),
|
||||||
|
To: time.Now(),
|
||||||
|
},
|
||||||
|
Interval: time.Second * 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
models, err = service.parseQuery(dsInfo, queryContext)
|
|
||||||
|
models, err = parseQuery(dsInfo, queryContext2)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fmt.Println(models)
|
fmt.Println(models)
|
||||||
require.Equal(t, time.Second*2, models[0].Step)
|
require.Equal(t, time.Second*2, models[0].Step)
|
||||||
@@ -173,15 +172,3 @@ func TestParseResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockCalculator struct {
|
|
||||||
interval intervalv2.Interval
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m mockCalculator) Calculate(timerange backend.TimeRange, minInterval time.Duration, maxDataPoints int64) intervalv2.Interval {
|
|
||||||
return m.interval
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m mockCalculator) CalculateSafeInterval(timerange backend.TimeRange, resolution int64) intervalv2.Interval {
|
|
||||||
return m.interval
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user