Skip to content

Commit

Permalink
#15: Provide some reasonable rules
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Geisselmeier committed Apr 15, 2015
1 parent 177e236 commit cf8caa2
Show file tree
Hide file tree
Showing 8 changed files with 411 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package org.levigo.jadice.server.converterclient.gui.clusterhealth;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

import javax.management.JMException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectInstance;
import javax.management.Query;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.levigo.jadice.server.converterclient.Preferences;

public class JmxHelper {

private static final String SERVER_BEAN_CLASS = "com.levigo.jadice.server.core.JadiceServer";

private static final String STATISTICS_BEAN_CLASS = "com.levigo.jadice.server.core.ServerStatistics";

private JmxHelper() {
// hidden constructor
}

public static JMXConnector createConnector(String jmxServiceUrl) throws JMException {
try {
JMXServiceURL jmxUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + jmxServiceUrl + "/jmxrmi");
final Map<String, Object> env = new HashMap<>();
if (Preferences.jmxUsernameProperty().isNotEmpty().get()) {
// See https://blogs.oracle.com/lmalventosa/entry/jmx_authentication_authorization
String[] creds = {
Preferences.jmxUsernameProperty().get(), Preferences.jmxPasswordProperty().get()
};
env.put(JMXConnector.CREDENTIALS, creds);
}
return JMXConnectorFactory.connect(jmxUrl, env);
} catch (IOException | IllegalArgumentException e) {
throw wrap(e);
}
}

private static <N extends Number> N retrieveNumericValue(MBeanServerConnection mbsc, String beanClassName, String attributeName,
N fallbackValue, Function<String, N> parser) throws JMException {
try {
ObjectInstance bean = getBeanByClassName(beanClassName, mbsc);
if (bean == null) {
return fallbackValue;
}
final Object attribute = mbsc.getAttribute(bean.getObjectName(), attributeName);
if (attribute == null) {
return fallbackValue;
}
return parser.apply(attribute.toString());
} catch (IOException | NumberFormatException e) {
throw wrap(e);
}
}

public static ObjectInstance getJadiceServerBean(MBeanServerConnection mbsc) throws IOException {
return JmxHelper.getBeanByClassName(SERVER_BEAN_CLASS, mbsc);
}


public static ObjectInstance getStatisticsBean(MBeanServerConnection mbsc) throws IOException {
return getBeanByClassName(STATISTICS_BEAN_CLASS, mbsc);
}


public static ObjectInstance getBeanByClassName(String classname, MBeanServerConnection mbsc) throws IOException {
final Set<ObjectInstance> beans = mbsc.queryMBeans(null, Query.isInstanceOf(Query.value(classname)));
if (beans.size() != 1) {
return null;
}
return beans.iterator().next();
}

public static float getTotalFailureRate(MBeanServerConnection mbsc) throws JMException {
return retrieveNumericValue(mbsc, STATISTICS_BEAN_CLASS, "TotalFailureRate", Float.NaN, Float::parseFloat);
}

public static float getRecentFailureRate(MBeanServerConnection mbsc) throws JMException {
return retrieveNumericValue(mbsc, STATISTICS_BEAN_CLASS, "TotalFailureRate", Float.NaN, Float::parseFloat);
}

public static long getRecentAverageExecutionTime(MBeanServerConnection mbsc) throws JMException {
return retrieveNumericValue(mbsc, STATISTICS_BEAN_CLASS, "RecentAverageExecutionTime", 0L, Long::parseLong);
}

public static long getAverageExecutionTime(MBeanServerConnection mbsc) throws JMException {
return retrieveNumericValue(mbsc, STATISTICS_BEAN_CLASS, "AverageExecutionTime", 0L, Long::parseLong);
}

public static float getEfficiency10Min(MBeanServerConnection mbsc) throws JMException {
return retrieveNumericValue(mbsc, STATISTICS_BEAN_CLASS, "Efficiency10Min", Float.NaN, Float::parseFloat);
}

public static boolean isRunning(MBeanServerConnection mbsc) throws JMException {
try {
final ObjectInstance bean = getJadiceServerBean(mbsc);
if (bean == null) {
return false;
}
return "true".equalsIgnoreCase(mbsc.getAttribute(bean.getObjectName(), "Running").toString());
} catch (IOException e) {
throw wrap(e);
}
}

private static JMException wrap(Exception e) throws JMException {
if (e instanceof JMException) {
return (JMException) e;
}
final JMException jmException = new JMException(e.getMessage());
jmException.initCause(e);
return jmException;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2013 by Gerrit Grunwald
*
* 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.levigo.jadice.server.converterclient.gui.clusterhealth;


import java.util.Timer;
import java.util.TimerTask;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import org.controlsfx.control.GridView;


/**
* Created by User: hansolo Date: 31.08.13 Time: 08:37
*/
public class StatusControlDemo extends Application {

private static final ClusterInstance instance1 = new ClusterInstance("localhost:61619", FXCollections.emptyObservableList());
private static final StatusControl control1 = new StatusControl(instance1);

private static final ClusterInstance instance2 = new ClusterInstance("jadice-server:61619", FXCollections.emptyObservableList());
private static final StatusControl control2 = new StatusControl(instance2);

private final Timer timer = new Timer();

@Override
public void init() {
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
instance1.update();
instance2.update();

}
}, 0, 5000);
}

@Override
public void stop() throws Exception {
timer.cancel();
}

@Override
public void start(Stage stage) {
final ObservableList<StatusControl> items = FXCollections.observableArrayList(control1, control2);
GridView<StatusControl> grid = new GridView<>(items);
grid.setCellFactory(view -> new StatusControlGridCell());
grid.setCellWidth(350);
grid.setCellHeight(30);
grid.setVerticalCellSpacing(5);
grid.setHorizontalCellSpacing(5);
final BorderPane root = new BorderPane(grid);
Scene scene = new Scene(root, 128, 128);
root.setBackground(new Background(new BackgroundFill(Color.WHITE, null, null)));
stage.setScene(scene);
stage.show();
}

public static void main(String[] args) {
launch(args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.levigo.jadice.server.converterclient.gui.clusterhealth.rule;

import javax.management.JMException;
import javax.management.MBeanServerConnection;

import org.levigo.jadice.server.converterclient.gui.clusterhealth.HealthStatus;
import org.levigo.jadice.server.converterclient.gui.clusterhealth.JmxHelper;

public class AverageExecutionTimeRule implements Rule<Long> {

private final long limit;

public AverageExecutionTimeRule(long limit) {
this.limit = limit;
}

@Override
public String getDescription() {
return "Average execution time";
}

@Override
public EvaluationResult<Long> evaluate(MBeanServerConnection mbsc) {
try {
final long execTime = JmxHelper.getAverageExecutionTime(mbsc);
if (execTime <= limit) {
return new EvaluationResult<Long>(HealthStatus.GOOD, execTime);
} else {
return new EvaluationResult<Long>(HealthStatus.ATTENTION, execTime, getDescription() + ": " + execTime);
}
} catch (JMException e) {
return new EvaluationResult<Long>(HealthStatus.FAILURE, -1L, e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.levigo.jadice.server.converterclient.gui.clusterhealth.rule;

import javax.management.JMException;
import javax.management.MBeanServerConnection;

import org.levigo.jadice.server.converterclient.gui.clusterhealth.HealthStatus;
import org.levigo.jadice.server.converterclient.gui.clusterhealth.JmxHelper;

public class RecentAverageExecutionTimeRule implements Rule<Long> {

private final long limit;

public RecentAverageExecutionTimeRule(long limit) {
this.limit = limit;
}

@Override
public String getDescription() {
return "Average execution time";
}

@Override
public EvaluationResult<Long> evaluate(MBeanServerConnection mbsc) {
try {
final long execTime = JmxHelper.getRecentAverageExecutionTime(mbsc);
if (execTime <= limit) {
return new EvaluationResult<Long>(HealthStatus.GOOD, execTime);
} else {
return new EvaluationResult<Long>(HealthStatus.ATTENTION, execTime, getDescription() + ": " + execTime);
}
} catch (JMException e) {
return new EvaluationResult<Long>(HealthStatus.FAILURE, -1L, e);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.levigo.jadice.server.converterclient.gui.clusterhealth.rule;

import javax.management.JMException;
import javax.management.MBeanServerConnection;

import org.levigo.jadice.server.converterclient.gui.clusterhealth.HealthStatus;
import org.levigo.jadice.server.converterclient.gui.clusterhealth.JmxHelper;

public class RecentEfficiencyRule implements Rule<Float> {

private final float limit;

public RecentEfficiencyRule(float limit) {
this.limit = limit;
}

@Override
public String getDescription() {
return "Recent efficiency";
}

@Override
public EvaluationResult<Float> evaluate(MBeanServerConnection mbsc) {
try {
final float eff = JmxHelper.getEfficiency10Min(mbsc);
if (eff <= limit) {
return new EvaluationResult<Float>(HealthStatus.GOOD, eff);
} else {
return new EvaluationResult<Float>(HealthStatus.ATTENTION, eff, getDescription() + ": " + eff);
}
} catch (JMException e) {
return new EvaluationResult<Float>(HealthStatus.FAILURE, Float.NaN, e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.levigo.jadice.server.converterclient.gui.clusterhealth.rule;

import javax.management.JMException;
import javax.management.MBeanServerConnection;

import org.levigo.jadice.server.converterclient.gui.clusterhealth.HealthStatus;
import org.levigo.jadice.server.converterclient.gui.clusterhealth.JmxHelper;

public class RecentFailureRateRule implements Rule<Float> {

private final float limit;

public RecentFailureRateRule(float limit) {
this.limit = limit;
}

@Override
public String getDescription() {
return "Recent failure rate";
}

@Override
public EvaluationResult<Float> evaluate(MBeanServerConnection mbsc) {
try {
final float rate = JmxHelper.getRecentFailureRate(mbsc);
if (rate <= limit) {
return new EvaluationResult<Float>(HealthStatus.GOOD, rate);
} else {
return new EvaluationResult<Float>(HealthStatus.ATTENTION, rate, getDescription() + ": " + rate);
}
} catch (JMException e) {
return new EvaluationResult<Float>(HealthStatus.FAILURE, Float.NaN, e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.levigo.jadice.server.converterclient.gui.clusterhealth.rule;

import javax.management.JMException;
import javax.management.MBeanServerConnection;

import org.levigo.jadice.server.converterclient.gui.clusterhealth.HealthStatus;
import org.levigo.jadice.server.converterclient.gui.clusterhealth.JmxHelper;

public class ServerRunningRule implements Rule<Boolean> {

@Override
public String getDescription() {
return "Instance is running";
}

@Override
public EvaluationResult<Boolean> evaluate(MBeanServerConnection mbsc) {
try {
if (JmxHelper.isRunning(mbsc)) {
return new EvaluationResult<Boolean>(HealthStatus.GOOD, true);
} else {
return new EvaluationResult<Boolean>(HealthStatus.FAILURE, false, getDescription() + ": false");
}
} catch (JMException e) {
return new EvaluationResult<Boolean>(HealthStatus.FAILURE, false, e);
}
}
}
Loading

0 comments on commit cf8caa2

Please sign in to comment.