Skip to content
This repository was archived by the owner on Apr 2, 2024. It is now read-only.

Commit 75daab3

Browse files
Rename and add perf metrics to clockcache.
Signed-off-by: Harkishen-Singh <[email protected]> This commit renames cache metrics as per the new design and adds performance metrics to clockcache. Following metrics are implemented/updated: promscale_cache_enabled{type="label", name=”cache-name”} promscale_cache_capacity_bytes{type="label", name=”cache-name”} promscale_cache_capacity_elements{type="label", name=”cache-name”} promscale_cache_elements{type="label", name=”cache-name”} promscale_cache_evictions_total{type="label", name=”cache-name”} promscale_cache_queries_hits_total{type="label", name=”cache-name”} promscale_cache_queries_total{type="label", name=”cache-name”} promscale_cache_queries_latency_bucket{type="label", name=”cache-name”} promscale_cache_queries_latency_sum{type="label", name=”cache-name”} promscale_cache_queries_latency_count{type="label", name=”cache-name”} However, statement_cache has promscale_cache_enabled, promscale_statement_cache_per_connection_capacity and promscale_cache_elements_histogram since it is not a clockcache.
1 parent ead44af commit 75daab3

File tree

9 files changed

+186
-114
lines changed

9 files changed

+186
-114
lines changed

pkg/api/metrics.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,7 @@ func createMetrics() *Metrics {
9494
IngestedSamples: prometheus.NewCounter(
9595
prometheus.CounterOpts{
9696
Namespace: util.PromNamespace,
97-
Subsystem: "ingest",
98-
Name: "ingested_total",
97+
Name: "ingested_samples_total",
9998
Help: "Total number of processed sample/metadata sent to remote storage.",
10099
},
101100
),

pkg/clockcache/cache.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ import (
99
"reflect"
1010
"sync"
1111
"sync/atomic"
12+
"time"
1213
)
1314

1415
// CLOCK based approximate LRU storing designed for concurrent usage.
1516
// Gets only require a read lock, while Inserts take at least one write lock.
1617
type Cache struct {
18+
metrics *perfMetrics
1719
// guards elements and all fields except for `used` in Element, must have at
1820
// least a read-lock to access, and a write-lock to insert/update/delete.
1921
elementsLock sync.RWMutex
@@ -48,11 +50,16 @@ type element struct {
4850

4951
func WithMax(max uint64) *Cache {
5052
return &Cache{
53+
metrics: &perfMetrics{}, // Unregistered metrics.
5154
elements: make(map[interface{}]*element, max),
5255
storage: make([]element, 0, max),
5356
}
5457
}
5558

59+
func (self *Cache) applyPerfMetric(m *perfMetrics) {
60+
self.metrics = m
61+
}
62+
5663
// Insert a key/value mapping into the cache if the key is not already present,
5764
// The sizeBytes represents the in-memory size of the key and value (used to estimate cache size).
5865
// returns the canonical version of the value
@@ -194,6 +201,9 @@ func (self *Cache) evict() (insertPtr *element) {
194201
// keys will be the keys whose values are present, while the remainder
195202
// will be the keys not present in the cache
196203
func (self *Cache) GetValues(keys []interface{}, valuesOut []interface{}) (numFound int) {
204+
start := time.Now()
205+
defer func() { self.metrics.Observe("Get_Values", time.Since(start)) }()
206+
197207
if len(keys) != len(valuesOut) {
198208
panic(fmt.Sprintf("keys and values are not the same len. %d keys, %d values", len(keys), len(valuesOut)))
199209
}
@@ -222,12 +232,16 @@ func (self *Cache) GetValues(keys []interface{}, valuesOut []interface{}) (numFo
222232
}
223233

224234
func (self *Cache) Get(key interface{}) (interface{}, bool) {
235+
start := time.Now()
236+
defer func() { self.metrics.Observe("Get", time.Since(start)) }()
237+
225238
self.elementsLock.RLock()
226239
defer self.elementsLock.RUnlock()
227240
return self.get(key)
228241
}
229242

230243
func (self *Cache) get(key interface{}) (interface{}, bool) {
244+
self.metrics.Inc(self.metrics.queriesTotal)
231245
elem, present := self.elements[key]
232246
if !present {
233247
return 0, false
@@ -241,6 +255,7 @@ func (self *Cache) get(key interface{}) (interface{}, bool) {
241255
if atomic.LoadUint32(&elem.used) == 0 {
242256
atomic.StoreUint32(&elem.used, 1)
243257
}
258+
self.metrics.Inc(self.metrics.hitsTotal)
244259

245260
return elem.value, true
246261
}

pkg/clockcache/metrics.go

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package clockcache
2+
3+
import (
4+
"time"
5+
6+
"github.com/prometheus/client_golang/prometheus"
7+
"github.com/timescale/promscale/pkg/util"
8+
)
9+
10+
type MetricOptions struct {
11+
Name, Module string
12+
}
13+
14+
// WithMetrics attaches the default cache metrics like _enabled, _capacity, _size, _elements, _evictions_total and
15+
// the perf metrics like _query_hits, _queries, _query_latency by function.
16+
// The module must be either 'metric' or 'trace'.
17+
func WithMetrics(cacheName, module string, max uint64) *Cache {
18+
cache := WithMax(max)
19+
RegisterBasicMetrics(cacheName, module, cache)
20+
21+
perf := new(perfMetrics)
22+
perf.createAndRegister(cacheName, module)
23+
cache.applyPerfMetric(perf)
24+
return cache
25+
}
26+
27+
type perfMetrics struct {
28+
isApplied bool
29+
hitsTotal prometheus.Counter
30+
queriesTotal prometheus.Counter
31+
queriesLatency *prometheus.HistogramVec
32+
}
33+
34+
func (pm *perfMetrics) createAndRegister(name, module string) {
35+
pm.isApplied = true
36+
pm.hitsTotal = prometheus.NewCounter(
37+
prometheus.CounterOpts{
38+
Namespace: "promscale",
39+
Subsystem: "cache",
40+
Name: "query_hits_total",
41+
Help: "Total query hits in clockcache.",
42+
ConstLabels: map[string]string{"type": module, "name": name},
43+
},
44+
)
45+
pm.queriesTotal = prometheus.NewCounter(
46+
prometheus.CounterOpts{
47+
Namespace: "promscale",
48+
Subsystem: "cache",
49+
Name: "queries_total",
50+
Help: "Total query requests to the clockcache.",
51+
ConstLabels: map[string]string{"type": module, "name": name},
52+
},
53+
)
54+
pm.queriesLatency = prometheus.NewHistogramVec(
55+
prometheus.HistogramOpts{
56+
Namespace: "promscale",
57+
Subsystem: "cache",
58+
Name: "query_latency_microseconds",
59+
Help: "Query latency for the clockcache.",
60+
ConstLabels: map[string]string{"type": module, "name": name},
61+
Buckets: prometheus.LinearBuckets(1, 500, 20),
62+
}, []string{"method"},
63+
)
64+
prometheus.MustRegister(pm.hitsTotal, pm.queriesTotal, pm.queriesLatency)
65+
}
66+
67+
func (pm *perfMetrics) Inc(c prometheus.Counter) {
68+
if pm.isApplied {
69+
c.Inc()
70+
}
71+
}
72+
73+
func (pm *perfMetrics) Observe(method string, d time.Duration) {
74+
if pm.isApplied {
75+
pm.queriesLatency.WithLabelValues(method).Observe(float64(d.Microseconds()))
76+
}
77+
}
78+
79+
// RegisterBasicMetrics registers and creates basic metrics for cache like:
80+
// 1. promscale_cache_enabled
81+
// 2. promscale_cache_elements
82+
// 3. promscale_cache_size
83+
// 4. promscale_cache_capacity
84+
// 5. promscale_cache_evictions_total
85+
// Note: the moduleType refers to which module the cache belongs. Valid options: ["metric", "trace"].
86+
func RegisterBasicMetrics(cacheName, moduleType string, c *Cache) {
87+
if !(moduleType == "metric" || moduleType == "trace") {
88+
panic("moduleType can only be either 'metric' or 'trace'")
89+
}
90+
enabled := prometheus.NewGauge(
91+
prometheus.GaugeOpts{
92+
Namespace: util.PromNamespace,
93+
Subsystem: "cache",
94+
Name: "enabled",
95+
Help: "Cache is enabled or not.",
96+
ConstLabels: map[string]string{ // type => ["trace" or "metric"] and name => name of the cache i.e., metric cache, series cache, schema cache, etc.
97+
"type": "trace",
98+
"name": cacheName,
99+
},
100+
},
101+
)
102+
enabled.Set(1)
103+
count := prometheus.NewGaugeFunc(
104+
prometheus.GaugeOpts{
105+
Namespace: util.PromNamespace,
106+
Subsystem: "cache",
107+
Name: "elements",
108+
Help: "Number of elements in cache in terms of elements count.",
109+
ConstLabels: map[string]string{"type": "trace", "name": cacheName},
110+
}, func() float64 {
111+
return float64(c.Len())
112+
},
113+
)
114+
size := prometheus.NewGaugeFunc(
115+
prometheus.GaugeOpts{
116+
Namespace: util.PromNamespace,
117+
Subsystem: "cache",
118+
Name: "capacity_bytes",
119+
Help: "Cache size in bytes.",
120+
ConstLabels: map[string]string{"type": "trace", "name": cacheName},
121+
}, func() float64 {
122+
return float64(c.SizeBytes())
123+
},
124+
)
125+
capacity := prometheus.NewGaugeFunc(
126+
prometheus.GaugeOpts{
127+
Namespace: util.PromNamespace,
128+
Subsystem: "cache",
129+
Name: "capacity_elements",
130+
Help: "Total cache capacity in terms of elements count.",
131+
ConstLabels: map[string]string{"type": "trace", "name": cacheName},
132+
}, func() float64 {
133+
return float64(c.Cap())
134+
},
135+
)
136+
evictions := prometheus.NewCounterFunc(
137+
prometheus.CounterOpts{
138+
Namespace: util.PromNamespace,
139+
Subsystem: "cache",
140+
Name: "evictions_total",
141+
Help: "Total evictions in a clockcache.",
142+
ConstLabels: map[string]string{"type": "trace", "name": cacheName},
143+
}, func() float64 {
144+
return float64(c.Evictions())
145+
},
146+
)
147+
prometheus.MustRegister(enabled, count, size, capacity, evictions)
148+
}

pkg/pgclient/metrics.go

Lines changed: 15 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -12,121 +12,29 @@ import (
1212
)
1313

1414
var (
15-
cachedMetricNames prometheus.GaugeFunc
16-
cachedLabels prometheus.GaugeFunc
17-
metricNamesCacheCap prometheus.GaugeFunc
18-
metricNamesCacheEvictions prometheus.CounterFunc
19-
labelsCacheCap prometheus.GaugeFunc
20-
labelsCacheEvictions prometheus.CounterFunc
21-
seriesCacheCap prometheus.GaugeFunc
22-
seriesCacheLen prometheus.GaugeFunc
23-
seriesCacheEvictions prometheus.CounterFunc
24-
statementCacheLen prometheus.Histogram
25-
statementCacheCap = prometheus.NewGauge(
15+
statementCacheLen prometheus.Histogram
16+
statementCacheCap = prometheus.NewGauge(
2617
prometheus.GaugeOpts{
2718
Namespace: util.PromNamespace,
28-
Name: "statement_cache_per_connection_capacity",
19+
Subsystem: "cache",
20+
Name: "statement_per_connection_capacity",
2921
Help: "Maximum number of statements in connection pool's statement cache",
3022
},
3123
)
3224
statementCacheEnabled = prometheus.NewGauge(
3325
prometheus.GaugeOpts{
34-
Namespace: util.PromNamespace,
35-
Name: "statement_cache_enabled",
36-
Help: "Is the database connection pool's statement cache enabled",
26+
Namespace: util.PromNamespace,
27+
Subsystem: "cache",
28+
Name: "enabled",
29+
Help: "Cache is enabled or not.",
30+
ConstLabels: map[string]string{"type": "metric", "name": "statement_cache"},
3731
},
3832
)
3933
)
4034

4135
func InitClientMetrics(client *Client) {
42-
// Only initialize once.
43-
if cachedMetricNames != nil {
44-
return
45-
}
46-
47-
cachedMetricNames = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
48-
Namespace: util.PromNamespace,
49-
Name: "metric_name_cache_elements_stored",
50-
Help: "Total number of metric names in the metric name cache.",
51-
}, func() float64 {
52-
return float64(client.NumCachedMetricNames())
53-
})
54-
55-
metricNamesCacheCap = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
56-
Namespace: util.PromNamespace,
57-
Name: "metric_name_cache_capacity",
58-
Help: "Maximum number of elements in the metric names cache.",
59-
}, func() float64 {
60-
return float64(client.MetricNamesCacheCapacity())
61-
})
62-
63-
metricNamesCacheEvictions = prometheus.NewCounterFunc(prometheus.CounterOpts{
64-
Namespace: util.PromNamespace,
65-
Name: "metric_name_cache_evictions_total",
66-
Help: "Evictions in the metric names cache.",
67-
}, func() float64 {
68-
return float64(client.metricCache.Evictions())
69-
})
70-
71-
cachedLabels = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
72-
Namespace: util.PromNamespace,
73-
Name: "label_cache_elements_stored",
74-
Help: "Total number of label-id to label mappings cache.",
75-
}, func() float64 {
76-
return float64(client.NumCachedLabels())
77-
})
78-
79-
labelsCacheCap = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
80-
Namespace: util.PromNamespace,
81-
Name: "label_cache_capacity",
82-
Help: "Total number of label-id to label mappings cache.",
83-
}, func() float64 {
84-
return float64(client.LabelsCacheCapacity())
85-
})
86-
87-
labelsCacheEvictions = prometheus.NewCounterFunc(prometheus.CounterOpts{
88-
Namespace: util.PromNamespace,
89-
Name: "label_cache_evictions_total",
90-
Help: "Total number of evictions in the label-id to label mappings cache.",
91-
}, func() float64 {
92-
return float64(client.labelsCache.Evictions())
93-
})
94-
95-
seriesCacheLen = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
96-
Namespace: util.PromNamespace,
97-
Name: "series_cache_elements_stored",
98-
Help: "Total number of series stored in cache",
99-
}, func() float64 {
100-
return float64(client.seriesCache.Len())
101-
})
102-
103-
seriesCacheCap = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
104-
Namespace: util.PromNamespace,
105-
Name: "series_cache_capacity",
106-
Help: "Total size of series cache.",
107-
}, func() float64 {
108-
return float64(client.seriesCache.Cap())
109-
})
110-
111-
seriesCacheEvictions = prometheus.NewCounterFunc(prometheus.CounterOpts{
112-
Namespace: util.PromNamespace,
113-
Name: "series_cache_evictions_total",
114-
Help: "Total number of series cache evictions.",
115-
}, func() float64 {
116-
return float64(client.seriesCache.Evictions())
117-
})
118-
11936
statementCacheLen = createStatementCacheLengthHistogramMetric(client)
12037
prometheus.MustRegister(
121-
cachedMetricNames,
122-
metricNamesCacheCap,
123-
cachedLabels,
124-
labelsCacheCap,
125-
seriesCacheLen,
126-
seriesCacheCap,
127-
seriesCacheEvictions,
128-
metricNamesCacheEvictions,
129-
labelsCacheEvictions,
13038
statementCacheEnabled,
13139
statementCacheCap,
13240
statementCacheLen,
@@ -154,10 +62,12 @@ func createStatementCacheLengthHistogramMetric(client *Client) prometheus.Histog
15462
histogramStartBucket := math.Pow(histogramBucketFactor, minFactor)
15563
return prometheus.NewHistogram(
15664
prometheus.HistogramOpts{
157-
Namespace: util.PromNamespace,
158-
Name: "statement_cache_elements_stored",
159-
Help: "Number of statements in connection pool's statement cache",
160-
Buckets: prometheus.ExponentialBuckets(histogramStartBucket, histogramBucketFactor, totalBuckets),
65+
Namespace: util.PromNamespace,
66+
Subsystem: "cache",
67+
Name: "elements_histogram",
68+
Help: "Number of elements in cache in terms of elements count.",
69+
Buckets: prometheus.ExponentialBuckets(histogramStartBucket, histogramBucketFactor, totalBuckets),
70+
ConstLabels: map[string]string{"type": "metric", "name": "statement_cache"},
16171
},
16272
)
16373
}

pkg/pgmodel/cache/cache.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ type MetricNameCache struct {
6262
}
6363

6464
func NewMetricCache(config Config) *MetricNameCache {
65-
return &MetricNameCache{Metrics: clockcache.WithMax(config.MetricsCacheSize)}
65+
return &MetricNameCache{Metrics: clockcache.WithMetrics("metric", "metric", config.MetricsCacheSize)}
6666
}
6767

6868
// Get fetches the table name for specified metric.
@@ -113,5 +113,5 @@ func (m *MetricNameCache) Evictions() uint64 {
113113
}
114114

115115
func NewLabelsCache(config Config) LabelsCache {
116-
return clockcache.WithMax(config.LabelsCacheSize)
116+
return clockcache.WithMetrics("label", "metric", config.LabelsCacheSize)
117117
}

pkg/pgmodel/cache/exemplar_key_cache.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ type ExemplarLabelsPosCache struct {
2929
// map[LabelName]LabelPosition. This means that the cache stores positions of each label's value per metric basis,
3030
// which is meant to preserve and reuse _prom_catalog.exemplar_label_position table's 'pos' column.
3131
func NewExemplarLabelsPosCache(config Config) PositionCache {
32-
return &ExemplarLabelsPosCache{cache: clockcache.WithMax(config.ExemplarKeyPosCacheSize)}
32+
return &ExemplarLabelsPosCache{cache: clockcache.WithMetrics("exemplar_labels", "metric", config.ExemplarKeyPosCacheSize)}
3333
}
3434

3535
func (pos *ExemplarLabelsPosCache) GetLabelPositions(metric string) (map[string]int, bool) {

0 commit comments

Comments
 (0)