@ -21,87 +21,152 @@ import (
var nilMetrics = NewSplitByMetrics ( nil )
func Test_splitQuery ( t * testing . T ) {
tests := [ ] struct {
name string
req queryrangebase . Request
interval time . Duration
want [ ] queryrangebase . Request
buildLokiRequest := func ( start , end time . Time ) queryrangebase . Request {
return & LokiRequest {
Query : "foo" ,
Limit : 1 ,
Step : 2 ,
StartTs : start ,
EndTs : end ,
Direction : logproto . BACKWARD ,
Path : "/path" ,
}
}
buildLokiSeriesRequest := func ( start , end time . Time ) queryrangebase . Request {
return & LokiSeriesRequest {
Match : [ ] string { "match1" } ,
StartTs : start ,
EndTs : end ,
Path : "/series" ,
Shards : [ ] string { "shard1" } ,
}
}
buildLokiLabelNamesRequest := func ( start , end time . Time ) queryrangebase . Request {
return & LokiLabelNamesRequest {
StartTs : start ,
EndTs : end ,
Path : "/labels" ,
}
}
type interval struct {
start , end time . Time
}
for requestType , tc := range map [ string ] struct {
requestBuilderFunc func ( start , end time . Time ) queryrangebase . Request
endTimeInclusive bool
} {
{
"smaller request than interval" ,
& LokiRequest {
StartTs : time . Date ( 2019 , 12 , 9 , 12 , 0 , 0 , 1 , time . UTC ) ,
EndTs : time . Date ( 2019 , 12 , 9 , 12 , 30 , 0 , 0 , time . UTC ) ,
} ,
time . Hour ,
[ ] queryrangebase . Request {
& LokiRequest {
StartTs : time . Date ( 2019 , 12 , 9 , 12 , 0 , 0 , 1 , time . UTC ) ,
EndTs : time . Date ( 2019 , 12 , 9 , 12 , 30 , 0 , 0 , time . UTC ) ,
} ,
} ,
"LokiRequest" : {
buildLokiRequest ,
false ,
} ,
{
"exactly 1 interval" ,
& LokiRequest {
StartTs : time . Date ( 2019 , 12 , 9 , 12 , 1 , 0 , 0 , time . UTC ) ,
EndTs : time . Date ( 2019 , 12 , 9 , 13 , 1 , 0 , 0 , time . UTC ) ,
} ,
time . Hour ,
[ ] queryrangebase . Request {
& LokiRequest {
StartTs : time . Date ( 2019 , 12 , 9 , 12 , 1 , 0 , 0 , time . UTC ) ,
EndTs : time . Date ( 2019 , 12 , 9 , 13 , 1 , 0 , 0 , time . UTC ) ,
} ,
} ,
"LokiSeriesRequest" : {
buildLokiSeriesRequest ,
true ,
} ,
{
"2 intervals" ,
& LokiRequest {
StartTs : time . Date ( 2019 , 12 , 9 , 12 , 0 , 0 , 1 , time . UTC ) ,
EndTs : time . Date ( 2019 , 12 , 9 , 13 , 0 , 0 , 2 , time . UTC ) ,
"LokiLabelNamesRequest" : {
buildLokiLabelNamesRequest ,
true ,
} ,
} {
expectedSplitGap := time . Duration ( 0 )
if tc . endTimeInclusive {
expectedSplitGap = time . Millisecond
}
for name , intervals := range map [ string ] struct {
inp interval
expected [ ] interval
} {
"no_change" : {
inp : interval {
start : time . Unix ( 0 , 0 ) ,
end : time . Unix ( 0 , ( 1 * time . Hour ) . Nanoseconds ( ) ) ,
} ,
expected : [ ] interval {
{
start : time . Unix ( 0 , 0 ) ,
end : time . Unix ( 0 , ( 1 * time . Hour ) . Nanoseconds ( ) ) ,
} ,
} ,
} ,
time . Hour ,
[ ] queryrangebase . Request {
& LokiRequest {
StartTs : time . Date ( 2019 , 12 , 9 , 12 , 0 , 0 , 1 , time . UTC ) ,
EndTs : time . Date ( 2019 , 12 , 9 , 13 , 0 , 0 , 1 , time . UTC ) ,
"align_start" : {
inp : interval {
start : time . Unix ( 0 , ( 5 * time . Minute ) . Nanoseconds ( ) ) ,
end : time . Unix ( 0 , ( 2 * time . Hour ) . Nanoseconds ( ) ) ,
} ,
& LokiRequest {
StartTs : time . Date ( 2019 , 12 , 9 , 13 , 0 , 0 , 1 , time . UTC ) ,
EndTs : time . Date ( 2019 , 12 , 9 , 13 , 0 , 0 , 2 , time . UTC ) ,
expected : [ ] interval {
{
start : time . Unix ( 0 , ( 5 * time . Minute ) . Nanoseconds ( ) ) ,
end : time . Unix ( 0 , ( 1 * time . Hour ) . Nanoseconds ( ) ) . Add ( - expectedSplitGap ) ,
} ,
{
start : time . Unix ( 0 , ( 1 * time . Hour ) . Nanoseconds ( ) ) ,
end : time . Unix ( 0 , ( 2 * time . Hour ) . Nanoseconds ( ) ) ,
} ,
} ,
} ,
} ,
{
"3 intervals series" ,
& LokiSeriesRequest {
StartTs : time . Date ( 2019 , 12 , 9 , 12 , 0 , 0 , 1 , time . UTC ) ,
EndTs : time . Date ( 2019 , 12 , 9 , 16 , 0 , 0 , 2 , time . UTC ) ,
"align_end" : {
inp : interval {
start : time . Unix ( 0 , 0 ) ,
end : time . Unix ( 0 , ( 115 * time . Minute ) . Nanoseconds ( ) ) ,
} ,
expected : [ ] interval {
{
start : time . Unix ( 0 , 0 ) ,
end : time . Unix ( 0 , ( 1 * time . Hour ) . Nanoseconds ( ) ) . Add ( - expectedSplitGap ) ,
} ,
{
start : time . Unix ( 0 , ( 1 * time . Hour ) . Nanoseconds ( ) ) ,
end : time . Unix ( 0 , ( 115 * time . Minute ) . Nanoseconds ( ) ) ,
} ,
} ,
} ,
2 * time . Hour ,
[ ] queryrangebase . Request {
& LokiSeriesRequest {
StartTs : time . Date ( 2019 , 12 , 9 , 12 , 0 , 0 , 1 , time . UTC ) ,
EndTs : time . Date ( 2019 , 12 , 9 , 14 , 0 , 0 , 1 , time . UTC ) ,
"align_both" : {
inp : interval {
start : time . Unix ( 0 , ( 5 * time . Minute ) . Nanoseconds ( ) ) ,
end : time . Unix ( 0 , ( 175 * time . Minute ) . Nanoseconds ( ) ) ,
} ,
expected : [ ] interval {
{
start : time . Unix ( 0 , ( 5 * time . Minute ) . Nanoseconds ( ) ) ,
end : time . Unix ( 0 , ( 1 * time . Hour ) . Nanoseconds ( ) ) . Add ( - expectedSplitGap ) ,
} ,
{
start : time . Unix ( 0 , ( 1 * time . Hour ) . Nanoseconds ( ) ) ,
end : time . Unix ( 0 , ( 2 * time . Hour ) . Nanoseconds ( ) ) . Add ( - expectedSplitGap ) ,
} ,
{
start : time . Unix ( 0 , ( 2 * time . Hour ) . Nanoseconds ( ) ) ,
end : time . Unix ( 0 , ( 175 * time . Minute ) . Nanoseconds ( ) ) ,
} ,
} ,
& LokiSeriesRequest {
StartTs : time . Date ( 2019 , 12 , 9 , 14 , 0 , 0 , 1 , time . UTC ) ,
EndTs : time . Date ( 2019 , 12 , 9 , 16 , 0 , 0 , 1 , time . UTC ) ,
} ,
"no_align" : {
inp : interval {
start : time . Unix ( 0 , ( 5 * time . Minute ) . Nanoseconds ( ) ) ,
end : time . Unix ( 0 , ( 55 * time . Minute ) . Nanoseconds ( ) ) ,
} ,
& LokiSeriesRequest {
StartTs : time . Date ( 2019 , 12 , 9 , 16 , 0 , 0 , 1 , time . UTC ) ,
EndTs : time . Date ( 2019 , 12 , 9 , 16 , 0 , 0 , 2 , time . UTC ) ,
expected : [ ] interval {
{
start : time . Unix ( 0 , ( 5 * time . Minute ) . Nanoseconds ( ) ) ,
end : time . Unix ( 0 , ( 55 * time . Minute ) . Nanoseconds ( ) ) ,
} ,
} ,
} ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
got , err := splitByTime ( tt . req , tt . interval )
require . NoError ( t , err )
require . Equal ( t , tt . want , got )
} )
} {
t . Run ( fmt . Sprintf ( "%s - %s" , name , requestType ) , func ( t * testing . T ) {
inp := tc . requestBuilderFunc ( intervals . inp . start , intervals . inp . end )
var want [ ] queryrangebase . Request
for _ , interval := range intervals . expected {
want = append ( want , tc . requestBuilderFunc ( interval . start , interval . end ) )
}
splits , err := splitByTime ( inp , time . Hour )
require . NoError ( t , err )
require . Equal ( t , want , splits )
} )
}
}
}
@ -287,6 +352,68 @@ func Test_splitMetricQuery(t *testing.T) {
interval : 3 * time . Hour ,
} ,
// step not a multiple of interval
// start time already step aligned
{
input : & LokiRequest {
StartTs : time . Unix ( 2 * 3600 - 9 , 0 ) , // 2h mod 17s = 9s
EndTs : time . Unix ( 3 * 3 * 3600 , 0 ) ,
Step : 17 * seconds ,
Query : ` rate( { app="foo"}[1m]) ` ,
} ,
expected : [ ] queryrangebase . Request {
& LokiRequest {
StartTs : time . Unix ( 2 * 3600 - 9 , 0 ) ,
EndTs : time . Unix ( ( 3 * 3600 ) - 5 , 0 ) , // 3h mod 17s = 5s
Step : 17 * seconds ,
Query : ` rate( { app="foo"}[1m]) ` ,
} ,
& LokiRequest {
StartTs : time . Unix ( ( 3 * 3600 ) + 12 , 0 ) ,
EndTs : time . Unix ( ( 2 * 3 * 3600 ) - 10 , 0 ) , // 6h mod 17s = 10s
Step : 17 * seconds ,
Query : ` rate( { app="foo"}[1m]) ` ,
} ,
& LokiRequest {
StartTs : time . Unix ( 2 * 3 * 3600 + 7 , 0 ) ,
EndTs : time . Unix ( 3 * 3 * 3600 , 0 ) ,
Step : 17 * seconds ,
Query : ` rate( { app="foo"}[1m]) ` ,
} ,
} ,
interval : 3 * time . Hour ,
} ,
// start time not aligned with step
{
input : & LokiRequest {
StartTs : time . Unix ( 2 * 3600 , 0 ) ,
EndTs : time . Unix ( 3 * 3 * 3600 , 0 ) ,
Step : 17 * seconds ,
Query : ` rate( { app="foo"}[1m]) ` ,
} ,
expected : [ ] queryrangebase . Request {
& LokiRequest {
StartTs : time . Unix ( 2 * 3600 , 0 ) ,
EndTs : time . Unix ( ( 3 * 3600 ) - 5 , 0 ) , // 3h mod 17s = 5s
Step : 17 * seconds ,
Query : ` rate( { app="foo"}[1m]) ` ,
} ,
& LokiRequest {
StartTs : time . Unix ( ( 3 * 3600 ) + 12 , 0 ) ,
EndTs : time . Unix ( ( 2 * 3 * 3600 ) - 10 , 0 ) , // 6h mod 17s = 10s
Step : 17 * seconds ,
Query : ` rate( { app="foo"}[1m]) ` ,
} ,
& LokiRequest {
StartTs : time . Unix ( 2 * 3 * 3600 + 7 , 0 ) ,
EndTs : time . Unix ( 3 * 3 * 3600 , 0 ) ,
Step : 17 * seconds ,
Query : ` rate( { app="foo"}[1m]) ` ,
} ,
} ,
interval : 3 * time . Hour ,
} ,
// step larger than split interval
{
input : & LokiRequest {