Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions cache/disk/census.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func newCensusRecorder() *censusRecorder {

evictedBytesByAge: prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "bazel_remote_disk_cache_evicted_bytes_by_age",
Help: "Bytes evicted from the disk cache, bucketed by age at eviction. age_kind is last_read (time since the entry was last read: evicted still-live bytes are the harm signal) or created (time since the entry was written: write-once bytes dying young are the garbage signal).",
Help: "Bytes evicted from the disk cache, bucketed by age at eviction. age_kind is last_read (time since the entry was last read: evicted still-live bytes are the harm signal), never_read (bucketed by created age, never-read entries only: young bands mean writes evicted before their first read), or created (time since the entry was written, every eviction: the superset of the other two).",
}, []string{"age_kind", "age_bucket", "tool"}),

accessIntervalByAge: prometheus.NewCounterVec(prometheus.CounterOpts{
Expand Down Expand Up @@ -271,13 +271,18 @@ func (r *censusRecorder) OnEvict(key string, value lruItem) {

sz := float64(value.sizeOnDisk)
// Never-read entries have no last read: they are counted in the
// never-read counter and the created-age buckets only, so the
// last_read series stays a pure harm signal (bytes someone actually
// used, evicted anyway). This also gives thrash alerts built-in
// restart tolerance: boot-scanned entries look never-read until first
// touched, so a roll cannot fabricate still-live evictions.
// never-read counter, a never_read age series (bucketed by CREATED
// age — a never-read entry evicted minutes after writing means the
// cache could not hold a write until its first read, and burying it
// in the aggregate created bands made that failure look healthy),
// and the created-age buckets. The last_read series stays a pure
// harm signal (bytes someone actually used, evicted anyway). This
// also gives thrash alerts built-in restart tolerance: boot-scanned
// entries look never-read until first touched, so a roll cannot
// fabricate still-live evictions.
if neverRead {
r.evictedNeverReadBytes.WithLabelValues(tool).Add(sz)
r.evictedBytesByAge.WithLabelValues("never_read", censusBucketLabels[createdIdx], tool).Add(sz)
} else {
r.evictedBytesByAge.WithLabelValues("last_read", censusBucketLabels[lastReadIdx], tool).Add(sz)
}
Expand Down
8 changes: 8 additions & 0 deletions cache/disk/census_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"testing"

"github.com/buchgr/bazel-remote/v2/cache"

"github.com/prometheus/client_golang/prometheus/testutil"
)

func TestCensusBucketIdx(t *testing.T) {
Expand Down Expand Up @@ -153,6 +155,12 @@ func TestCensusAccounting(t *testing.T) {
if rows3[0].EvictedNeverReadBytes != 200 {
t.Errorf("EvictedNeverReadBytes = %d, want 200", rows3[0].EvictedNeverReadBytes)
}
// The never_read Prometheus series buckets by CREATED age (14h -> 24h
// band): a young never-read eviction must be visible as such, not
// buried in the aggregate created bands.
if got := testutil.ToFloat64(rec.evictedBytesByAge.WithLabelValues("never_read", "24h", "go")); got != 200 {
t.Errorf("never_read 24h band = %v, want 200", got)
}
// B's last read is its creation stamp, 14h before eviction: not live.
if rows3[0].EvictedLiveBytes != 0 {
t.Errorf("EvictedLiveBytes = %d, want 0", rows3[0].EvictedLiveBytes)
Expand Down
Loading