Convert DataPolicy type into String.
Guard against null/unset Pool names when processing a non-client Region. Add statistics-enabled configuration meta-data property to the health information for a Region. Handle PARTITION Region statisitcs using the RegionStatisticsResolver class. Convert EvictionAction types to Strings. Convert EvictionAlgorithm types to Strings. Convert ExpirationAction types to Strings.
This commit is contained in:
@@ -26,9 +26,12 @@ import java.util.stream.Collectors;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionAttributes;
|
||||
import org.apache.geode.internal.cache.LocalDataSet;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
import org.springframework.geode.boot.actuate.health.AbstractGeodeHealthIndicator;
|
||||
import org.springframework.geode.boot.actuate.health.support.RegionStatisticsResolver;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link GeodeRegionsHealthIndicator} class is a Spring Boot {@link HealthIndicator} providing details about
|
||||
@@ -48,7 +51,7 @@ public class GeodeRegionsHealthIndicator extends AbstractGeodeHealthIndicator {
|
||||
private final BiConsumer<Region<?, ?>, Health.Builder> gemfireRegionHealthIndicatorConsumers = withRegionDetails()
|
||||
.andThen(withPartitionRegionDetails())
|
||||
.andThen(withRegionEvictionPolicyDetails())
|
||||
.andThen(withRegionExpirationDetails())
|
||||
.andThen(withRegionExpirationPolicyDetails())
|
||||
.andThen(withRegionStatisticsDetails());
|
||||
|
||||
/**
|
||||
@@ -125,13 +128,16 @@ public class GeodeRegionsHealthIndicator extends AbstractGeodeHealthIndicator {
|
||||
Optional.ofNullable(region.getAttributes())
|
||||
.ifPresent(regionAttributes -> builder
|
||||
.withDetail(cacheRegionKey(regionName, "cloning-enabled"), toYesNoString(regionAttributes.getCloningEnabled()))
|
||||
.withDetail(cacheRegionKey(regionName, "data-policy"), regionAttributes.getDataPolicy())
|
||||
.withDetail(cacheRegionKey(regionName, "data-policy"), String.valueOf(regionAttributes.getDataPolicy()))
|
||||
.withDetail(cacheRegionKey(regionName, "initial-capacity"), regionAttributes.getInitialCapacity())
|
||||
.withDetail(cacheRegionKey(regionName, "load-factor"), regionAttributes.getLoadFactor())
|
||||
.withDetail(cacheRegionKey(regionName, "key-constraint"), nullSafeClassName(regionAttributes.getKeyConstraint()))
|
||||
.withDetail(cacheRegionKey(regionName, "off-heap"), toYesNoString(regionAttributes.getOffHeap()))
|
||||
.withDetail(cacheRegionKey(regionName, "pool-name"), regionAttributes.getPoolName())
|
||||
.withDetail(cacheRegionKey(regionName, "scope"), regionAttributes.getScope())
|
||||
.withDetail(cacheRegionKey(regionName, "pool-name"), Optional.ofNullable(regionAttributes.getPoolName())
|
||||
.filter(StringUtils::hasText)
|
||||
.orElse(""))
|
||||
.withDetail(cacheRegionKey(regionName, "scope"), String.valueOf(regionAttributes.getScope()))
|
||||
.withDetail(cacheRegionKey(regionName, "statistics-enabled"), toYesNoString(regionAttributes.getStatisticsEnabled()))
|
||||
.withDetail(cacheRegionKey(regionName, "value-constraint"), nullSafeClassName(regionAttributes.getValueConstraint())));
|
||||
};
|
||||
|
||||
@@ -144,11 +150,13 @@ public class GeodeRegionsHealthIndicator extends AbstractGeodeHealthIndicator {
|
||||
String regionName = region.getName();
|
||||
|
||||
Optional.of(region)
|
||||
.filter(it -> it.getAttributes() != null)
|
||||
.filter(this::isRegionAttributesPresent)
|
||||
.map(Region::getAttributes)
|
||||
.map(RegionAttributes::getPartitionAttributes)
|
||||
.ifPresent(partitionAttributes -> builder
|
||||
.withDetail(cachePartitionRegionKey(regionName, "collocated-with"), partitionAttributes.getColocatedWith())
|
||||
.withDetail(cachePartitionRegionKey(regionName, "collocated-with"), Optional.ofNullable(partitionAttributes.getColocatedWith())
|
||||
.filter(StringUtils::hasText)
|
||||
.orElse(""))
|
||||
.withDetail(cachePartitionRegionKey(regionName, "local-max-memory"), partitionAttributes.getLocalMaxMemory())
|
||||
.withDetail(cachePartitionRegionKey(regionName, "redundant-copies"), partitionAttributes.getRedundantCopies())
|
||||
.withDetail(cachePartitionRegionKey(regionName, "total-max-memory"), partitionAttributes.getTotalMaxMemory())
|
||||
@@ -163,15 +171,15 @@ public class GeodeRegionsHealthIndicator extends AbstractGeodeHealthIndicator {
|
||||
String regionName = region.getName();
|
||||
|
||||
Optional.of(region)
|
||||
.filter(it -> it.getAttributes() != null)
|
||||
.filter(this::isRegionAttributesPresent)
|
||||
.map(Region::getAttributes)
|
||||
.map(RegionAttributes::getEvictionAttributes)
|
||||
.ifPresent(evictionAttributes -> {
|
||||
|
||||
builder.withDetail(cacheRegionEvictionKey(regionName, "action"), evictionAttributes.getAction())
|
||||
.withDetail(cacheRegionEvictionKey(regionName, "algorithm"), evictionAttributes.getAlgorithm());
|
||||
builder.withDetail(cacheRegionEvictionKey(regionName, "action"), String.valueOf(evictionAttributes.getAction()))
|
||||
.withDetail(cacheRegionEvictionKey(regionName, "algorithm"), String.valueOf(evictionAttributes.getAlgorithm()));
|
||||
|
||||
// NOTE: Careful! Eviction Maximum does not apply when Algorithm is Heap LRU.
|
||||
// NOTE: Careful! Eviction Maximum does not apply when Eviction Algorithm is Heap LRU.
|
||||
Optional.ofNullable(evictionAttributes.getAlgorithm())
|
||||
.filter(it -> !it.isLRUHeap())
|
||||
.ifPresent(it -> builder
|
||||
@@ -180,26 +188,26 @@ public class GeodeRegionsHealthIndicator extends AbstractGeodeHealthIndicator {
|
||||
};
|
||||
}
|
||||
|
||||
private BiConsumer<Region<?, ?>, Health.Builder> withRegionExpirationDetails() {
|
||||
private BiConsumer<Region<?, ?>, Health.Builder> withRegionExpirationPolicyDetails() {
|
||||
|
||||
return (region, builder) -> {
|
||||
|
||||
String regionName = region.getName();
|
||||
|
||||
Optional.of(region)
|
||||
.filter(it -> it.getAttributes() != null)
|
||||
.filter(this::isRegionAttributesPresent)
|
||||
.map(Region::getAttributes)
|
||||
.map(RegionAttributes::getEntryTimeToLive)
|
||||
.ifPresent(expirationAttributes -> builder
|
||||
.withDetail(cacheRegionExpirationKey(regionName, "entry.ttl.action"), expirationAttributes.getAction())
|
||||
.withDetail(cacheRegionExpirationKey(regionName, "entry.ttl.action"), String.valueOf(expirationAttributes.getAction()))
|
||||
.withDetail(cacheRegionExpirationKey(regionName, "entry.ttl.timeout"), expirationAttributes.getTimeout()));
|
||||
|
||||
Optional.of(region)
|
||||
.filter(it -> it.getAttributes() != null)
|
||||
.filter(this::isRegionAttributesPresent)
|
||||
.map(Region::getAttributes)
|
||||
.map(RegionAttributes::getEntryIdleTimeout)
|
||||
.ifPresent(expirationAttributes -> builder
|
||||
.withDetail(cacheRegionExpirationKey(regionName, "entry.tti.action"), expirationAttributes.getAction())
|
||||
.withDetail(cacheRegionExpirationKey(regionName, "entry.tti.action"), String.valueOf(expirationAttributes.getAction()))
|
||||
.withDetail(cacheRegionExpirationKey(regionName, "entry.tti.timeout"), expirationAttributes.getTimeout()));
|
||||
};
|
||||
}
|
||||
@@ -211,10 +219,11 @@ public class GeodeRegionsHealthIndicator extends AbstractGeodeHealthIndicator {
|
||||
String regionName = region.getName();
|
||||
|
||||
Optional.of(region)
|
||||
.filter(it -> it.getAttributes() != null)
|
||||
.filter(it -> it.getAttributes().getStatisticsEnabled())
|
||||
.map(Region::getStatistics)
|
||||
.filter(this::isNotLocalDataSet)
|
||||
.filter(this::isStatisticsEnabled)
|
||||
.map(RegionStatisticsResolver::resolve)
|
||||
.ifPresent(cacheStatistics -> builder
|
||||
.withDetail(cacheRegionStatisticsKey(regionName, "cache-statistics-type"), nullSafeClassName(cacheStatistics.getClass()))
|
||||
.withDetail(cacheRegionStatisticsKey(regionName, "hit-count"), cacheStatistics.getHitCount())
|
||||
.withDetail(cacheRegionStatisticsKey(regionName, "hit-ratio"), cacheStatistics.getHitRatio())
|
||||
.withDetail(cacheRegionStatisticsKey(regionName, "last-accessed-time"), cacheStatistics.getLastAccessedTime())
|
||||
@@ -223,6 +232,29 @@ public class GeodeRegionsHealthIndicator extends AbstractGeodeHealthIndicator {
|
||||
};
|
||||
}
|
||||
|
||||
private boolean isLocalDataSet(Region<?, ?> region) {
|
||||
return region instanceof LocalDataSet;
|
||||
}
|
||||
|
||||
private boolean isNotLocalDataSet(Region<?, ?> region) {
|
||||
return !isLocalDataSet(region);
|
||||
}
|
||||
|
||||
private boolean isRegionAttributesPresent(Region<?, ?> region) {
|
||||
|
||||
return Optional.ofNullable(region)
|
||||
.map(Region::getAttributes)
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
private boolean isStatisticsEnabled(Region<?, ?> region) {
|
||||
|
||||
return Optional.ofNullable(region)
|
||||
.map(Region::getAttributes)
|
||||
.filter(RegionAttributes::getStatisticsEnabled)
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
private String cachePartitionRegionKey(String regionName, String suffix) {
|
||||
return cacheRegionKey(regionName, String.format("partition.%s", suffix));
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ import org.springframework.data.gemfire.tests.mock.CacheMockObjects;
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.apache.geode.cache.CacheStatistics
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.boot.actuate.health.Health
|
||||
@@ -90,6 +91,7 @@ public class GeodeRegionsHealthIndicatorUnitTests {
|
||||
when(mockRegionOne.getAttributes().getOffHeap()).thenReturn(true);
|
||||
when(mockRegionOne.getAttributes().getPoolName()).thenReturn("");
|
||||
when(mockRegionOne.getAttributes().getScope()).thenReturn(Scope.DISTRIBUTED_ACK);
|
||||
when(mockRegionOne.getAttributes().getStatisticsEnabled()).thenReturn(false);
|
||||
when(mockRegionOne.getAttributes().getValueConstraint()).thenReturn((Class) Currency.class);
|
||||
|
||||
PartitionAttributes<?, ?> mockPartitionAttributes = mock(PartitionAttributes.class);
|
||||
@@ -163,13 +165,13 @@ public class GeodeRegionsHealthIndicatorUnitTests {
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions", Arrays.asList("/MockRegionOne", "/MockRegionTwo"));
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.count", (long) mockRegions.size());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.cloning-enabled", "Yes");
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.data-policy", DataPolicy.PARTITION);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.data-policy", DataPolicy.PARTITION.toString());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.initial-capacity", 101);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.load-factor", 0.75f);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.key-constraint", Long.class.getName());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.off-heap", "Yes");
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.eviction.action", EvictionAction.LOCAL_DESTROY);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.eviction.algorithm", EvictionAlgorithm.LRU_ENTRY);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.eviction.action", EvictionAction.LOCAL_DESTROY.toString());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.eviction.algorithm", EvictionAlgorithm.LRU_ENTRY.toString());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.eviction.maximum", 10000);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.partition.collocated-with", "CollocatedRegion");
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.partition.local-max-memory", 10240);
|
||||
@@ -177,19 +179,21 @@ public class GeodeRegionsHealthIndicatorUnitTests {
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.partition.total-max-memory", 4096000L);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.partition.total-number-of-buckets", 226);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.pool-name", "");
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.scope", Scope.DISTRIBUTED_ACK);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.scope", Scope.DISTRIBUTED_ACK.toString());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.statistics-enabled", "No");
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionOne.value-constraint", Currency.class.getName());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.cloning-enabled", "No");
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.data-policy", DataPolicy.EMPTY);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.data-policy", DataPolicy.EMPTY.toString());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.initial-capacity", 0);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.load-factor", 0.0f);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.key-constraint", Integer.class.getName());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.off-heap", "No");
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.pool-name", "TestPool");
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.scope", Scope.DISTRIBUTED_NO_ACK);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.expiration.entry.tti.action", ExpirationAction.INVALIDATE);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.scope", Scope.DISTRIBUTED_NO_ACK.toString());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.statistics-enabled", "Yes");
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.expiration.entry.tti.action", ExpirationAction.INVALIDATE.toString());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.expiration.entry.tti.timeout", 600);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.expiration.entry.ttl.action", ExpirationAction.DESTROY);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.expiration.entry.ttl.action", ExpirationAction.DESTROY.toString());
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.expiration.entry.ttl.timeout", 900);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.statistics.hit-count", 202408L);
|
||||
assertThat(healthDetails).containsEntry("geode.cache.regions.MockRegionTwo.statistics.hit-ratio", 0.82f);
|
||||
|
||||
Reference in New Issue
Block a user