Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple caches, one metric #244

Open
twolf-adc opened this issue Apr 8, 2024 · 2 comments
Open

Multiple caches, one metric #244

twolf-adc opened this issue Apr 8, 2024 · 2 comments

Comments

@twolf-adc
Copy link

twolf-adc commented Apr 8, 2024

I currently have multiple caches, that I don't want to join as one. However, in my Prometheus metrics I want all of these caches to use the same metric aka namespace, where each cache has its uniquely identifying label. This way I can easily query Prometheus, showing me the metric over all caches or filtered to (via the label) the one cache I want.

What I tried
Attempting to call cachemetrics.NewPrometheus() multiple times with the same namespace but setting some label differently. This results in a runtime panic (panic: duplicate metrics collector registration attempted).

Other than that, I don't see a way to achieve this. Am I missing something, any suggestion?

Platforms:

alpine Linux

Versions:

v4.1.5

If this is not possible currently, is this a feature that you'd be willing to accept as a contribution from me?

@semihbkgr
Copy link
Contributor

If you use two different type of storage, they should uniquely identified by the store label.

# HELP cache_collector This represent the number of items in cache
# TYPE cache_collector gauge
cache_collector{metric="delete_error",service="cache-app",store="go-cache"} 0
cache_collector{metric="delete_error",service="cache-app",store="hazelcast"} 0
cache_collector{metric="delete_success",service="cache-app",store="go-cache"} 0
cache_collector{metric="delete_success",service="cache-app",store="hazelcast"} 0
cache_collector{metric="hit_count",service="cache-app",store="go-cache"} 0
cache_collector{metric="hit_count",service="cache-app",store="hazelcast"} 0
cache_collector{metric="invalidate_error",service="cache-app",store="go-cache"} 0
cache_collector{metric="invalidate_error",service="cache-app",store="hazelcast"} 0
cache_collector{metric="invalidate_success",service="cache-app",store="go-cache"} 0
cache_collector{metric="invalidate_success",service="cache-app",store="hazelcast"} 0
cache_collector{metric="miss_count",service="cache-app",store="go-cache"} 0
cache_collector{metric="miss_count",service="cache-app",store="hazelcast"} 0
cache_collector{metric="set_error",service="cache-app",store="go-cache"} 0
cache_collector{metric="set_error",service="cache-app",store="hazelcast"} 0
cache_collector{metric="set_success",service="cache-app",store="go-cache"} 0
cache_collector{metric="set_success",service="cache-app",store="hazelcast"} 0
# HELP promhttp_metric_handler_errors_total Total number of internal errors encountered by the promhttp metric handler.
# TYPE promhttp_metric_handler_errors_total counter
promhttp_metric_handler_errors_total{cause="encoding"} 0
promhttp_metric_handler_errors_total{cause="gathering"} 0

If you use the same type of storage, it seems that the API doesn't provide direct support. However, there's a workaround you can use.

You can create a storage wrapper type to customize the store type modifying GetType function , so that the store value in the labels will be differentiated.

type StoreInterfaceWrapper struct {
	store.StoreInterface
	t string
}

func (c *StoreInterfaceWrapper) GetType() string {
	return fmt.Sprintf("%s-%s", c.StoreInterface.GetType(), c.t)
}
gocacheClientOne := gocache.New(5*time.Minute, 10*time.Minute)
gocacheStoreOne := gocache_store.NewGoCache(gocacheClientOne)
cacheManagerOne := cache.New[[]byte](&StoreInterfaceWrapper{StoreInterface: gocacheStoreOne, t: "one"})

gocacheClientTwo := gocache.New(5*time.Minute, 10*time.Minute)
gocacheStoreTwo := gocache_store.NewGoCache(gocacheClientTwo)
cacheManagerTwo := cache.New[[]byte](&StoreInterfaceWrapper{StoreInterface: gocacheStoreTwo, t: "two"})

reg := prometheus.NewRegistry()
p := metrics.NewPrometheus("cache-app", metrics.WithRegisterer(reg), metrics.WithNamespace("cache"))
go func() {
for {
	fmt.Println("sending metrics")
	p.RecordFromCodec(cacheManagerOne.GetCodec())
	p.RecordFromCodec(cacheManagerTwo.GetCodec())
	time.Sleep(time.Second * 5)
}
}()

http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg}))
# HELP cache_collector This represent the number of items in cache
# TYPE cache_collector gauge
cache_collector{metric="delete_error",service="cache-app",store="go-cache-one"} 0
cache_collector{metric="delete_error",service="cache-app",store="go-cache-two"} 0
cache_collector{metric="delete_success",service="cache-app",store="go-cache-one"} 0
cache_collector{metric="delete_success",service="cache-app",store="go-cache-two"} 0
cache_collector{metric="hit_count",service="cache-app",store="go-cache-one"} 0
cache_collector{metric="hit_count",service="cache-app",store="go-cache-two"} 0
cache_collector{metric="invalidate_error",service="cache-app",store="go-cache-one"} 0
cache_collector{metric="invalidate_error",service="cache-app",store="go-cache-two"} 0
cache_collector{metric="invalidate_success",service="cache-app",store="go-cache-one"} 0
cache_collector{metric="invalidate_success",service="cache-app",store="go-cache-two"} 0
cache_collector{metric="miss_count",service="cache-app",store="go-cache-one"} 0
cache_collector{metric="miss_count",service="cache-app",store="go-cache-two"} 0
cache_collector{metric="set_error",service="cache-app",store="go-cache-one"} 0
cache_collector{metric="set_error",service="cache-app",store="go-cache-two"} 0
cache_collector{metric="set_success",service="cache-app",store="go-cache-one"} 0
cache_collector{metric="set_success",service="cache-app",store="go-cache-two"} 0
# HELP promhttp_metric_handler_errors_total Total number of internal errors encountered by the promhttp metric handler.
# TYPE promhttp_metric_handler_errors_total counter
promhttp_metric_handler_errors_total{cause="encoding"} 0
promhttp_metric_handler_errors_total{cause="gathering"} 0

@semihbkgr
Copy link
Contributor

@eko I think it should be supported in the API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants