DATAREDIS-1082 - Capture per cache statistics.

Original Pull Request: #545
This commit is contained in:
Christoph Strobl
2020-07-10 12:22:41 +02:00
parent 6daeb1a04c
commit 72c20447b8
16 changed files with 989 additions and 186 deletions

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.redis.cache;
import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/**
* @author Christoph Strobl
*/
class DefaultCacheStatisticsCollectorUnitTests {
static final String CACHE_1 = "cache:1";
static final String CACHE_2 = "cache:2";
DefaultCacheStatisticsCollector collector;
@BeforeEach
void beforeEach() {
collector = new DefaultCacheStatisticsCollector();
}
@Test // DATAREDIS-1082
void collectsStatsPerCache() {
collector.incGets(CACHE_1);
collector.incPuts(CACHE_2);
assertThat(collector.getCacheStatistics(CACHE_1).getGets()).isOne();
assertThat(collector.getCacheStatistics(CACHE_1).getPuts()).isZero();
assertThat(collector.getCacheStatistics(CACHE_2).getGets()).isZero();
assertThat(collector.getCacheStatistics(CACHE_2).getPuts()).isOne();
}
@Test // DATAREDIS-1082
void returnsEmptyStatsForCacheWithoutStatsSet() {
assertThat(collector.getCacheStatistics(CACHE_1).getGets()).isZero();
assertThat(collector.getCacheStatistics(CACHE_1).getPuts()).isZero();
assertThat(collector.getCacheStatistics(CACHE_1).getDeletes()).isZero();
}
@Test // DATAREDIS-1082
void returnsSnapshotOnGet() {
collector.incGets(CACHE_1);
CacheStatistics stats = collector.getCacheStatistics(CACHE_1);
assertThat(stats.getGets()).isOne();
collector.incGets(CACHE_1);
assertThat(stats.getGets()).isOne();
assertThat(collector.getCacheStatistics(CACHE_1).getGets()).isEqualTo(2);
}
@Test // DATAREDIS-1082
void resetClearsData() {
collector.incGets(CACHE_1);
CacheStatistics stats = collector.getCacheStatistics(CACHE_1);
assertThat(stats.getGets()).isOne();
collector.reset(CACHE_1);
assertThat(stats.getGets()).isOne();
assertThat(collector.getCacheStatistics(CACHE_1).getGets()).isZero();
}
}

View File

@@ -90,7 +90,7 @@ public class DefaultRedisCacheWriterTests {
@Test // DATAREDIS-481, DATAREDIS-1082
public void putShouldAddEternalEntry() {
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory);
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory).with(CacheStatisticsCollector.instance());
writer.put(CACHE_NAME, binaryCacheKey, binaryCacheValue, Duration.ZERO);
doWithConnection(connection -> {
@@ -98,8 +98,8 @@ public class DefaultRedisCacheWriterTests {
assertThat(connection.ttl(binaryCacheKey)).isEqualTo(-1);
});
assertThat(writer.getStatistics().getStores()).isOne();
assertThat(writer.getStatistics().getLockWaitDuration(TimeUnit.NANOSECONDS)).isZero();
assertThat(writer.getCacheStatistics(CACHE_NAME).getPuts()).isOne();
assertThat(writer.getCacheStatistics(CACHE_NAME).getLockWaitDuration(TimeUnit.NANOSECONDS)).isZero();
}
@Test // DATAREDIS-481
@@ -147,13 +147,13 @@ public class DefaultRedisCacheWriterTests {
doWithConnection(connection -> connection.set(binaryCacheKey, binaryCacheValue));
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory);
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory).with(CacheStatisticsCollector.instance());
assertThat(writer.get(CACHE_NAME, binaryCacheKey))
.isEqualTo(binaryCacheValue);
assertThat(writer.getStatistics().getRetrievals()).isOne();
assertThat(writer.getStatistics().getHits()).isOne();
assertThat(writer.getStatistics().getMisses()).isZero();
assertThat(writer.getCacheStatistics(CACHE_NAME).getGets()).isOne();
assertThat(writer.getCacheStatistics(CACHE_NAME).getHits()).isOne();
assertThat(writer.getCacheStatistics(CACHE_NAME).getMisses()).isZero();
}
@Test // DATAREDIS-481
@@ -164,7 +164,7 @@ public class DefaultRedisCacheWriterTests {
@Test // DATAREDIS-481, DATAREDIS-1082
public void putIfAbsentShouldAddEternalEntryWhenKeyDoesNotExist() {
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory);
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory).with(CacheStatisticsCollector.instance());
assertThat(writer.putIfAbsent(CACHE_NAME, binaryCacheKey, binaryCacheValue,
Duration.ZERO)).isNull();
@@ -172,7 +172,7 @@ public class DefaultRedisCacheWriterTests {
assertThat(connection.get(binaryCacheKey)).isEqualTo(binaryCacheValue);
});
assertThat(writer.getStatistics().getStores()).isOne();
assertThat(writer.getCacheStatistics(CACHE_NAME).getPuts()).isOne();
}
@Test // DATAREDIS-481, DATAREDIS-1082
@@ -180,7 +180,7 @@ public class DefaultRedisCacheWriterTests {
doWithConnection(connection -> connection.set(binaryCacheKey, binaryCacheValue));
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory);
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory).with(CacheStatisticsCollector.instance());
assertThat(writer.putIfAbsent(CACHE_NAME, binaryCacheKey, "foo".getBytes(), Duration.ZERO))
.isEqualTo(binaryCacheValue);
@@ -188,19 +188,19 @@ public class DefaultRedisCacheWriterTests {
assertThat(connection.get(binaryCacheKey)).isEqualTo(binaryCacheValue);
});
assertThat(writer.getStatistics().getStores()).isZero();
assertThat(writer.getCacheStatistics(CACHE_NAME).getPuts()).isZero();
}
@Test // DATAREDIS-481, DATAREDIS-1082
public void putIfAbsentShouldAddExpiringEntryWhenKeyDoesNotExist() {
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory);
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory).with(CacheStatisticsCollector.instance());
assertThat(writer.putIfAbsent(CACHE_NAME, binaryCacheKey, binaryCacheValue, Duration.ofSeconds(5))).isNull();
doWithConnection(connection -> {
assertThat(connection.ttl(binaryCacheKey)).isGreaterThan(3).isLessThan(6);
});
assertThat(writer.getStatistics().getStores()).isOne();
assertThat(writer.getCacheStatistics(CACHE_NAME).getPuts()).isOne();
}
@Test // DATAREDIS-481, DATAREDIS-1082
@@ -208,11 +208,11 @@ public class DefaultRedisCacheWriterTests {
doWithConnection(connection -> connection.set(binaryCacheKey, binaryCacheValue));
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory);
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory).with(CacheStatisticsCollector.instance());
writer.remove(CACHE_NAME, binaryCacheKey);
doWithConnection(connection -> assertThat(connection.exists(binaryCacheKey)).isFalse());
assertThat(writer.getStatistics().getRemovals()).isOne();
assertThat(writer.getCacheStatistics(CACHE_NAME).getDeletes()).isOne();
}
@Test // DATAREDIS-418, DATAREDIS-1082
@@ -223,14 +223,14 @@ public class DefaultRedisCacheWriterTests {
connection.set("foo".getBytes(), "bar".getBytes());
});
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory);
RedisCacheWriter writer = nonLockingRedisCacheWriter(connectionFactory).with(CacheStatisticsCollector.instance());
writer.clean(CACHE_NAME, (CACHE_NAME + "::*").getBytes(Charset.forName("UTF-8")));
doWithConnection(connection -> {
assertThat(connection.exists(binaryCacheKey)).isFalse();
assertThat(connection.exists("foo".getBytes())).isTrue();
});
assertThat(writer.getStatistics().getRemovals()).isOne();
assertThat(writer.getCacheStatistics(CACHE_NAME).getDeletes()).isOne();
}
@Test // DATAREDIS-481
@@ -261,7 +261,7 @@ public class DefaultRedisCacheWriterTests {
@Test // DATAREDIS-481, DATAREDIS-1082
public void lockingCacheWriterShouldWaitForLockRelease() throws InterruptedException {
DefaultRedisCacheWriter writer = (DefaultRedisCacheWriter) lockingRedisCacheWriter(connectionFactory);
DefaultRedisCacheWriter writer = (DefaultRedisCacheWriter) lockingRedisCacheWriter(connectionFactory).with(CacheStatisticsCollector.instance());
writer.lock(CACHE_NAME);
CountDownLatch beforeWrite = new CountDownLatch(1);
@@ -291,7 +291,7 @@ public class DefaultRedisCacheWriterTests {
doWithConnection(connection -> {
assertThat(connection.exists(binaryCacheKey)).isTrue();
});
assertThat(writer.getStatistics().getLockWaitDuration(TimeUnit.NANOSECONDS)).isGreaterThan(0);
assertThat(writer.getCacheStatistics(CACHE_NAME).getLockWaitDuration(TimeUnit.NANOSECONDS)).isGreaterThan(0);
} finally {
th.interrupt();
}
@@ -338,6 +338,18 @@ public class DefaultRedisCacheWriterTests {
.hasCauseInstanceOf(InterruptedException.class);
}
@Test // DATAREDIS-1082
public void noOpSatisticsCollectorReturnsEmptyStatsInstance() {
DefaultRedisCacheWriter cw = (DefaultRedisCacheWriter) lockingRedisCacheWriter(connectionFactory);
CacheStatistics stats = cw.getCacheStatistics(CACHE_NAME);
cw.putIfAbsent(CACHE_NAME, binaryCacheKey, binaryCacheValue, Duration.ofSeconds(5));
assertThat(stats).isNotNull();
assertThat(stats.getPuts()).isNegative();
}
private void doWithConnection(Consumer<RedisConnection> callback) {
RedisConnection connection = connectionFactory.getConnection();

View File

@@ -20,22 +20,22 @@ import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Test;
/**
* Unit tests for {@link DefaultCacheStatistics}.
* Unit tests for {@link MutableCacheStatistics}.
*
* @author Mark Paluch
*/
class DefaultCacheStatisticsUnitTests {
class MutableCacheStatisticsUnitTests {
DefaultCacheStatistics statistics = new DefaultCacheStatistics();
MutableCacheStatistics statistics = new MutableCacheStatistics("cache-name");
@Test // DATAREDIS-1082
void shouldReportRetrievals() {
assertThat(statistics.getRetrievals()).isZero();
assertThat(statistics.getGets()).isZero();
statistics.incrementRetrievals();
statistics.incGets();
assertThat(statistics.getRetrievals()).isOne();
assertThat(statistics.getGets()).isOne();
}
@Test // DATAREDIS-1082
@@ -43,7 +43,7 @@ class DefaultCacheStatisticsUnitTests {
assertThat(statistics.getHits()).isZero();
statistics.incrementHits();
statistics.incHits();
assertThat(statistics.getHits()).isOne();
}
@@ -53,7 +53,7 @@ class DefaultCacheStatisticsUnitTests {
assertThat(statistics.getMisses()).isZero();
statistics.incrementMisses();
statistics.incMisses();
assertThat(statistics.getMisses()).isOne();
}
@@ -61,20 +61,20 @@ class DefaultCacheStatisticsUnitTests {
@Test // DATAREDIS-1082
void shouldReportPuts() {
assertThat(statistics.getStores()).isZero();
assertThat(statistics.getPuts()).isZero();
statistics.incrementStores();
statistics.incPuts();
assertThat(statistics.getStores()).isOne();
assertThat(statistics.getPuts()).isOne();
}
@Test // DATAREDIS-1082
void shouldReportRemovals() {
assertThat(statistics.getRemovals()).isZero();
assertThat(statistics.getDeletes()).isZero();
statistics.incrementRemovals();
statistics.incDeletes();
assertThat(statistics.getRemovals()).isOne();
assertThat(statistics.getDeletes()).isOne();
}
}

View File

@@ -171,4 +171,21 @@ class RedisCacheManagerUnitTests {
void builderShouldRequireCacheWriter() {
assertThatIllegalStateException().isThrownBy(() -> RedisCacheManager.builder().build());
}
@Test // DATAREDIS-1082
void builderSetsStatisticsCollectorWhenEnabled() {
when(cacheWriter.with(any())).thenReturn(cacheWriter);
RedisCacheManager.builder(cacheWriter).enableStatistics().build();
verify(cacheWriter).with(any(DefaultCacheStatisticsCollector.class));
}
@Test // DATAREDIS-1082
void builderWontSetStatisticsCollectorByDefault() {
RedisCacheManager.builder(cacheWriter).build();
verify(cacheWriter, never()).with(any());
}
}