@@ -243,6 +243,15 @@ func (c *BlocksCleaner) loop(ctx context.Context) error {
243
243
go func () {
244
244
c .runDeleteUserCleanup (ctx , deleteChan )
245
245
}()
246
+ var metricsChan chan * cleanerJob
247
+ if c .cfg .ShardingStrategy == util .ShardingStrategyShuffle &&
248
+ c .cfg .CompactionStrategy == util .CompactionStrategyPartitioning {
249
+ metricsChan = make (chan * cleanerJob )
250
+ defer close (metricsChan )
251
+ go func () {
252
+ c .runEmitMetricsWorker (ctx , metricsChan )
253
+ }()
254
+ }
246
255
247
256
for {
248
257
select {
@@ -276,6 +285,17 @@ func (c *BlocksCleaner) loop(ctx context.Context) error {
276
285
c .enqueueJobFailed .WithLabelValues (deletedStatus ).Inc ()
277
286
}
278
287
288
+ if metricsChan != nil {
289
+ select {
290
+ case metricsChan <- & cleanerJob {
291
+ users : activeUsers ,
292
+ timestamp : cleanJobTimestamp ,
293
+ }:
294
+ default :
295
+ level .Warn (c .logger ).Log ("msg" , "unable to push metrics job to metricsChan" )
296
+ }
297
+ }
298
+
279
299
case <- ctx .Done ():
280
300
return nil
281
301
}
@@ -295,10 +315,25 @@ func (c *BlocksCleaner) checkRunError(runType string, err error) {
295
315
}
296
316
}
297
317
298
- func (c * BlocksCleaner ) runActiveUserCleanup (ctx context.Context , jobChan chan * cleanerJob ) {
318
+ func (c * BlocksCleaner ) runEmitMetricsWorker (ctx context.Context , jobChan <- chan * cleanerJob ) {
319
+ for job := range jobChan {
320
+ err := concurrency .ForEachUser (ctx , job .users , c .cfg .CleanupConcurrency , func (ctx context.Context , userID string ) error {
321
+ userLogger := util_log .WithUserID (userID , c .logger )
322
+ userBucket := bucket .NewUserBucketClient (userID , c .bucketClient , c .cfgProvider )
323
+ c .emitUserMetrics (ctx , userLogger , userBucket , userID )
324
+ return nil
325
+ })
326
+
327
+ if err != nil {
328
+ level .Error (c .logger ).Log ("msg" , "emit metrics failed" , "err" , err .Error ())
329
+ }
330
+ }
331
+ }
332
+
333
+ func (c * BlocksCleaner ) runActiveUserCleanup (ctx context.Context , jobChan <- chan * cleanerJob ) {
299
334
for job := range jobChan {
300
335
if job .timestamp < time .Now ().Add (- c .cfg .CleanupInterval ).Unix () {
301
- level .Warn (c .logger ).Log ("Active user cleaner job too old. Ignoring to get recent data" )
336
+ level .Warn (c .logger ).Log ("msg" , " Active user cleaner job too old. Ignoring to get recent data" )
302
337
continue
303
338
}
304
339
err := c .cleanUpActiveUsers (ctx , job .users , false )
@@ -746,59 +781,14 @@ func (c *BlocksCleaner) updateBucketMetrics(userID string, parquetEnabled bool,
746
781
}
747
782
748
783
func (c * BlocksCleaner ) cleanPartitionedGroupInfo (ctx context.Context , userBucket objstore.InstrumentedBucket , userLogger log.Logger , userID string ) {
749
- existentPartitionedGroupInfo := make (map [* PartitionedGroupInfo ]struct {
750
- path string
751
- status PartitionedGroupStatus
752
- })
753
- err := userBucket .Iter (ctx , PartitionedGroupDirectory , func (file string ) error {
754
- if strings .Contains (file , PartitionVisitMarkerDirectory ) {
755
- return nil
756
- }
757
- partitionedGroupInfo , err := ReadPartitionedGroupInfoFile (ctx , userBucket , userLogger , file )
758
- if err != nil {
759
- level .Warn (userLogger ).Log ("msg" , "failed to read partitioned group info" , "partitioned_group_info" , file )
760
- return nil
761
- }
762
-
763
- status := partitionedGroupInfo .getPartitionedGroupStatus (ctx , userBucket , c .compactionVisitMarkerTimeout , userLogger )
764
- level .Debug (userLogger ).Log ("msg" , "got partitioned group status" , "partitioned_group_status" , status .String ())
765
- existentPartitionedGroupInfo [partitionedGroupInfo ] = struct {
766
- path string
767
- status PartitionedGroupStatus
768
- }{
769
- path : file ,
770
- status : status ,
771
- }
772
- return nil
773
- })
774
-
784
+ err , existentPartitionedGroupInfo := c .iterPartitionGroups (ctx , userBucket , userLogger )
775
785
if err != nil {
776
786
level .Warn (userLogger ).Log ("msg" , "error return when going through partitioned group directory" , "err" , err )
777
787
}
778
788
779
- remainingCompactions := 0
780
- inProgressCompactions := 0
781
- var oldestPartitionGroup * PartitionedGroupInfo
782
- defer func () {
783
- c .remainingPlannedCompactions .WithLabelValues (userID ).Set (float64 (remainingCompactions ))
784
- c .inProgressCompactions .WithLabelValues (userID ).Set (float64 (inProgressCompactions ))
785
- if c .oldestPartitionGroupOffset != nil {
786
- if oldestPartitionGroup != nil {
787
- c .oldestPartitionGroupOffset .WithLabelValues (userID ).Set (float64 (time .Now ().Unix () - oldestPartitionGroup .CreationTime ))
788
- level .Debug (userLogger ).Log ("msg" , "partition group info with oldest creation time" , "partitioned_group_id" , oldestPartitionGroup .PartitionedGroupID , "creation_time" , oldestPartitionGroup .CreationTime )
789
- } else {
790
- c .oldestPartitionGroupOffset .WithLabelValues (userID ).Set (0 )
791
- }
792
- }
793
- }()
794
789
for partitionedGroupInfo , extraInfo := range existentPartitionedGroupInfo {
795
790
partitionedGroupInfoFile := extraInfo .path
796
791
797
- remainingCompactions += extraInfo .status .PendingPartitions
798
- inProgressCompactions += extraInfo .status .InProgressPartitions
799
- if oldestPartitionGroup == nil || partitionedGroupInfo .CreationTime < oldestPartitionGroup .CreationTime {
800
- oldestPartitionGroup = partitionedGroupInfo
801
- }
802
792
if extraInfo .status .CanDelete {
803
793
if extraInfo .status .IsCompleted {
804
794
// Try to remove all blocks included in partitioned group info
@@ -829,6 +819,72 @@ func (c *BlocksCleaner) cleanPartitionedGroupInfo(ctx context.Context, userBucke
829
819
}
830
820
}
831
821
822
+ func (c * BlocksCleaner ) emitUserMetrics (ctx context.Context , userLogger log.Logger , userBucket objstore.InstrumentedBucket , userID string ) {
823
+ err , existentPartitionedGroupInfo := c .iterPartitionGroups (ctx , userBucket , userLogger )
824
+ if err != nil {
825
+ level .Warn (userLogger ).Log ("msg" , "error return when going through partitioned group directory" , "err" , err )
826
+ }
827
+
828
+ remainingCompactions := 0
829
+ inProgressCompactions := 0
830
+ completedCompaction := 0
831
+ var oldestPartitionGroup * PartitionedGroupInfo
832
+ defer func () {
833
+ c .remainingPlannedCompactions .WithLabelValues (userID ).Set (float64 (remainingCompactions ))
834
+ c .inProgressCompactions .WithLabelValues (userID ).Set (float64 (inProgressCompactions ))
835
+ if c .oldestPartitionGroupOffset != nil {
836
+ if oldestPartitionGroup != nil {
837
+ c .oldestPartitionGroupOffset .WithLabelValues (userID ).Set (float64 (time .Now ().Unix () - oldestPartitionGroup .CreationTime ))
838
+ level .Debug (userLogger ).Log ("msg" , "partition group info with oldest creation time" , "partitioned_group_id" , oldestPartitionGroup .PartitionedGroupID , "creation_time" , oldestPartitionGroup .CreationTime )
839
+ } else {
840
+ c .oldestPartitionGroupOffset .WithLabelValues (userID ).Set (0 )
841
+ }
842
+ }
843
+ }()
844
+ for partitionedGroupInfo , extraInfo := range existentPartitionedGroupInfo {
845
+ remainingCompactions += extraInfo .status .PendingPartitions
846
+ inProgressCompactions += extraInfo .status .InProgressPartitions
847
+ if oldestPartitionGroup == nil || partitionedGroupInfo .CreationTime < oldestPartitionGroup .CreationTime {
848
+ oldestPartitionGroup = partitionedGroupInfo
849
+ }
850
+ if extraInfo .status .IsCompleted {
851
+ completedCompaction += len (partitionedGroupInfo .Partitions )
852
+ }
853
+ }
854
+ }
855
+
856
+ func (c * BlocksCleaner ) iterPartitionGroups (ctx context.Context , userBucket objstore.InstrumentedBucket , userLogger log.Logger ) (error , map [* PartitionedGroupInfo ]struct {
857
+ path string
858
+ status PartitionedGroupStatus
859
+ }) {
860
+ existentPartitionedGroupInfo := make (map [* PartitionedGroupInfo ]struct {
861
+ path string
862
+ status PartitionedGroupStatus
863
+ })
864
+ err := userBucket .Iter (ctx , PartitionedGroupDirectory , func (file string ) error {
865
+ if strings .Contains (file , PartitionVisitMarkerDirectory ) {
866
+ return nil
867
+ }
868
+ partitionedGroupInfo , err := ReadPartitionedGroupInfoFile (ctx , userBucket , userLogger , file )
869
+ if err != nil {
870
+ level .Warn (userLogger ).Log ("msg" , "failed to read partitioned group info" , "partitioned_group_info" , file )
871
+ return nil
872
+ }
873
+
874
+ status := partitionedGroupInfo .getPartitionedGroupStatus (ctx , userBucket , c .compactionVisitMarkerTimeout , userLogger )
875
+ level .Debug (userLogger ).Log ("msg" , "got partitioned group status" , "partitioned_group_status" , status .String ())
876
+ existentPartitionedGroupInfo [partitionedGroupInfo ] = struct {
877
+ path string
878
+ status PartitionedGroupStatus
879
+ }{
880
+ path : file ,
881
+ status : status ,
882
+ }
883
+ return nil
884
+ })
885
+ return err , existentPartitionedGroupInfo
886
+ }
887
+
832
888
// cleanUserPartialBlocks delete partial blocks which are safe to be deleted. The provided partials map
833
889
// and index are updated accordingly.
834
890
func (c * BlocksCleaner ) cleanUserPartialBlocks (ctx context.Context , userID string , partials map [ulid.ULID ]error , idx * bucketindex.Index , userBucket objstore.InstrumentedBucket , userLogger log.Logger ) {
0 commit comments