mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
add initial JMX driver implementation
This commit is contained in:
parent
fff55212da
commit
0b3d30caf0
44
driver-jmx/pom.xml
Normal file
44
driver-jmx/pom.xml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>mvn-defaults</artifactId>
|
||||||
|
<groupId>io.nosqlbench</groupId>
|
||||||
|
<version>3.12.129-SNAPSHOT</version>
|
||||||
|
<relativePath>../mvn-defaults</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>driver-jmx</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>
|
||||||
|
A JMX nosqlbench ActivityType (AT) driver module;
|
||||||
|
This provides the ability to query system via JMX
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.nosqlbench</groupId>
|
||||||
|
<artifactId>engine-api</artifactId>
|
||||||
|
<version>3.12.129-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- test scope only -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,37 @@
|
|||||||
|
package io.nosqlbench.driver.jmx;
|
||||||
|
|
||||||
|
import io.nosqlbench.driver.jmx.ops.JmxOp;
|
||||||
|
import io.nosqlbench.engine.api.activityapi.core.SyncAction;
|
||||||
|
import io.nosqlbench.engine.api.activityapi.planning.OpSequence;
|
||||||
|
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class JMXAction implements SyncAction {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(JMXAction.class);
|
||||||
|
|
||||||
|
private final ActivityDef activityDef;
|
||||||
|
private final int slot;
|
||||||
|
private final JMXActivity activity;
|
||||||
|
private OpSequence<ReadyJmxOp> sequencer;
|
||||||
|
|
||||||
|
public JMXAction(ActivityDef activityDef, int slot, JMXActivity activity) {
|
||||||
|
this.activityDef = activityDef;
|
||||||
|
this.slot = slot;
|
||||||
|
this.activity = activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
this.sequencer = activity.getSequencer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int runCycle(long value) {
|
||||||
|
ReadyJmxOp readyJmxOp = sequencer.get(value);
|
||||||
|
JmxOp jmxOp = readyJmxOp.bind(value);
|
||||||
|
jmxOp.execute();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package io.nosqlbench.driver.jmx;
|
||||||
|
|
||||||
|
import io.nosqlbench.engine.api.activityapi.core.Action;
|
||||||
|
import io.nosqlbench.engine.api.activityapi.core.ActionDispenser;
|
||||||
|
|
||||||
|
public class JMXActionDispenser implements ActionDispenser {
|
||||||
|
private JMXActivity activity;
|
||||||
|
|
||||||
|
public JMXActionDispenser(JMXActivity activity) {
|
||||||
|
this.activity = activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Action getAction(int slot) {
|
||||||
|
return new JMXAction(activity.getActivityDef(),slot,activity);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package io.nosqlbench.driver.jmx;
|
||||||
|
|
||||||
|
import io.nosqlbench.engine.api.activityapi.core.Activity;
|
||||||
|
import io.nosqlbench.engine.api.activityapi.planning.OpSequence;
|
||||||
|
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||||
|
import io.nosqlbench.engine.api.activityimpl.SimpleActivity;
|
||||||
|
|
||||||
|
public class JMXActivity extends SimpleActivity implements Activity {
|
||||||
|
|
||||||
|
private OpSequence<ReadyJmxOp> sequence;
|
||||||
|
|
||||||
|
public JMXActivity(ActivityDef activityDef) {
|
||||||
|
super(activityDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initActivity() {
|
||||||
|
super.initActivity();
|
||||||
|
this.sequence = createOpSequenceFromCommands(ReadyJmxOp::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OpSequence<ReadyJmxOp> getSequencer() {
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package io.nosqlbench.driver.jmx;
|
||||||
|
|
||||||
|
import io.nosqlbench.engine.api.activityapi.core.ActionDispenser;
|
||||||
|
import io.nosqlbench.engine.api.activityapi.core.ActivityType;
|
||||||
|
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||||
|
import io.nosqlbench.nb.annotations.Service;
|
||||||
|
|
||||||
|
@Service(ActivityType.class)
|
||||||
|
public class JMXActivityType implements ActivityType<JMXActivity> {
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "jmx";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JMXActivity getActivity(ActivityDef activityDef) {
|
||||||
|
return new JMXActivity(activityDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionDispenser getActionDispenser(JMXActivity activity) {
|
||||||
|
return new JMXActionDispenser(activity);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package io.nosqlbench.driver.jmx;
|
||||||
|
|
||||||
|
import io.nosqlbench.driver.jmx.ops.JMXExplainOperation;
|
||||||
|
import io.nosqlbench.driver.jmx.ops.JMXReadOperation;
|
||||||
|
import io.nosqlbench.driver.jmx.ops.JmxOp;
|
||||||
|
import io.nosqlbench.engine.api.templating.CommandTemplate;
|
||||||
|
|
||||||
|
import javax.management.MalformedObjectNameException;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
import javax.management.remote.JMXConnector;
|
||||||
|
import javax.management.remote.JMXConnectorFactory;
|
||||||
|
import javax.management.remote.JMXServiceURL;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class ReadyJmxOp {
|
||||||
|
|
||||||
|
private final CommandTemplate command;
|
||||||
|
|
||||||
|
public ReadyJmxOp(CommandTemplate command) {
|
||||||
|
this.command = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JmxOp bind(long value) {
|
||||||
|
Map<String, String> cmdmap = command.getCommand(value);
|
||||||
|
JMXConnector connector = bindConnector(cmdmap);
|
||||||
|
|
||||||
|
if (!cmdmap.containsKey("object")) {
|
||||||
|
throw new RuntimeException("You must specify an object in a jmx operation as in object=...");
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectName objectName = null;
|
||||||
|
try {
|
||||||
|
String object = cmdmap.get("object");
|
||||||
|
if (object==null) {
|
||||||
|
throw new RuntimeException("You must specify an object name for any JMX operation.");
|
||||||
|
}
|
||||||
|
objectName = new ObjectName(object);
|
||||||
|
} catch (MalformedObjectNameException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdmap.containsKey("readvar")) {
|
||||||
|
return new JMXReadOperation(connector, objectName, cmdmap.get("readvar"), cmdmap.get("as_type"),cmdmap.get("as_name"));
|
||||||
|
} else if (cmdmap.containsKey("explain")) {
|
||||||
|
return new JMXExplainOperation(connector,objectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("No valid form of JMX operation was determined from the provided command details:" + cmdmap.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private JMXConnector bindConnector(Map<String, String> cmdmap) {
|
||||||
|
|
||||||
|
JMXConnector connector = null;
|
||||||
|
try {
|
||||||
|
JMXServiceURL url = bindJMXServiceURL(cmdmap);
|
||||||
|
connector = JMXConnectorFactory.connect(url);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return connector;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JMXServiceURL bindJMXServiceURL(Map<String, String> cmdmap) {
|
||||||
|
JMXServiceURL url = null;
|
||||||
|
try {
|
||||||
|
if (cmdmap.containsKey("url")) {
|
||||||
|
url = new JMXServiceURL(cmdmap.get("url"));
|
||||||
|
} else {
|
||||||
|
if (cmdmap.containsKey("host")) {
|
||||||
|
throw new RuntimeException("You must provide at least a host if you do not provide a url.");
|
||||||
|
}
|
||||||
|
String protocol = cmdmap.get("protocol");
|
||||||
|
String host = cmdmap.get("host");
|
||||||
|
int port = Optional.ofNullable(cmdmap.get("port")).map(Integer::parseInt).orElse(0);
|
||||||
|
String path = cmdmap.get("path");
|
||||||
|
url = new JMXServiceURL(protocol, host, port, path);
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package io.nosqlbench.driver.jmx;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class ValueConverter {
|
||||||
|
|
||||||
|
public static Object convert(String typeName, Object o) {
|
||||||
|
|
||||||
|
if (!typeName.contains(".")) {
|
||||||
|
if (Number.class.isAssignableFrom(o.getClass())) {
|
||||||
|
switch (typeName) {
|
||||||
|
case "String":
|
||||||
|
return o.toString();
|
||||||
|
case "long":
|
||||||
|
case "Long":
|
||||||
|
return (((Number) o).longValue());
|
||||||
|
case "int":
|
||||||
|
case "Integer":
|
||||||
|
return (((Number) o).intValue());
|
||||||
|
case "double":
|
||||||
|
case "Double":
|
||||||
|
return (((Number) o).doubleValue());
|
||||||
|
case "float":
|
||||||
|
case "Float":
|
||||||
|
return (((Number) o).floatValue());
|
||||||
|
case "short":
|
||||||
|
case "Short":
|
||||||
|
return (((Number) o).shortValue());
|
||||||
|
case "byte":
|
||||||
|
case "Byte":
|
||||||
|
return (((Number) o).byteValue());
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("For numeric values, you can only convert to long,int,double,float,byte,short or String");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String value;
|
||||||
|
if (CharSequence.class.isAssignableFrom(o.getClass())) {
|
||||||
|
value = (String) o;
|
||||||
|
} else {
|
||||||
|
value = o.toString();
|
||||||
|
}
|
||||||
|
switch (typeName) {
|
||||||
|
case "String":
|
||||||
|
return value;
|
||||||
|
case "long":
|
||||||
|
case "Long":
|
||||||
|
return Long.parseLong(value);
|
||||||
|
case "int":
|
||||||
|
case "Integer":
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
case "double":
|
||||||
|
case "Double":
|
||||||
|
return Double.parseDouble(value);
|
||||||
|
case "float":
|
||||||
|
case "Float":
|
||||||
|
return Float.parseFloat(value);
|
||||||
|
case "short":
|
||||||
|
case "Short":
|
||||||
|
return Short.parseShort(value);
|
||||||
|
case "byte":
|
||||||
|
case "Byte":
|
||||||
|
return Byte.parseByte(value);
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("For String values, you can only convert to long, int, double, float, short, byte, or String");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<?> aClass = Class.forName(typeName);
|
||||||
|
return aClass.cast(o);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
package io.nosqlbench.driver.jmx.formats;
|
||||||
|
|
||||||
|
import javax.management.*;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class MBeanInfoConsoleFormat {
|
||||||
|
|
||||||
|
private static Map<Integer,String> MbeanOpImpacts = Map.of(
|
||||||
|
MBeanOperationInfo.ACTION,"ACTION",
|
||||||
|
MBeanOperationInfo.ACTION_INFO,"ACTION_INFO",
|
||||||
|
MBeanOperationInfo.UNKNOWN,"UNKNOWN",
|
||||||
|
MBeanOperationInfo.INFO,"INFO");
|
||||||
|
|
||||||
|
// Not including Descriptors here
|
||||||
|
public static String formatAsText(MBeanInfo info, ObjectName objectName) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("### MBeanInfo for '").append(objectName).append("'\n");
|
||||||
|
|
||||||
|
String className = info.getClassName();
|
||||||
|
sb.append("# classname: ").append(className).append("\n");
|
||||||
|
|
||||||
|
String description = info.getDescription();
|
||||||
|
sb.append("# ").append(description).append("\n");
|
||||||
|
|
||||||
|
MBeanConstructorInfo[] constructors = info.getConstructors();
|
||||||
|
if (constructors.length > 0) {
|
||||||
|
sb.append("## constructors:\n");
|
||||||
|
for (MBeanConstructorInfo constructor : constructors) {
|
||||||
|
|
||||||
|
String ctorDesc = constructor.getDescription();
|
||||||
|
sb.append("# ").append(ctorDesc).append("\n");
|
||||||
|
|
||||||
|
String name = constructor.getName();
|
||||||
|
sb.append("# ").append(name).append("(");
|
||||||
|
sb.append(pramDetail(constructor.getSignature(), " "));
|
||||||
|
sb.append(" )\n");
|
||||||
|
// sb.append(" [").append(descriptorDetail(constructor.getDescriptor())).append("]\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MBeanAttributeInfo[] attributes = info.getAttributes();
|
||||||
|
if (attributes.length > 0) {
|
||||||
|
sb.append("## attributes:\n");
|
||||||
|
|
||||||
|
for (MBeanAttributeInfo attribute : attributes) {
|
||||||
|
String attrDesc = attribute.getDescription();
|
||||||
|
String attrName = attribute.getName();
|
||||||
|
String attrType = attribute.getType();
|
||||||
|
sb.append("# ").append(attrDesc).append("\n");
|
||||||
|
sb.append("- '").append(attrName).append("' type=").append(attrType);
|
||||||
|
sb.append("readable=").append(attribute.isReadable()).append(" writable=").append(attribute.isWritable()).append(" is_is=").append(attribute.isIs());
|
||||||
|
sb.append("\n");
|
||||||
|
// sb.append(" [").append(descriptorDetail(attribute.getDescriptor())).append("]\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MBeanNotificationInfo[] notifications = info.getNotifications();
|
||||||
|
if (notifications.length > 0) {
|
||||||
|
sb.append("## notifications:\n");
|
||||||
|
for (MBeanNotificationInfo notification : notifications) {
|
||||||
|
String notifName = notification.getName();
|
||||||
|
String notifDesc = notification.getDescription();
|
||||||
|
String[] notifTypes = notification.getNotifTypes();
|
||||||
|
Class<? extends MBeanNotificationInfo> notifClass = notification.getClass();
|
||||||
|
sb.append("# ").append(notifDesc).append("\n");
|
||||||
|
sb.append("- ").append(notifName).append(" [").append(descriptorDetail(notification.getDescriptor())).append("]\n");
|
||||||
|
|
||||||
|
if (notifTypes.length > 0) {
|
||||||
|
for (String notifType : notifTypes) {
|
||||||
|
sb.append(" - ").append(notifType).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MBeanOperationInfo[] operations = info.getOperations();
|
||||||
|
if (operations.length > 0) {
|
||||||
|
sb.append("## operations:\n");
|
||||||
|
for (MBeanOperationInfo operation : operations) {
|
||||||
|
String opDesc = operation.getDescription();
|
||||||
|
String opName = operation.getName();
|
||||||
|
MBeanParameterInfo[] opSig = operation.getSignature();
|
||||||
|
Class<? extends MBeanOperationInfo> opClass = operation.getClass();
|
||||||
|
|
||||||
|
sb.append("# ").append(opDesc).append("\n");
|
||||||
|
sb.append("- ").append(opName).append("(");
|
||||||
|
sb.append(pramDetail(operation.getSignature(), " "));
|
||||||
|
sb.append(") -> ").append(operation.getReturnType());
|
||||||
|
sb.append(" impact=").append(MbeanOpImpacts.get(operation.getImpact())).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String descriptorDetail(Descriptor descriptor) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("valid=").append(descriptor.isValid());
|
||||||
|
String[] fieldNames = descriptor.getFieldNames();
|
||||||
|
for (String field : fieldNames) {
|
||||||
|
sb.append(" ").append(field).append("=").append(descriptor.getFieldValue(field));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String pramDetail(MBeanParameterInfo[] signature, String prefix) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
for (MBeanParameterInfo paramInfo : signature) {
|
||||||
|
String desc = paramInfo.getDescription();
|
||||||
|
if (desc != null) {
|
||||||
|
sb.append(prefix).append(" # ").append(desc).append("\n");
|
||||||
|
}
|
||||||
|
sb.append(prefix).append(" - ").append(paramInfo.getName()).append("\n");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package io.nosqlbench.driver.jmx.ops;
|
||||||
|
|
||||||
|
import io.nosqlbench.driver.jmx.formats.MBeanInfoConsoleFormat;
|
||||||
|
|
||||||
|
import javax.management.*;
|
||||||
|
import javax.management.remote.JMXConnector;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class JMXExplainOperation extends JmxOp {
|
||||||
|
public JMXExplainOperation(JMXConnector connector, ObjectName objectName) {
|
||||||
|
super(connector,objectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
MBeanServerConnection bean = getMBeanConnection();
|
||||||
|
try {
|
||||||
|
MBeanInfo info = bean.getMBeanInfo(objectName);
|
||||||
|
String mbeanInfoText = MBeanInfoConsoleFormat.formatAsText(info, objectName);
|
||||||
|
System.out.println(mbeanInfoText);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package io.nosqlbench.driver.jmx.ops;
|
||||||
|
|
||||||
|
import io.nosqlbench.driver.jmx.ValueConverter;
|
||||||
|
import io.nosqlbench.virtdata.library.basics.core.threadstate.SharedState;
|
||||||
|
import org.apache.commons.math4.analysis.function.Exp;
|
||||||
|
|
||||||
|
import javax.management.*;
|
||||||
|
import javax.management.remote.JMXConnector;
|
||||||
|
import javax.management.remote.JMXServiceURL;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class JMXReadOperation extends JmxOp {
|
||||||
|
private final String attribute;
|
||||||
|
private final String asType;
|
||||||
|
private final String asName;
|
||||||
|
|
||||||
|
public JMXReadOperation(JMXConnector connector, ObjectName objectName, String attribute, String asType, String asName) {
|
||||||
|
super(connector, objectName);
|
||||||
|
this.attribute = attribute;
|
||||||
|
this.asType = asType;
|
||||||
|
this.asName = asName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
try {
|
||||||
|
Object value = getMBeanConnection().getAttribute(objectName, this.attribute);
|
||||||
|
logger.trace("read attribute '" + value +"': " + value);
|
||||||
|
|
||||||
|
if (asType!=null) {
|
||||||
|
value = ValueConverter.convert(asType,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
String storedName = (asName==null) ? attribute : asName;
|
||||||
|
SharedState.tl_ObjectMap.get().put(storedName,value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package io.nosqlbench.driver.jmx.ops;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.management.MBeanServerConnection;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
import javax.management.remote.JMXConnector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All JMX Operations should built on this base type.
|
||||||
|
*/
|
||||||
|
public abstract class JmxOp {
|
||||||
|
|
||||||
|
protected final static Logger logger = LoggerFactory.getLogger(JmxOp.class);
|
||||||
|
|
||||||
|
protected JMXConnector connector;
|
||||||
|
protected ObjectName objectName;
|
||||||
|
|
||||||
|
public JmxOp(JMXConnector connector, ObjectName objectName) {
|
||||||
|
this.connector = connector;
|
||||||
|
this.objectName = objectName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MBeanServerConnection getMBeanConnection() {
|
||||||
|
MBeanServerConnection connection = null;
|
||||||
|
try {
|
||||||
|
connection = connector.getMBeanServerConnection();
|
||||||
|
return connection;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void execute();
|
||||||
|
}
|
71
driver-jmx/src/main/resources/jmx.md
Normal file
71
driver-jmx/src/main/resources/jmx.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# JMX Driver
|
||||||
|
|
||||||
|
The JMX Driver allows you to do various JMX operations against a JMX service URL
|
||||||
|
and object name.
|
||||||
|
|
||||||
|
You must specify the service URL and object name in the op template. Alternately, you can specify
|
||||||
|
the protocol, host, port and path. Each cycle, the full JMX operation is derived from the
|
||||||
|
op template, and executed.
|
||||||
|
|
||||||
|
In the first version of this driver, only reads are supported.
|
||||||
|
|
||||||
|
# Connection Options
|
||||||
|
|
||||||
|
JMX transports can be configured in a myriad of ways. The options below allow you to add
|
||||||
|
connection options such as SSL and authentication.
|
||||||
|
|
||||||
|
- **ssl** - Use SSL settings provided. Thes SSL settings are from the NoSQLBench standard
|
||||||
|
SSL support
|
||||||
|
|
||||||
|
# Example Operations
|
||||||
|
|
||||||
|
## readvar
|
||||||
|
|
||||||
|
The readvar operation is used to read a named attribute of the named object and store it in the
|
||||||
|
thread local variable map.
|
||||||
|
|
||||||
|
```
|
||||||
|
statements:
|
||||||
|
- read1:
|
||||||
|
url: service:jmx:rmi:///jndi/rmi://dsehost:7199/jmxrmi
|
||||||
|
object: org.apache.cassandra.metrics:type=Compaction,name=PendingTasks
|
||||||
|
readvar: Value
|
||||||
|
as_type: int
|
||||||
|
as_name: pending_tasks
|
||||||
|
```
|
||||||
|
|
||||||
|
The `as_type` and `as_name` are optional, and if provided will set the name and data type used in
|
||||||
|
the thread local variable map.
|
||||||
|
|
||||||
|
- *as_type* can be any of long, int, double, float, byte, short, or String. If the original type
|
||||||
|
is convertable to a number, then it will be converted to a number and then to the desired type. If it
|
||||||
|
is not, it will be converted to String form first and then to the desired type. If the type name
|
||||||
|
contains dots, as in a fully-qualified class name, then direct class casting will be used if the
|
||||||
|
types are compatible.
|
||||||
|
|
||||||
|
A combined format is available if you don't want to put every command property on a separate line.
|
||||||
|
In this format, the first entry in the command map is taken as the command name and a set of key=value
|
||||||
|
command arguments. It is semantically equivalent to the above example, only more compact.
|
||||||
|
|
||||||
|
```
|
||||||
|
statements:
|
||||||
|
- read1: readvar=Value as_type=int as_name=pending_tasks
|
||||||
|
url: service:jmx:rmi:///jndi/rmi://dsehost:7199/jmxrmi
|
||||||
|
object: org.apache.cassandra.metrics:type=Compaction,name=PendingTasks
|
||||||
|
```
|
||||||
|
|
||||||
|
## explain
|
||||||
|
|
||||||
|
If you want to see the details about a managed object, you can use the explain command:
|
||||||
|
|
||||||
|
```
|
||||||
|
statements:
|
||||||
|
- explain1:
|
||||||
|
url: service:jmx:rmi:///jndi/rmi://dsehost:7199/jmxrmi
|
||||||
|
object: org.apache.cassandra.metrics:type=Compaction,name=PendingTasks
|
||||||
|
explain: object
|
||||||
|
```
|
||||||
|
|
||||||
|
This will use the MBeanInfo to interrogate the named management bean and provide a summary
|
||||||
|
of it's available attriburtes, operations, notifications, and constructors to stdout.
|
||||||
|
This is not meant for bulk testing, but more for explaining and documenting JMX beans.
|
@ -0,0 +1,15 @@
|
|||||||
|
package io.nosqlbench.driver.jmx;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
public class ValueConverterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConvertStringDouble() {
|
||||||
|
String s = "3";
|
||||||
|
double d = (double) ValueConverter.convert("double", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
driver-jmx/src/test/resources/activities/jmx-test-1.yaml
Normal file
10
driver-jmx/src/test/resources/activities/jmx-test-1.yaml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# (src/test/resources/activities/) jmx-test-1.yaml
|
||||||
|
statements:
|
||||||
|
- read1:
|
||||||
|
url: service:jmx:rmi:///jndi/rmi://dsehost:7199/jmxrmi
|
||||||
|
object: org.apache.cassandra.metrics:type=Compaction,name=PendingTasks
|
||||||
|
readvar: Value
|
||||||
|
as_type: int
|
||||||
|
as_name: pending_tasks
|
||||||
|
|
||||||
|
|
8
driver-jmx/src/test/resources/activities/jmx-test-2.yaml
Normal file
8
driver-jmx/src/test/resources/activities/jmx-test-2.yaml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# (src/test/resources/activities/) jmx-test-2.yaml
|
||||||
|
statements:
|
||||||
|
- explain1:
|
||||||
|
url: service:jmx:rmi:///jndi/rmi://dsehost:7199/jmxrmi
|
||||||
|
object: org.apache.cassandra.metrics:type=Compaction,name=PendingTasks
|
||||||
|
explain: object
|
||||||
|
|
||||||
|
|
4
driver-jmx/src/test/resources/activities/jmx-test-3.yaml
Normal file
4
driver-jmx/src/test/resources/activities/jmx-test-3.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
statements:
|
||||||
|
- read1: readvar=Value as_type=int as_name=pending_tasks
|
||||||
|
url: service:jmx:rmi:///jndi/rmi://dsehost:7199/jmxrmi
|
||||||
|
object: org.apache.cassandra.metrics:type=Compaction,name=PendingTasks
|
@ -86,6 +86,12 @@
|
|||||||
<version>3.12.129-SNAPSHOT</version>
|
<version>3.12.129-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.nosqlbench</groupId>
|
||||||
|
<artifactId>driver-jmx</artifactId>
|
||||||
|
<version>3.12.129-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.nosqlbench</groupId>
|
<groupId>io.nosqlbench</groupId>
|
||||||
<artifactId>driver-cql-shaded</artifactId>
|
<artifactId>driver-cql-shaded</artifactId>
|
||||||
|
Loading…
Reference in New Issue
Block a user