Skip to content

Commit 738c274

Browse files
authored
fix(blooms): Fix partitionSeriesByDay function (#12900)
The function `partitionSeriesByDay` could yield empty when chunks were outside of the requested time range. This would result in requests for a time range that does not contain any chunks for a series to filter. These requests would return errors, because a subsequent `partitionSeriesByDay` for would remove that day resulting in no task. Signed-off-by: Christian Haudum <[email protected]>
1 parent 1951322 commit 738c274

File tree

3 files changed

+42
-13
lines changed

3 files changed

+42
-13
lines changed

pkg/bloomgateway/bloomgateway.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ func (g *Gateway) FilterChunkRefs(ctx context.Context, req *logproto.FilterChunk
274274
"series_requested", len(req.Refs),
275275
)
276276

277-
if len(seriesByDay) != 1 {
277+
if len(seriesByDay) > 1 {
278278
stats.Status = labelFailure
279279
return nil, errors.New("request time range must span exactly one day")
280280
}

pkg/bloomgateway/util.go

+2-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package bloomgateway
22

33
import (
44
"sort"
5-
"time"
65

76
"github.com/prometheus/common/model"
87
"golang.org/x/exp/slices"
@@ -13,13 +12,8 @@ import (
1312
"github.com/grafana/loki/v3/pkg/storage/stores/shipper/bloomshipper"
1413
)
1514

16-
func getDayTime(ts model.Time) time.Time {
17-
return ts.Time().UTC().Truncate(Day)
18-
}
19-
2015
func truncateDay(ts model.Time) model.Time {
21-
// model.minimumTick is time.Millisecond
22-
return ts - (ts % model.Time(24*time.Hour/time.Millisecond))
16+
return model.TimeFromUnix(ts.Time().Truncate(Day).Unix())
2317
}
2418

2519
// getFromThrough assumes a list of ShortRefs sorted by From time
@@ -125,7 +119,7 @@ func partitionSeriesByDay(from, through model.Time, seriesWithChunks []*logproto
125119
})
126120

127121
// All chunks fall outside of the range
128-
if min == len(chunks) || max == 0 {
122+
if min == len(chunks) || max == 0 || min == max {
129123
continue
130124
}
131125

@@ -135,7 +129,6 @@ func partitionSeriesByDay(from, through model.Time, seriesWithChunks []*logproto
135129
if chunks[max-1].Through > maxTs {
136130
maxTs = chunks[max-1].Through
137131
}
138-
// fmt.Println("day", day, "series", series.Fingerprint, "minTs", minTs, "maxTs", maxTs)
139132

140133
res = append(res, &logproto.GroupedChunkRefs{
141134
Fingerprint: series.Fingerprint,

pkg/bloomgateway/util_test.go

+39-3
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,46 @@ func TestPartitionRequest(t *testing.T) {
166166
exp []seriesWithInterval
167167
}{
168168

169-
"empty": {
169+
"no series": {
170170
inp: &logproto.FilterChunkRefRequest{
171-
From: ts.Add(-24 * time.Hour),
172-
Through: ts,
171+
From: ts.Add(-12 * time.Hour),
172+
Through: ts.Add(12 * time.Hour),
173+
Refs: []*logproto.GroupedChunkRefs{},
174+
},
175+
exp: []seriesWithInterval{},
176+
},
177+
178+
"no chunks for series": {
179+
inp: &logproto.FilterChunkRefRequest{
180+
From: ts.Add(-12 * time.Hour),
181+
Through: ts.Add(12 * time.Hour),
182+
Refs: []*logproto.GroupedChunkRefs{
183+
{
184+
Fingerprint: 0x00,
185+
Refs: []*logproto.ShortRef{},
186+
},
187+
{
188+
Fingerprint: 0x10,
189+
Refs: []*logproto.ShortRef{},
190+
},
191+
},
192+
},
193+
exp: []seriesWithInterval{},
194+
},
195+
196+
"chunks before and after requested day": {
197+
inp: &logproto.FilterChunkRefRequest{
198+
From: ts.Add(-2 * time.Hour),
199+
Through: ts.Add(2 * time.Hour),
200+
Refs: []*logproto.GroupedChunkRefs{
201+
{
202+
Fingerprint: 0x00,
203+
Refs: []*logproto.ShortRef{
204+
{From: ts.Add(-13 * time.Hour), Through: ts.Add(-12 * time.Hour)},
205+
{From: ts.Add(13 * time.Hour), Through: ts.Add(14 * time.Hour)},
206+
},
207+
},
208+
},
173209
},
174210
exp: []seriesWithInterval{},
175211
},

0 commit comments

Comments
 (0)