@@ -236,6 +236,15 @@ func (c *BlocksCleaner) loop(ctx context.Context) error {
236236 go func () {
237237 c .runDeleteUserCleanup (ctx , deleteChan )
238238 }()
239+ var metricsChan chan * cleanerJob
240+ if c .cfg .ShardingStrategy == util .ShardingStrategyShuffle &&
241+ c .cfg .CompactionStrategy == util .CompactionStrategyPartitioning {
242+ metricsChan = make (chan * cleanerJob )
243+ defer close (metricsChan )
244+ go func () {
245+ c .runEmitMetricsWorker (ctx , metricsChan )
246+ }()
247+ }
239248
240249 for {
241250 select {
@@ -269,6 +278,17 @@ func (c *BlocksCleaner) loop(ctx context.Context) error {
269278 c .enqueueJobFailed .WithLabelValues (deletedStatus ).Inc ()
270279 }
271280
281+ if metricsChan != nil {
282+ select {
283+ case metricsChan <- & cleanerJob {
284+ users : activeUsers ,
285+ timestamp : cleanJobTimestamp ,
286+ }:
287+ default :
288+ level .Warn (c .logger ).Log ("msg" , "unable to push metrics job to metricsChan" )
289+ }
290+ }
291+
272292 case <- ctx .Done ():
273293 return nil
274294 }
@@ -288,10 +308,25 @@ func (c *BlocksCleaner) checkRunError(runType string, err error) {
288308 }
289309}
290310
291- func (c * BlocksCleaner ) runActiveUserCleanup (ctx context.Context , jobChan chan * cleanerJob ) {
311+ func (c * BlocksCleaner ) runEmitMetricsWorker (ctx context.Context , jobChan <- chan * cleanerJob ) {
312+ for job := range jobChan {
313+ err := concurrency .ForEachUser (ctx , job .users , c .cfg .CleanupConcurrency , func (ctx context.Context , userID string ) error {
314+ userLogger := util_log .WithUserID (userID , c .logger )
315+ userBucket := bucket .NewUserBucketClient (userID , c .bucketClient , c .cfgProvider )
316+ c .emitUserMetrics (ctx , userLogger , userBucket , userID )
317+ return nil
318+ })
319+
320+ if err != nil {
321+ level .Error (c .logger ).Log ("msg" , "emit metrics failed" , "err" , err .Error ())
322+ }
323+ }
324+ }
325+
326+ func (c * BlocksCleaner ) runActiveUserCleanup (ctx context.Context , jobChan <- chan * cleanerJob ) {
292327 for job := range jobChan {
293328 if job .timestamp < time .Now ().Add (- c .cfg .CleanupInterval ).Unix () {
294- level .Warn (c .logger ).Log ("Active user cleaner job too old. Ignoring to get recent data" )
329+ level .Warn (c .logger ).Log ("msg" , " Active user cleaner job too old. Ignoring to get recent data" )
295330 continue
296331 }
297332 err := c .cleanUpActiveUsers (ctx , job .users , false )
@@ -726,59 +761,14 @@ func (c *BlocksCleaner) cleanUser(ctx context.Context, userLogger log.Logger, us
726761}
727762
728763func (c * BlocksCleaner ) cleanPartitionedGroupInfo (ctx context.Context , userBucket objstore.InstrumentedBucket , userLogger log.Logger , userID string ) {
729- existentPartitionedGroupInfo := make (map [* PartitionedGroupInfo ]struct {
730- path string
731- status PartitionedGroupStatus
732- })
733- err := userBucket .Iter (ctx , PartitionedGroupDirectory , func (file string ) error {
734- if strings .Contains (file , PartitionVisitMarkerDirectory ) {
735- return nil
736- }
737- partitionedGroupInfo , err := ReadPartitionedGroupInfoFile (ctx , userBucket , userLogger , file )
738- if err != nil {
739- level .Warn (userLogger ).Log ("msg" , "failed to read partitioned group info" , "partitioned_group_info" , file )
740- return nil
741- }
742-
743- status := partitionedGroupInfo .getPartitionedGroupStatus (ctx , userBucket , c .compactionVisitMarkerTimeout , userLogger )
744- level .Debug (userLogger ).Log ("msg" , "got partitioned group status" , "partitioned_group_status" , status .String ())
745- existentPartitionedGroupInfo [partitionedGroupInfo ] = struct {
746- path string
747- status PartitionedGroupStatus
748- }{
749- path : file ,
750- status : status ,
751- }
752- return nil
753- })
754-
764+ err , existentPartitionedGroupInfo := c .iterPartitionGroups (ctx , userBucket , userLogger )
755765 if err != nil {
756766 level .Warn (userLogger ).Log ("msg" , "error return when going through partitioned group directory" , "err" , err )
757767 }
758768
759- remainingCompactions := 0
760- inProgressCompactions := 0
761- var oldestPartitionGroup * PartitionedGroupInfo
762- defer func () {
763- c .remainingPlannedCompactions .WithLabelValues (userID ).Set (float64 (remainingCompactions ))
764- c .inProgressCompactions .WithLabelValues (userID ).Set (float64 (inProgressCompactions ))
765- if c .oldestPartitionGroupOffset != nil {
766- if oldestPartitionGroup != nil {
767- c .oldestPartitionGroupOffset .WithLabelValues (userID ).Set (float64 (time .Now ().Unix () - oldestPartitionGroup .CreationTime ))
768- level .Debug (userLogger ).Log ("msg" , "partition group info with oldest creation time" , "partitioned_group_id" , oldestPartitionGroup .PartitionedGroupID , "creation_time" , oldestPartitionGroup .CreationTime )
769- } else {
770- c .oldestPartitionGroupOffset .WithLabelValues (userID ).Set (0 )
771- }
772- }
773- }()
774769 for partitionedGroupInfo , extraInfo := range existentPartitionedGroupInfo {
775770 partitionedGroupInfoFile := extraInfo .path
776771
777- remainingCompactions += extraInfo .status .PendingPartitions
778- inProgressCompactions += extraInfo .status .InProgressPartitions
779- if oldestPartitionGroup == nil || partitionedGroupInfo .CreationTime < oldestPartitionGroup .CreationTime {
780- oldestPartitionGroup = partitionedGroupInfo
781- }
782772 if extraInfo .status .CanDelete {
783773 if extraInfo .status .IsCompleted {
784774 // Try to remove all blocks included in partitioned group info
@@ -809,6 +799,72 @@ func (c *BlocksCleaner) cleanPartitionedGroupInfo(ctx context.Context, userBucke
809799 }
810800}
811801
802+ func (c * BlocksCleaner ) emitUserMetrics (ctx context.Context , userLogger log.Logger , userBucket objstore.InstrumentedBucket , userID string ) {
803+ err , existentPartitionedGroupInfo := c .iterPartitionGroups (ctx , userBucket , userLogger )
804+ if err != nil {
805+ level .Warn (userLogger ).Log ("msg" , "error return when going through partitioned group directory" , "err" , err )
806+ }
807+
808+ remainingCompactions := 0
809+ inProgressCompactions := 0
810+ completedCompaction := 0
811+ var oldestPartitionGroup * PartitionedGroupInfo
812+ defer func () {
813+ c .remainingPlannedCompactions .WithLabelValues (userID ).Set (float64 (remainingCompactions ))
814+ c .inProgressCompactions .WithLabelValues (userID ).Set (float64 (inProgressCompactions ))
815+ if c .oldestPartitionGroupOffset != nil {
816+ if oldestPartitionGroup != nil {
817+ c .oldestPartitionGroupOffset .WithLabelValues (userID ).Set (float64 (time .Now ().Unix () - oldestPartitionGroup .CreationTime ))
818+ level .Debug (userLogger ).Log ("msg" , "partition group info with oldest creation time" , "partitioned_group_id" , oldestPartitionGroup .PartitionedGroupID , "creation_time" , oldestPartitionGroup .CreationTime )
819+ } else {
820+ c .oldestPartitionGroupOffset .WithLabelValues (userID ).Set (0 )
821+ }
822+ }
823+ }()
824+ for partitionedGroupInfo , extraInfo := range existentPartitionedGroupInfo {
825+ remainingCompactions += extraInfo .status .PendingPartitions
826+ inProgressCompactions += extraInfo .status .InProgressPartitions
827+ if oldestPartitionGroup == nil || partitionedGroupInfo .CreationTime < oldestPartitionGroup .CreationTime {
828+ oldestPartitionGroup = partitionedGroupInfo
829+ }
830+ if extraInfo .status .IsCompleted {
831+ completedCompaction += len (partitionedGroupInfo .Partitions )
832+ }
833+ }
834+ }
835+
836+ func (c * BlocksCleaner ) iterPartitionGroups (ctx context.Context , userBucket objstore.InstrumentedBucket , userLogger log.Logger ) (error , map [* PartitionedGroupInfo ]struct {
837+ path string
838+ status PartitionedGroupStatus
839+ }) {
840+ existentPartitionedGroupInfo := make (map [* PartitionedGroupInfo ]struct {
841+ path string
842+ status PartitionedGroupStatus
843+ })
844+ err := userBucket .Iter (ctx , PartitionedGroupDirectory , func (file string ) error {
845+ if strings .Contains (file , PartitionVisitMarkerDirectory ) {
846+ return nil
847+ }
848+ partitionedGroupInfo , err := ReadPartitionedGroupInfoFile (ctx , userBucket , userLogger , file )
849+ if err != nil {
850+ level .Warn (userLogger ).Log ("msg" , "failed to read partitioned group info" , "partitioned_group_info" , file )
851+ return nil
852+ }
853+
854+ status := partitionedGroupInfo .getPartitionedGroupStatus (ctx , userBucket , c .compactionVisitMarkerTimeout , userLogger )
855+ level .Debug (userLogger ).Log ("msg" , "got partitioned group status" , "partitioned_group_status" , status .String ())
856+ existentPartitionedGroupInfo [partitionedGroupInfo ] = struct {
857+ path string
858+ status PartitionedGroupStatus
859+ }{
860+ path : file ,
861+ status : status ,
862+ }
863+ return nil
864+ })
865+ return err , existentPartitionedGroupInfo
866+ }
867+
812868// cleanUserPartialBlocks delete partial blocks which are safe to be deleted. The provided partials map
813869// and index are updated accordingly.
814870func (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