Skip to content

Commit e3e1f09

Browse files
feat: store details of processed streams while processing delete requests (#16825)
1 parent 8948c11 commit e3e1f09

24 files changed

+1073
-428
lines changed

‎pkg/compactor/compactor.go

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ import (
1313
"unsafe"
1414

1515
"github.com/go-kit/log/level"
16-
"github.com/pkg/errors"
17-
"github.com/prometheus/client_golang/prometheus"
18-
"github.com/prometheus/common/model"
19-
2016
"github.com/grafana/dskit/backoff"
2117
"github.com/grafana/dskit/kv"
2218
"github.com/grafana/dskit/ring"
2319
"github.com/grafana/dskit/services"
20+
"github.com/pkg/errors"
21+
"github.com/prometheus/client_golang/prometheus"
22+
"github.com/prometheus/common/model"
23+
"github.com/prometheus/prometheus/model/labels"
2424

2525
"github.com/grafana/loki/v3/pkg/analytics"
2626
"github.com/grafana/loki/v3/pkg/compactor/deletion"
@@ -406,13 +406,10 @@ func (c *Compactor) initDeletes(objectClient client.ObjectClient, indexUpdatePro
406406

407407
c.DeleteRequestsGRPCHandler = deletion.NewGRPCRequestHandler(c.deleteRequestsStore, limits)
408408

409-
c.deleteRequestsManager = deletion.NewDeleteRequestsManager(
410-
c.deleteRequestsStore,
411-
c.cfg.DeleteRequestCancelPeriod,
412-
c.cfg.DeleteBatchSize,
413-
limits,
414-
r,
415-
)
409+
c.deleteRequestsManager, err = deletion.NewDeleteRequestsManager(deletionWorkDir, c.deleteRequestsStore, c.cfg.DeleteRequestCancelPeriod, c.cfg.DeleteBatchSize, limits, r)
410+
if err != nil {
411+
return err
412+
}
416413

417414
c.expirationChecker = newExpirationChecker(retention.NewExpirationChecker(limits), c.deleteRequestsManager)
418415
return nil
@@ -853,12 +850,12 @@ func newExpirationChecker(retentionExpiryChecker, deletionExpiryChecker retentio
853850
return &expirationChecker{retentionExpiryChecker, deletionExpiryChecker}
854851
}
855852

856-
func (e *expirationChecker) Expired(ref retention.ChunkEntry, now model.Time) (bool, filter.Func) {
857-
if expired, nonDeletedIntervals := e.retentionExpiryChecker.Expired(ref, now); expired {
853+
func (e *expirationChecker) Expired(userID []byte, chk retention.Chunk, lbls labels.Labels, seriesID []byte, tableName string, now model.Time) (bool, filter.Func) {
854+
if expired, nonDeletedIntervals := e.retentionExpiryChecker.Expired(userID, chk, lbls, seriesID, tableName, now); expired {
858855
return expired, nonDeletedIntervals
859856
}
860857

861-
return e.deletionExpiryChecker.Expired(ref, now)
858+
return e.deletionExpiryChecker.Expired(userID, chk, lbls, seriesID, tableName, now)
862859
}
863860

864861
func (e *expirationChecker) MarkPhaseStarted() {
@@ -885,8 +882,12 @@ func (e *expirationChecker) IntervalMayHaveExpiredChunks(interval model.Interval
885882
return e.retentionExpiryChecker.IntervalMayHaveExpiredChunks(interval, userID) || e.deletionExpiryChecker.IntervalMayHaveExpiredChunks(interval, userID)
886883
}
887884

888-
func (e *expirationChecker) DropFromIndex(ref retention.ChunkEntry, tableEndTime model.Time, now model.Time) bool {
889-
return e.retentionExpiryChecker.DropFromIndex(ref, tableEndTime, now) || e.deletionExpiryChecker.DropFromIndex(ref, tableEndTime, now)
885+
func (e *expirationChecker) DropFromIndex(userID []byte, chk retention.Chunk, labels labels.Labels, tableEndTime model.Time, now model.Time) bool {
886+
return e.retentionExpiryChecker.DropFromIndex(userID, chk, labels, tableEndTime, now) || e.deletionExpiryChecker.DropFromIndex(userID, chk, labels, tableEndTime, now)
887+
}
888+
889+
func (e *expirationChecker) CanSkipSeries(userID []byte, lbls labels.Labels, seriesID []byte, seriesStart model.Time, tableName string, now model.Time) bool {
890+
return e.retentionExpiryChecker.CanSkipSeries(userID, lbls, seriesID, seriesStart, tableName, now) && e.deletionExpiryChecker.CanSkipSeries(userID, lbls, seriesID, seriesStart, tableName, now)
890891
}
891892

892893
func (c *Compactor) OnRingInstanceRegister(_ *ring.BasicLifecycler, ringDesc ring.Desc, instanceExists bool, _ string, instanceDesc ring.InstanceDesc) (ring.InstanceState, ring.Tokens) {

‎pkg/compactor/deletion/delete_request.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,14 @@ func allMatch(matchers []*labels.Matcher, labels labels.Labels) bool {
109109
// IsDeleted checks if the given ChunkEntry will be deleted by this DeleteRequest.
110110
// It returns a filter.Func if the chunk is supposed to be deleted partially or the delete request contains line filters.
111111
// If the filter.Func is nil, the whole chunk is supposed to be deleted.
112-
func (d *DeleteRequest) IsDeleted(entry retention.ChunkEntry) (bool, filter.Func) {
113-
if d.UserID != unsafeGetString(entry.UserID) {
112+
func (d *DeleteRequest) IsDeleted(userID []byte, lbls labels.Labels, chunk retention.Chunk) (bool, filter.Func) {
113+
if d.UserID != unsafeGetString(userID) {
114114
return false, nil
115115
}
116116

117117
if !intervalsOverlap(model.Interval{
118-
Start: entry.From,
119-
End: entry.Through,
118+
Start: chunk.From,
119+
End: chunk.Through,
120120
}, model.Interval{
121121
Start: d.StartTime,
122122
End: d.EndTime,
@@ -137,16 +137,16 @@ func (d *DeleteRequest) IsDeleted(entry retention.ChunkEntry) (bool, filter.Func
137137
}
138138
}
139139

140-
if !labels.Selector(d.matchers).Matches(entry.Labels) {
140+
if !labels.Selector(d.matchers).Matches(lbls) {
141141
return false, nil
142142
}
143143

144-
if d.StartTime <= entry.From && d.EndTime >= entry.Through && !d.logSelectorExpr.HasFilter() {
144+
if d.StartTime <= chunk.From && d.EndTime >= chunk.Through && !d.logSelectorExpr.HasFilter() {
145145
// Delete request covers the whole chunk and there are no line filters in the logSelectorExpr so the whole chunk will be deleted
146146
return true, nil
147147
}
148148

149-
ff, err := d.FilterFunction(entry.Labels)
149+
ff, err := d.FilterFunction(lbls)
150150
if err != nil {
151151
// The query in the delete request is checked when added to the table.
152152
// So this error should not occur.

‎pkg/compactor/deletion/delete_request_test.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,9 @@ func TestDeleteRequest_IsDeleted(t *testing.T) {
3333
lblWithStructuredMetadataFilter := `{foo="bar", fizz="buzz"} | ping="pong"`
3434
lblWithLineAndStructuredMetadataFilter := `{foo="bar", fizz="buzz"} | ping="pong" |= "filter"`
3535

36-
chunkEntry := retention.ChunkEntry{
37-
ChunkRef: retention.ChunkRef{
38-
UserID: []byte(user1),
39-
From: now.Add(-3 * time.Hour),
40-
Through: now.Add(-time.Hour),
41-
},
42-
Labels: mustParseLabel(lbl),
36+
chunkEntry := retention.Chunk{
37+
From: now.Add(-3 * time.Hour),
38+
Through: now.Add(-time.Hour),
4339
}
4440

4541
type resp struct {
@@ -275,7 +271,7 @@ func TestDeleteRequest_IsDeleted(t *testing.T) {
275271
t.Run(tc.name, func(t *testing.T) {
276272
require.NoError(t, tc.deleteRequest.SetQuery(tc.deleteRequest.Query))
277273
tc.deleteRequest.Metrics = newDeleteRequestsManagerMetrics(nil)
278-
isExpired, filterFunc := tc.deleteRequest.IsDeleted(chunkEntry)
274+
isExpired, filterFunc := tc.deleteRequest.IsDeleted([]byte(user1), mustParseLabel(lbl), chunkEntry)
279275
require.Equal(t, tc.expectedResp.isDeleted, isExpired)
280276
if tc.expectedResp.expectedFilter == nil {
281277
require.Nil(t, filterFunc)

0 commit comments

Comments
 (0)