feat(s3/lifecycle): metadata_only_total Prometheus counter (#9399)

Operator-visible signal for the metadata-only delete path landed in
PR 9390. Increment seaweedfs_s3_lifecycle_metadata_only_total{bucket,
rule_hash} after each successful unversioned or noncurrent / expired-
marker delete that took the skip-chunk path. Suspended-versioning
null delete is intentionally not counted: that path's nil err can
mean "deleted" or "NotFound", so a count there would over-report.
rule_hash is hex-encoded for label safety; nil bytes collapse to
"". DeleteBucketMetrics tears the new series down alongside the
existing lifecycle counters when a bucket is removed.
This commit is contained in:
Chris Lu authored and GitHub committed 2026-05-09 20:02:26 -07:00
1 parent c0cf1417f1
commit af2a359e45
3 files changed
+82

No files matched your search

+15
View File
@@ -3,6 +3,7 @@ package s3api
import (
"bytes"
"context"
"encoding/hex"
"errors"
"path"
"strings"
@@ -12,6 +13,7 @@ import (
"github.com/seaweedfs/seaweedfs/weed/pb/s3_lifecycle_pb"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3lifecycle"
stats_collect "github.com/seaweedfs/seaweedfs/weed/stats"
)
// LifecycleDelete executes one (rule, action) verdict: re-fetch, identity
@@ -99,6 +101,7 @@ func (s3a *S3ApiServer) lifecycleDispatch(ctx context.Context, req *s3_lifecycle
}
return retryLater("TRANSPORT_ERROR: deleteUnversioned: " + err.Error()), nil
}
recordMetadataOnlyIf(metadataOnly, req)
return done(), nil
}
@@ -141,6 +144,7 @@ func (s3a *S3ApiServer) lifecycleDispatch(ctx context.Context, req *s3_lifecycle
}
return retryLater("TRANSPORT_ERROR: deleteSpecificVersion: " + err.Error()), nil
}
recordMetadataOnlyIf(metadataOnly, req)
return done(), nil
case s3_lifecycle_pb.ActionKind_ABORT_MPU:
@@ -343,6 +347,17 @@ func identityMatches(live, want *s3_lifecycle_pb.EntryIdentity) bool {
return bytes.Equal(live.ExtendedHash, want.ExtendedHash)
}
// recordMetadataOnlyIf bumps the metadata-only counter when on=true.
// Skipped when off so callers don't need a guard at every call site.
// rule_hash is hex-encoded so operators can group by rule when
// debugging; nil rule_hash collapses to the empty string.
func recordMetadataOnlyIf(on bool, req *s3_lifecycle_pb.LifecycleDeleteRequest) {
if !on || req == nil {
return
}
stats_collect.S3LifecycleMetadataOnlyCounter.WithLabelValues(req.Bucket, hex.EncodeToString(req.RuleHash)).Inc()
}
func done() *s3_lifecycle_pb.LifecycleDeleteResponse {
return &s3_lifecycle_pb.LifecycleDeleteResponse{Outcome: s3_lifecycle_pb.LifecycleDeleteOutcome_DONE}
}