Skip to content

Commit 5515d62

Browse files
committed
Add option collectEvictionWeightAsCounter to collect caffeine_cache_eviction_weight as an incremental counter
Signed-off-by: Jean Hominal <[email protected]>
1 parent 27cefa7 commit 5515d62

File tree

2 files changed

+126
-22
lines changed

2 files changed

+126
-22
lines changed

prometheus-metrics-instrumentation-caffeine/src/main/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollector.java

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,30 @@ public class CacheMetricsCollector implements MultiCollector {
8484
METRIC_NAME_CACHE_LOAD_DURATION_SECONDS));
8585

8686
protected final ConcurrentMap<String, Cache<?, ?>> children = new ConcurrentHashMap<>();
87+
private final boolean collectEvictionWeightAsCounter;
88+
89+
/**
90+
* Instantiates a {@link CacheMetricsCollector}, with the legacy parameters.
91+
*
92+
* <p>The use of this constructor is discouraged, in favor of a Builder pattern {@link #builder()}
93+
*
94+
* <p>Note that the {@link #builder()} API has different default values than this deprecated
95+
* constructor.
96+
*/
97+
@Deprecated
98+
public CacheMetricsCollector() {
99+
this(false);
100+
}
101+
102+
/**
103+
* Instantiate a {@link CacheMetricsCollector}
104+
*
105+
* @param collectEvictionWeightAsCounter If true, {@code caffeine_cache_eviction_weight} will be
106+
* observed as an incrementing counter instead of a gauge.
107+
*/
108+
protected CacheMetricsCollector(boolean collectEvictionWeightAsCounter) {
109+
this.collectEvictionWeightAsCounter = collectEvictionWeightAsCounter;
110+
}
87111

88112
/**
89113
* Add or replace the cache with the given name.
@@ -154,6 +178,10 @@ public MetricSnapshots collect() {
154178
CounterSnapshot.builder()
155179
.name(METRIC_NAME_CACHE_EVICTION_WEIGHT)
156180
.help("Weight of evicted cache entries, doesn't include manually removed entries");
181+
final GaugeSnapshot.Builder cacheEvictionWeightLegacyGauge =
182+
GaugeSnapshot.builder()
183+
.name(METRIC_NAME_CACHE_EVICTION_WEIGHT)
184+
.help("Weight of evicted cache entries, doesn't include manually removed entries");
157185

158186
final CounterSnapshot.Builder cacheLoadFailure =
159187
CounterSnapshot.builder().name(METRIC_NAME_CACHE_LOAD_FAILURE).help("Cache load failures");
@@ -188,6 +216,11 @@ public MetricSnapshots collect() {
188216
.labels(labels)
189217
.value(stats.evictionWeight())
190218
.build());
219+
cacheEvictionWeightLegacyGauge.dataPoint(
220+
GaugeSnapshot.GaugeDataPointSnapshot.builder()
221+
.labels(labels)
222+
.value(stats.evictionWeight())
223+
.build());
191224
} catch (Exception e) {
192225
// EvictionWeight metric is unavailable, newer version of Caffeine is needed.
193226
}
@@ -258,7 +291,10 @@ public MetricSnapshots collect() {
258291
.metricSnapshot(cacheMissTotal.build())
259292
.metricSnapshot(cacheRequestsTotal.build())
260293
.metricSnapshot(cacheEvictionTotal.build())
261-
.metricSnapshot(cacheEvictionWeight.build())
294+
.metricSnapshot(
295+
collectEvictionWeightAsCounter
296+
? cacheEvictionWeight.build()
297+
: cacheEvictionWeightLegacyGauge.build())
262298
.metricSnapshot(cacheLoadFailure.build())
263299
.metricSnapshot(cacheLoadTotal.build())
264300
.metricSnapshot(cacheSize.build())
@@ -277,8 +313,16 @@ public static Builder builder() {
277313
}
278314

279315
public static class Builder {
316+
317+
private boolean collectEvictionWeightAsCounter = true;
318+
319+
public Builder collectEvictionWeightAsCounter(boolean collectEvictionWeightAsCounter) {
320+
this.collectEvictionWeightAsCounter = collectEvictionWeightAsCounter;
321+
return this;
322+
}
323+
280324
public CacheMetricsCollector build() {
281-
return new CacheMetricsCollector();
325+
return new CacheMetricsCollector(collectEvictionWeightAsCounter);
282326
}
283327
}
284328
}

prometheus-metrics-instrumentation-caffeine/src/test/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollectorTest.java

Lines changed: 80 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import io.prometheus.metrics.model.registry.PrometheusRegistry;
1414
import io.prometheus.metrics.model.snapshots.CounterSnapshot;
1515
import io.prometheus.metrics.model.snapshots.DataPointSnapshot;
16+
import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
1617
import io.prometheus.metrics.model.snapshots.Labels;
1718
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
1819
import io.prometheus.metrics.model.snapshots.SummarySnapshot;
@@ -22,17 +23,34 @@
2223
import java.nio.charset.StandardCharsets;
2324
import java.util.List;
2425
import org.junit.jupiter.api.Test;
26+
import org.junit.jupiter.params.ParameterizedTest;
27+
import org.junit.jupiter.params.provider.EnumSource;
2528

2629
@SuppressWarnings("CheckReturnValue")
2730
class CacheMetricsCollectorTest {
31+
// This enum was added to simplify test parametrization on argument options.
32+
public enum Options {
33+
LEGACY(false),
34+
COLLECT_EVICTION_WEIGHT_AS_COUNTER(true);
2835

29-
@Test
30-
public void cacheExposesMetricsForHitMissAndEviction() {
36+
private final boolean collectEvictionWeightAsCounter;
37+
38+
Options(boolean collectEvictionWeightAsCounter) {
39+
this.collectEvictionWeightAsCounter = collectEvictionWeightAsCounter;
40+
}
41+
}
42+
43+
@ParameterizedTest
44+
@EnumSource
45+
public void cacheExposesMetricsForHitMissAndEviction(Options options) {
3146
// Run cleanup in same thread, to remove async behavior with evictions
3247
final Cache<String, String> cache =
3348
Caffeine.newBuilder().maximumSize(2).recordStats().executor(Runnable::run).build();
3449

35-
final CacheMetricsCollector collector = CacheMetricsCollector.builder().build();
50+
final CacheMetricsCollector collector =
51+
CacheMetricsCollector.builder()
52+
.collectEvictionWeightAsCounter(options.collectEvictionWeightAsCounter)
53+
.build();
3654
collector.addCache("users", cache);
3755

3856
final PrometheusRegistry registry = new PrometheusRegistry();
@@ -52,7 +70,20 @@ public void cacheExposesMetricsForHitMissAndEviction() {
5270
assertCounterMetric(registry, "caffeine_cache_miss", "users", 2.0);
5371
assertCounterMetric(registry, "caffeine_cache_requests", "users", 3.0);
5472
assertCounterMetric(registry, "caffeine_cache_eviction", "users", 2.0);
55-
assertCounterMetric(registry, "caffeine_cache_eviction_weight", "users", 2.0);
73+
String openMetricEvictionWeightExpectedText;
74+
if (options.collectEvictionWeightAsCounter) {
75+
assertCounterMetric(registry, "caffeine_cache_eviction_weight", "users", 2.0);
76+
openMetricEvictionWeightExpectedText =
77+
"# TYPE caffeine_cache_eviction_weight counter\n"
78+
+ "# HELP caffeine_cache_eviction_weight Weight of evicted cache entries, doesn't include manually removed entries\n"
79+
+ "caffeine_cache_eviction_weight_total{cache=\"users\"} 2.0\n";
80+
} else {
81+
assertGaugeMetric(registry, "caffeine_cache_eviction_weight", "users", 2.0);
82+
openMetricEvictionWeightExpectedText =
83+
"# TYPE caffeine_cache_eviction_weight gauge\n"
84+
+ "# HELP caffeine_cache_eviction_weight Weight of evicted cache entries, doesn't include manually removed entries\n"
85+
+ "caffeine_cache_eviction_weight{cache=\"users\"} 2.0\n";
86+
}
5687

5788
final String expected =
5889
"# TYPE caffeine_cache_estimated_size gauge\n"
@@ -61,9 +92,7 @@ public void cacheExposesMetricsForHitMissAndEviction() {
6192
+ "# TYPE caffeine_cache_eviction counter\n"
6293
+ "# HELP caffeine_cache_eviction Cache eviction totals, doesn't include manually removed entries\n"
6394
+ "caffeine_cache_eviction_total{cache=\"users\"} 2.0\n"
64-
+ "# TYPE caffeine_cache_eviction_weight counter\n"
65-
+ "# HELP caffeine_cache_eviction_weight Weight of evicted cache entries, doesn't include manually removed entries\n"
66-
+ "caffeine_cache_eviction_weight_total{cache=\"users\"} 2.0\n"
95+
+ openMetricEvictionWeightExpectedText
6796
+ "# TYPE caffeine_cache_hit counter\n"
6897
+ "# HELP caffeine_cache_hit Cache hit totals\n"
6998
+ "caffeine_cache_hit_total{cache=\"users\"} 1.0\n"
@@ -78,8 +107,9 @@ public void cacheExposesMetricsForHitMissAndEviction() {
78107
assertThat(convertToOpenMetricsFormat(registry)).isEqualTo(expected);
79108
}
80109

81-
@Test
82-
public void weightedCacheExposesMetricsForHitMissAndEvictionWeightedSize() {
110+
@ParameterizedTest
111+
@EnumSource
112+
public void weightedCacheExposesMetricsForHitMissAndEvictionWeightedSize(Options options) {
83113
// Run cleanup in same thread, to remove async behavior with evictions
84114
final Cache<String, String> cache =
85115
Caffeine.newBuilder()
@@ -89,7 +119,10 @@ public void weightedCacheExposesMetricsForHitMissAndEvictionWeightedSize() {
89119
.executor(Runnable::run)
90120
.build();
91121

92-
final CacheMetricsCollector collector = CacheMetricsCollector.builder().build();
122+
final CacheMetricsCollector collector =
123+
CacheMetricsCollector.builder()
124+
.collectEvictionWeightAsCounter(options.collectEvictionWeightAsCounter)
125+
.build();
93126
collector.addCache("users", cache);
94127

95128
final PrometheusRegistry registry = new PrometheusRegistry();
@@ -109,7 +142,20 @@ public void weightedCacheExposesMetricsForHitMissAndEvictionWeightedSize() {
109142
assertCounterMetric(registry, "caffeine_cache_miss", "users", 2.0);
110143
assertCounterMetric(registry, "caffeine_cache_requests", "users", 3.0);
111144
assertCounterMetric(registry, "caffeine_cache_eviction", "users", 2.0);
112-
assertCounterMetric(registry, "caffeine_cache_eviction_weight", "users", 31.0);
145+
String openMetricEvictionWeightExpectedText;
146+
if (options.collectEvictionWeightAsCounter) {
147+
assertCounterMetric(registry, "caffeine_cache_eviction_weight", "users", 31.0);
148+
openMetricEvictionWeightExpectedText =
149+
"# TYPE caffeine_cache_eviction_weight counter\n"
150+
+ "# HELP caffeine_cache_eviction_weight Weight of evicted cache entries, doesn't include manually removed entries\n"
151+
+ "caffeine_cache_eviction_weight_total{cache=\"users\"} 31.0\n";
152+
} else {
153+
assertGaugeMetric(registry, "caffeine_cache_eviction_weight", "users", 31.0);
154+
openMetricEvictionWeightExpectedText =
155+
"# TYPE caffeine_cache_eviction_weight gauge\n"
156+
+ "# HELP caffeine_cache_eviction_weight Weight of evicted cache entries, doesn't include manually removed entries\n"
157+
+ "caffeine_cache_eviction_weight{cache=\"users\"} 31.0\n";
158+
}
113159

114160
final String expected =
115161
"# TYPE caffeine_cache_estimated_size gauge\n"
@@ -118,9 +164,7 @@ public void weightedCacheExposesMetricsForHitMissAndEvictionWeightedSize() {
118164
+ "# TYPE caffeine_cache_eviction counter\n"
119165
+ "# HELP caffeine_cache_eviction Cache eviction totals, doesn't include manually removed entries\n"
120166
+ "caffeine_cache_eviction_total{cache=\"users\"} 2.0\n"
121-
+ "# TYPE caffeine_cache_eviction_weight counter\n"
122-
+ "# HELP caffeine_cache_eviction_weight Weight of evicted cache entries, doesn't include manually removed entries\n"
123-
+ "caffeine_cache_eviction_weight_total{cache=\"users\"} 31.0\n"
167+
+ openMetricEvictionWeightExpectedText
124168
+ "# TYPE caffeine_cache_hit counter\n"
125169
+ "# HELP caffeine_cache_hit Cache hit totals\n"
126170
+ "caffeine_cache_hit_total{cache=\"users\"} 1.0\n"
@@ -178,9 +222,13 @@ public void loadingCacheExposesMetricsForLoadsAndExceptions() throws Exception {
178222
assertThat(loadDuration.getSum()).isGreaterThan(0);
179223
}
180224

181-
@Test
182-
public void getPrometheusNamesHasSameSizeAsMetricSizeWhenScraping() {
183-
final CacheMetricsCollector collector = CacheMetricsCollector.builder().build();
225+
@ParameterizedTest
226+
@EnumSource
227+
public void getPrometheusNamesHasSameSizeAsMetricSizeWhenScraping(Options options) {
228+
final CacheMetricsCollector collector =
229+
CacheMetricsCollector.builder()
230+
.collectEvictionWeightAsCounter(options.collectEvictionWeightAsCounter)
231+
.build();
184232

185233
final PrometheusRegistry registry = new PrometheusRegistry();
186234
registry.register(collector);
@@ -191,9 +239,13 @@ public void getPrometheusNamesHasSameSizeAsMetricSizeWhenScraping() {
191239
assertThat(prometheusNames).hasSize(metricSnapshots.size());
192240
}
193241

194-
@Test
195-
public void collectedMetricNamesAreKnownPrometheusNames() {
196-
final CacheMetricsCollector collector = CacheMetricsCollector.builder().build();
242+
@ParameterizedTest
243+
@EnumSource
244+
public void collectedMetricNamesAreKnownPrometheusNames(Options options) {
245+
final CacheMetricsCollector collector =
246+
CacheMetricsCollector.builder()
247+
.collectEvictionWeightAsCounter(options.collectEvictionWeightAsCounter)
248+
.build();
197249

198250
final PrometheusRegistry registry = new PrometheusRegistry();
199251
registry.register(collector);
@@ -214,6 +266,14 @@ private void assertCounterMetric(
214266
assertThat(dataPointSnapshot.getValue()).isEqualTo(value);
215267
}
216268

269+
private void assertGaugeMetric(
270+
PrometheusRegistry registry, String name, String cacheName, double value) {
271+
final GaugeSnapshot.GaugeDataPointSnapshot dataPointSnapshot =
272+
(GaugeSnapshot.GaugeDataPointSnapshot) getDataPointSnapshot(registry, name, cacheName);
273+
274+
assertThat(dataPointSnapshot.getValue()).isEqualTo(value);
275+
}
276+
217277
private DataPointSnapshot getDataPointSnapshot(
218278
PrometheusRegistry registry, String name, String cacheName) {
219279
final Labels labels = Labels.of(new String[] {"cache"}, new String[] {cacheName});

0 commit comments

Comments
 (0)