diff --git a/spring-geode-actuator/spring-geode-actuator.gradle b/spring-geode-actuator/spring-geode-actuator.gradle new file mode 100644 index 00000000..4f9510b7 --- /dev/null +++ b/spring-geode-actuator/spring-geode-actuator.gradle @@ -0,0 +1,24 @@ +apply plugin: 'io.spring.convention.spring-module' + +description = "Spring Boot for Apache Geode Actuator" + +dependencies { + + compile project(":spring-geode") + + compile 'org.springframework.boot:spring-boot-starter-actuator' + + testCompile "org.assertj:assertj-core" + testCompile "junit:junit" + testCompile "org.mockito:mockito-core" + testCompile "org.projectlombok:lombok" + testCompile "edu.umd.cs.mtc:multithreadedtc" + + testCompile("org.springframework.boot:spring-boot-starter-test") { + exclude group: "org.springframework.boot", module: "spring-boot-starter-logging" + } + + testCompile "org.springframework.data:spring-data-geode-test" + testCompile slf4jDependencies + +} diff --git a/spring-geode-actuator/src/main/java/org/springframework/geode/boot/actuate/health/AbstractGeodeHealthIndicator.java b/spring-geode-actuator/src/main/java/org/springframework/geode/boot/actuate/health/AbstractGeodeHealthIndicator.java new file mode 100644 index 00000000..a287c805 --- /dev/null +++ b/spring-geode-actuator/src/main/java/org/springframework/geode/boot/actuate/health/AbstractGeodeHealthIndicator.java @@ -0,0 +1,97 @@ +/* + * Copyright 2018 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 + * + * http://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.geode.boot.actuate.health; + +import java.util.Optional; + +import org.apache.geode.cache.GemFireCache; +import org.springframework.boot.actuate.health.AbstractHealthIndicator; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.util.Assert; + +/** + * The {@link AbstractGeodeHealthIndicator} class is an abstract base class encapsulating functionality common to all + * Apache Geode {@link HealthIndicator} objects. + * + * @author John Blum + * @see org.apache.geode.cache.GemFireCache + * @see org.springframework.boot.actuate.health.AbstractHealthIndicator + * @see org.springframework.boot.actuate.health.HealthIndicator + * @since 1.0.0 + */ +@SuppressWarnings("unused") +public abstract class AbstractGeodeHealthIndicator extends AbstractHealthIndicator { + + protected static final String UNKNOWN = "unknown"; + + private final GemFireCache gemfireCache; + + /** + * Default constructor to construct an uninitialized instance of {@link AbstractGeodeHealthIndicator}, + * which will not provide any health information. + */ + public AbstractGeodeHealthIndicator(String healthCheckedFailedMessage) { + super(healthCheckedFailedMessage); + this.gemfireCache = null; + } + + /** + * Constructs an instance of the {@link AbstractGeodeHealthIndicator} initialized with a reference to + * the {@link GemFireCache} instance. + * + * @param gemfireCache reference to the {@link GemFireCache} instance used to collect health information. + * @throws IllegalArgumentException if {@link GemFireCache} is {@literal null}. + * @see org.apache.geode.cache.GemFireCache + */ + public AbstractGeodeHealthIndicator(GemFireCache gemfireCache) { + + Assert.notNull(gemfireCache, "GemFireCache must not be null"); + + this.gemfireCache = gemfireCache; + } + + /** + * Returns a reference to the {@link GemFireCache} instance. + * + * @return a reference to the {@link GemFireCache} instance. + * @see org.apache.geode.cache.GemFireCache + */ + protected Optional getGemFireCache() { + return Optional.ofNullable(this.gemfireCache); + } + + /** + * Determines the {@link String name} of the {@link Class} type safely by handling {@literal null}. + * + * @param type {@link Class} type to evaluate. + * @return the {@link String name} of the {@link Class} type. + * @see java.lang.Class#getName() + */ + protected String nullSafeClassName(Class type) { + return type != null ? type.getName() : ""; + } + + /** + * Converts a {@link Boolean} value into a {@literal yes} / {@literal no} {@link String}. + * + * @param value {@link Boolean} value to convert. + * @return a {@literal yes} / {@literal no} response for the given {@link Boolean} value. + */ + protected String toYesNoString(Boolean value) { + return Boolean.TRUE.equals(value) ? "Yes" : "No"; + } +} diff --git a/spring-geode-actuator/src/main/java/org/springframework/geode/boot/actuate/health/support/ActuatorServerLoadProbeWrapper.java b/spring-geode-actuator/src/main/java/org/springframework/geode/boot/actuate/health/support/ActuatorServerLoadProbeWrapper.java new file mode 100644 index 00000000..15563a2a --- /dev/null +++ b/spring-geode-actuator/src/main/java/org/springframework/geode/boot/actuate/health/support/ActuatorServerLoadProbeWrapper.java @@ -0,0 +1,107 @@ +/* + * Copyright 2018 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 + * + * http://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.geode.boot.actuate.health.support; + +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.geode.cache.server.ServerLoad; +import org.apache.geode.cache.server.ServerLoadProbe; +import org.apache.geode.cache.server.ServerMetrics; +import org.springframework.util.Assert; + +/** + * The ActuatorServerLoadProbeWrapper class is an implementation of Apache Geode's {@link ServerLoadProbe} interface + * used to capture the current {@link ServerMetrics} and access the latest {@link ServerLoad} details. + * + * @author John Blum + * @see org.apache.geode.cache.server.ServerLoad + * @see org.apache.geode.cache.server.ServerLoadProbe + * @see org.apache.geode.cache.server.ServerMetrics + * @since 1.0.0 + */ +@SuppressWarnings("unused") +public class ActuatorServerLoadProbeWrapper implements ServerLoadProbe { + + private AtomicReference currentServerMetrics = new AtomicReference<>(null); + + private final ServerLoadProbe delegate; + + /** + * Constructs a new instance of {@link ActuatorServerLoadProbeWrapper} initialized with the required + * {@link ServerLoadProbe} used as the delegate. + * + * @param serverLoadProbe required {@link ServerLoadProbe}. + * @throws IllegalArgumentException if {@link ServerLoadProbe} is {@literal null}. + * @see org.apache.geode.cache.server.ServerLoadProbe + */ + public ActuatorServerLoadProbeWrapper(ServerLoadProbe serverLoadProbe) { + + Assert.notNull(serverLoadProbe, "ServerLoaderProbe is required"); + + this.delegate = serverLoadProbe; + } + + /** + * Returns the current, most up-to-date details on the {@link ServerLoad} if possible. + * + * @return the current {@link ServerLoad}. + * @see org.apache.geode.cache.server.ServerLoad + * @see #getCurrentServerMetrics() + * @see java.util.Optional + */ + public Optional getCurrentServerLoad() { + return getCurrentServerMetrics().map(getDelegate()::getLoad); + } + + /** + * Returns the current, provided {@link ServerMetrics} if available. + * + * @return the current, provided {@link ServerMetrics} if available. + */ + public Optional getCurrentServerMetrics() { + return Optional.ofNullable(this.currentServerMetrics.get()); + } + + /** + * Returns the underlying, wrapped {@link ServerLoadProbe} backing this instance. + * + * @return the underlying, wrapped {@link ServerLoadProbe}. + * @see org.apache.geode.cache.server.ServerLoadProbe + */ + protected ServerLoadProbe getDelegate() { + return this.delegate; + } + + @Override + public ServerLoad getLoad(ServerMetrics metrics) { + + this.currentServerMetrics.set(metrics); + + return getDelegate().getLoad(metrics); + } + + @Override + public void open() { + getDelegate().open(); + } + + @Override + public void close() { + getDelegate().close(); + } +}