|
|
@ -30,6 +30,58 @@ var ( |
|
|
|
ErrMockMultiple = util.MultiError{ErrMock, ErrMock} |
|
|
|
ErrMockMultiple = util.MultiError{ErrMock, ErrMock} |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func TestEngine_LogsRateUnwrap(t *testing.T) { |
|
|
|
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
for _, test := range []struct { |
|
|
|
|
|
|
|
qs string |
|
|
|
|
|
|
|
ts time.Time |
|
|
|
|
|
|
|
direction logproto.Direction |
|
|
|
|
|
|
|
limit uint32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// an array of data per params will be returned by the querier.
|
|
|
|
|
|
|
|
// This is to cover logql that requires multiple queries.
|
|
|
|
|
|
|
|
data interface{} |
|
|
|
|
|
|
|
params interface{} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expected interface{} |
|
|
|
|
|
|
|
}{ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
`rate({app="foo"} | unwrap foo [30s])`, time.Unix(60, 0), logproto.FORWARD, 10, |
|
|
|
|
|
|
|
[][]logproto.Series{ |
|
|
|
|
|
|
|
// 30s range the lower bound of the range is not inclusive only 15 samples will make it 60 included
|
|
|
|
|
|
|
|
{newSeries(testSize, offset(46, incValue(10)), `{app="foo"}`)}, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
[]SelectSampleParams{ |
|
|
|
|
|
|
|
{&logproto.SampleQueryRequest{Start: time.Unix(30, 0), End: time.Unix(60, 0), Selector: `rate({app="foo"} | unwrap foo[30s])`}}, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
promql.Vector{promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0.46666766666666665}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}}}}, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
} { |
|
|
|
|
|
|
|
test := test |
|
|
|
|
|
|
|
t.Run(fmt.Sprintf("%s %s", test.qs, test.direction), func(t *testing.T) { |
|
|
|
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
eng := NewEngine(EngineOpts{}, newQuerierRecorder(t, test.data, test.params), NoLimits) |
|
|
|
|
|
|
|
q := eng.Query(LiteralParams{ |
|
|
|
|
|
|
|
qs: test.qs, |
|
|
|
|
|
|
|
start: test.ts, |
|
|
|
|
|
|
|
end: test.ts, |
|
|
|
|
|
|
|
direction: test.direction, |
|
|
|
|
|
|
|
limit: test.limit, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
res, err := q.Exec(user.InjectOrgID(context.Background(), "fake")) |
|
|
|
|
|
|
|
if expectedError, ok := test.expected.(error); ok { |
|
|
|
|
|
|
|
assert.Equal(t, expectedError.Error(), err.Error()) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
t.Fatal(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
assert.Equal(t, test.expected, res.Data) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestEngine_LogsInstantQuery(t *testing.T) { |
|
|
|
func TestEngine_LogsInstantQuery(t *testing.T) { |
|
|
|
t.Parallel() |
|
|
|
t.Parallel() |
|
|
|
for _, test := range []struct { |
|
|
|
for _, test := range []struct { |
|
|
@ -95,7 +147,7 @@ func TestEngine_LogsInstantQuery(t *testing.T) { |
|
|
|
[]SelectSampleParams{ |
|
|
|
[]SelectSampleParams{ |
|
|
|
{&logproto.SampleQueryRequest{Start: time.Unix(30, 0), End: time.Unix(60, 0), Selector: `rate({app="foo"} | unwrap foo[30s])`}}, |
|
|
|
{&logproto.SampleQueryRequest{Start: time.Unix(30, 0), End: time.Unix(60, 0), Selector: `rate({app="foo"} | unwrap foo[30s])`}}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
promql.Vector{promql.Sample{Point: promql.Point{T: 60 * 1000, V: 1.0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}}}}, |
|
|
|
promql.Vector{promql.Sample{Point: promql.Point{T: 60 * 1000, V: 0.0}, Metric: labels.Labels{labels.Label{Name: "app", Value: "foo"}}}}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
{ |
|
|
|
`count_over_time({app="foo"} |~".+bar" [1m])`, time.Unix(60, 0), logproto.BACKWARD, 10, |
|
|
|
`count_over_time({app="foo"} |~".+bar" [1m])`, time.Unix(60, 0), logproto.BACKWARD, 10, |
|
|
@ -1240,11 +1292,11 @@ func TestEngine_RangeQuery(t *testing.T) { |
|
|
|
promql.Matrix{ |
|
|
|
promql.Matrix{ |
|
|
|
promql.Series{ |
|
|
|
promql.Series{ |
|
|
|
Metric: labels.Labels{{Name: "app", Value: "bar"}}, |
|
|
|
Metric: labels.Labels{{Name: "app", Value: "bar"}}, |
|
|
|
Points: []promql.Point{{T: 60 * 1000, V: 0.4}, {T: 90 * 1000, V: 0.4}, {T: 120 * 1000, V: 0.4}, {T: 150 * 1000, V: 0.4}, {T: 180 * 1000, V: 0.4}}, |
|
|
|
Points: []promql.Point{{T: 60 * 1000, V: 0.0}, {T: 90 * 1000, V: 0.0}, {T: 120 * 1000, V: 0.0}, {T: 150 * 1000, V: 0.0}, {T: 180 * 1000, V: 0.0}}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
promql.Series{ |
|
|
|
promql.Series{ |
|
|
|
Metric: labels.Labels{{Name: "app", Value: "foo"}}, |
|
|
|
Metric: labels.Labels{{Name: "app", Value: "foo"}}, |
|
|
|
Points: []promql.Point{{T: 60 * 1000, V: 0.2}, {T: 90 * 1000, V: 0.2}, {T: 120 * 1000, V: 0.2}, {T: 150 * 1000, V: 0.2}, {T: 180 * 1000, V: 0.2}}, |
|
|
|
Points: []promql.Point{{T: 60 * 1000, V: 0.0}, {T: 90 * 1000, V: 0.0}, {T: 120 * 1000, V: 0.0}, {T: 150 * 1000, V: 0.0}, {T: 180 * 1000, V: 0.0}}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
@ -2451,6 +2503,23 @@ func constantValue(t int64) generator { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// nolint
|
|
|
|
|
|
|
|
func incValue(val int64) generator { |
|
|
|
|
|
|
|
return func(i int64) logData { |
|
|
|
|
|
|
|
return logData{ |
|
|
|
|
|
|
|
Entry: logproto.Entry{ |
|
|
|
|
|
|
|
Timestamp: time.Unix(i, 0), |
|
|
|
|
|
|
|
Line: fmt.Sprintf("%d", i), |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
Sample: logproto.Sample{ |
|
|
|
|
|
|
|
Timestamp: time.Unix(i, 0).UnixNano(), |
|
|
|
|
|
|
|
Hash: uint64(i), |
|
|
|
|
|
|
|
Value: float64(val + i), |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// nolint
|
|
|
|
// nolint
|
|
|
|
func inverse(g generator) generator { |
|
|
|
func inverse(g generator) generator { |
|
|
|
return func(i int64) logData { |
|
|
|
return func(i int64) logData { |
|
|
|