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:
John Blum
2018-09-21 15:16:02 -07:00
parent 5861740a66
commit 6f58762f62
2 changed files with 62 additions and 26 deletions

View File

@@ -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));
}

View File

@@ -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);