diff --git a/cachetype_string.go b/cachetype_string.go new file mode 100644 index 00000000..7a93c371 --- /dev/null +++ b/cachetype_string.go @@ -0,0 +1,26 @@ +// Code generated by "stringer -type=CacheType"; DO NOT EDIT. + +package galaxycache + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[MainCache-1] + _ = x[HotCache-2] + _ = x[CandidateCache-3] +} + +const _CacheType_name = "MainCacheHotCacheCandidateCache" + +var _CacheType_index = [...]uint8{0, 9, 17, 31} + +func (i CacheType) String() string { + i -= 1 + if i < 0 || i >= CacheType(len(_CacheType_index)-1) { + return "CacheType(" + strconv.FormatInt(int64(i+1), 10) + ")" + } + return _CacheType_name[_CacheType_index[i]:_CacheType_index[i+1]] +} diff --git a/galaxycache.go b/galaxycache.go index e2186eb8..3211a453 100644 --- a/galaxycache.go +++ b/galaxycache.go @@ -127,13 +127,16 @@ func (universe *Universe) NewGalaxy(name string, cacheBytes int64, getter Backen peerPicker: universe.peerPicker, cacheBytes: cacheBytes, mainCache: cache{ - lru: lru.New(0), + ctype: MainCache, + lru: lru.New(0), }, hotCache: cache{ - lru: lru.New(0), + ctype: HotCache, + lru: lru.New(0), }, candidateCache: cache{ - lru: lru.New(gOpts.maxCandidates), + ctype: CandidateCache, + lru: lru.New(gOpts.maxCandidates), }, hcStatsWithTime: HCStatsWithTime{ hcs: &promoter.HCStats{ @@ -498,7 +501,7 @@ func (g *Galaxy) load(ctx context.Context, key string, dest Codec) (value *valWi stats.Record(ctx, MCoalescedBackendLoads.M(1)) destPopulated = true // only one caller of load gets this return value value = newValWithStat(data, nil) - g.populateCache(key, value, &g.mainCache) + g.populateCache(ctx, key, value, &g.mainCache) return &valWithLevel{value, hitBackend, authoritative, peerErr, err}, nil }) if err == nil { @@ -537,7 +540,7 @@ func (g *Galaxy) getFromPeer(ctx context.Context, peer RemoteFetcher, key string } value := newValWithStat(data, kStats) if g.opts.promoter.ShouldPromote(key, value.data, stats) { - g.populateCache(key, value, &g.hotCache) + g.populateCache(ctx, key, value, &g.hotCache) } return value, nil } @@ -558,11 +561,16 @@ func (g *Galaxy) lookupCache(key string) (*valWithStat, hitLevel) { return vi.(*valWithStat), hitHotcache } -func (g *Galaxy) populateCache(key string, value *valWithStat, cache *cache) { +func (g *Galaxy) populateCache(ctx context.Context, key string, value *valWithStat, cache *cache) { if g.cacheBytes <= 0 { return } cache.add(key, value) + // Record the size of this cache after we've finished evicting any necessary values. + defer func() { + stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(CacheLevelKey, cache.ctype.String())}, + MCacheSize.M(cache.bytes()), MCacheEntries.M(cache.items())) + }() // Evict items from cache(s) if necessary. for { @@ -619,6 +627,7 @@ func (g *Galaxy) CacheStats(which CacheType) CacheStats { // and counts the size of all keys and values. Candidate cache only // utilizes the lru.Cache and mutex, not the included stats. type cache struct { + ctype CacheType mu sync.Mutex nbytes int64 // of all keys and values lru *lru.Cache @@ -737,3 +746,5 @@ type CacheStats struct { Hits int64 Evictions int64 } + +//go:generate stringer -type=CacheType diff --git a/observability.go b/observability.go index c89f8fe1..933f288f 100644 --- a/observability.go +++ b/observability.go @@ -52,6 +52,9 @@ var ( MValueLength = stats.Int64("galaxycache/value_length", "The length of values", stats.UnitBytes) MRoundtripLatencyMilliseconds = stats.Float64("galaxycache/roundtrip_latency", "Roundtrip latency in milliseconds", stats.UnitMilliseconds) + + MCacheSize = stats.Int64("galaxycache/cache_bytes", "The number of bytes used for storing Keys and Values in the cache", stats.UnitBytes) + MCacheEntries = stats.Int64("galaxycache/cache_entries", "The number of entries in the cache", stats.UnitDimensionless) ) // GalaxyKey tags the name of the galaxy @@ -80,6 +83,8 @@ var AllViews = []*view.View{ {Measure: MValueLength, TagKeys: []tag.Key{GalaxyKey}, Aggregation: defaultBytesDistribution}, {Measure: MRoundtripLatencyMilliseconds, TagKeys: []tag.Key{GalaxyKey}, Aggregation: defaultMillisecondsDistribution}, + {Measure: MCacheSize, TagKeys: []tag.Key{GalaxyKey, CacheLevelKey}, Aggregation: view.LastValue()}, + {Measure: MCacheEntries, TagKeys: []tag.Key{GalaxyKey, CacheLevelKey}, Aggregation: view.LastValue()}, } func sinceInMilliseconds(start time.Time) float64 {