blob: a1561818851315b4adc6e4d64bf73b9bda8328bb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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.apache.geode.admin.internal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.logging.log4j.Logger;
import org.apache.geode.admin.GemFireHealth;
import org.apache.geode.admin.GemFireHealthConfig;
import org.apache.geode.distributed.internal.ClusterDistributionManager;
import org.apache.geode.internal.Assert;
import org.apache.geode.internal.logging.LogService;
/**
* Evaluates the health of various GemFire components in the VM according to a
* {@link GemFireHealthConfig}.
*
* <P>
*
* Note that evaluators never reside in the administration VM, they only in member VMs. They are not
* <code>Serializable</code> and aren't meant to be.
*
* @see MemberHealthEvaluator
* @see CacheHealthEvaluator
*
*
* @since GemFire 3.5
*/
public class GemFireHealthEvaluator {
private static final Logger logger = LogService.getLogger();
/** Determines how the health of GemFire is determined */
private GemFireHealthConfig config;
/** Evaluates the health of this member of the distributed system */
private MemberHealthEvaluator memberHealth;
/** Evaluates the health of the Cache hosted in this VM */
private CacheHealthEvaluator cacheHealth;
/**
* The most recent <code>OKAY_HEALTH</code> diagnoses of the GemFire system
*/
private List<String> okayDiagnoses;
/**
* The most recent <code>POOR_HEALTH</code> diagnoses of the GemFire system
*/
private List<String> poorDiagnoses;
/////////////////////// Constructors ///////////////////////
/**
* Creates a new <code>GemFireHealthEvaluator</code>
*
* @param config The configuration that determines whether or GemFire is healthy
* @param dm The distribution manager
*/
public GemFireHealthEvaluator(GemFireHealthConfig config, ClusterDistributionManager dm) {
if (config == null) {
throw new NullPointerException(
"Null GemFireHealthConfig");
}
this.config = config;
this.memberHealth = new MemberHealthEvaluator(config, dm);
this.cacheHealth = new CacheHealthEvaluator(config, dm);
this.okayDiagnoses = new ArrayList<>();
this.poorDiagnoses = new ArrayList<>();
}
////////////////////// Instance Methods //////////////////////
/**
* Evaluates the health of the GemFire components in this VM.
*
* @return The aggregate health code (such as {@link GemFireHealth#OKAY_HEALTH}) of the GemFire
* components.
*/
public GemFireHealth.Health evaluate() {
List status = new ArrayList();
this.memberHealth.evaluate(status);
this.cacheHealth.evaluate(status);
GemFireHealth.Health overallHealth = GemFireHealth.GOOD_HEALTH;
this.okayDiagnoses.clear();
this.poorDiagnoses.clear();
for (Iterator iter = status.iterator(); iter.hasNext();) {
AbstractHealthEvaluator.HealthStatus health =
(AbstractHealthEvaluator.HealthStatus) iter.next();
if (overallHealth == GemFireHealth.GOOD_HEALTH) {
if ((health.getHealthCode() != GemFireHealth.GOOD_HEALTH)) {
overallHealth = health.getHealthCode();
}
} else if (overallHealth == GemFireHealth.OKAY_HEALTH) {
if (health.getHealthCode() == GemFireHealth.POOR_HEALTH) {
overallHealth = GemFireHealth.POOR_HEALTH;
}
}
GemFireHealth.Health healthCode = health.getHealthCode();
if (healthCode == GemFireHealth.OKAY_HEALTH) {
this.okayDiagnoses.add(health.getDiagnosis());
} else if (healthCode == GemFireHealth.POOR_HEALTH) {
this.poorDiagnoses.add(health.getDiagnosis());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Evaluated health to be {}", overallHealth);
}
return overallHealth;
}
/**
* Returns detailed information explaining the current health status. Each array element is a
* different cause for the current status. An empty array will be returned if the current status
* is {@link GemFireHealth#GOOD_HEALTH}.
*/
public String[] getDiagnosis(GemFireHealth.Health healthCode) {
if (healthCode == GemFireHealth.GOOD_HEALTH) {
return new String[0];
} else if (healthCode == GemFireHealth.OKAY_HEALTH) {
String[] array = new String[this.okayDiagnoses.size()];
this.okayDiagnoses.toArray(array);
return array;
} else {
Assert.assertTrue(healthCode == GemFireHealth.POOR_HEALTH);
String[] array = new String[this.poorDiagnoses.size()];
this.poorDiagnoses.toArray(array);
return array;
}
}
/**
* Resets the state of this evaluator
*/
public void reset() {
this.okayDiagnoses.clear();
this.poorDiagnoses.clear();
}
/**
* Returns the heath evaluation interval, in seconds.
*
* @see GemFireHealthConfig#getHealthEvaluationInterval
*/
public int getEvaluationInterval() {
return this.config.getHealthEvaluationInterval();
}
/**
* Closes this evaluator and releases all of its resources
*/
public void close() {
this.memberHealth.close();
this.cacheHealth.close();
}
}