mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
rewrite JMX as a driver adapter
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.adapter.jmx;
|
||||
|
||||
import io.nosqlbench.adapter.jmx.mappers.JMXOpMapper;
|
||||
import io.nosqlbench.engine.api.activityimpl.OpMapper;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.DriverSpaceCache;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op;
|
||||
import io.nosqlbench.nb.annotations.Service;
|
||||
import io.nosqlbench.nb.api.config.standard.NBConfigModel;
|
||||
import io.nosqlbench.nb.api.config.standard.NBConfigurable;
|
||||
import io.nosqlbench.nb.api.config.standard.NBConfiguration;
|
||||
|
||||
@Service(value = DriverAdapter.class, selector = "jmx-v2")
|
||||
public class JMXDriverAdapter implements DriverAdapter<Op,JMXSpace>, NBConfigurable {
|
||||
|
||||
private NBConfiguration config;
|
||||
|
||||
@Override
|
||||
public OpMapper<Op> getOpMapper() {
|
||||
return new JMXOpMapper(getSpaceCache());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DriverSpaceCache<? extends JMXSpace> getSpaceCache() {
|
||||
return new DriverSpaceCache<>(JMXSpace::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBConfiguration getConfiguration() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyConfig(NBConfiguration cfg) {
|
||||
this.config = cfg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBConfigModel getConfigModel() {
|
||||
return new JMXSpace("test").getConfigModel();
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.adapter.jmx;
|
||||
|
||||
public enum JMXOpTypes {
|
||||
Read,
|
||||
Print,
|
||||
Explain
|
||||
}
|
113
driver-jmx/src/main/java/io/nosqlbench/adapter/jmx/JMXSpace.java
Normal file
113
driver-jmx/src/main/java/io/nosqlbench/adapter/jmx/JMXSpace.java
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.adapter.jmx;
|
||||
|
||||
import io.nosqlbench.engine.api.util.SSLKsFactory;
|
||||
import io.nosqlbench.nb.api.config.standard.*;
|
||||
import io.nosqlbench.nb.api.errors.OpConfigError;
|
||||
|
||||
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.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class JMXSpace implements NBConfigurable {
|
||||
private final String name;
|
||||
private JMXConnector connector;
|
||||
private NBConfiguration cfg;
|
||||
|
||||
public JMXSpace(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyConfig(NBConfiguration cfg) {
|
||||
this.cfg = cfg;
|
||||
}
|
||||
|
||||
public NBConfigModel getConfigModel() {
|
||||
return ConfigModel.of(JMXSpace.class)
|
||||
.add(Param.optional("username", String.class))
|
||||
.add(Param.optional("password", String.class))
|
||||
.add(SSLKsFactory.get().getConfigModel())
|
||||
.asReadOnly();
|
||||
}
|
||||
|
||||
public synchronized JMXConnector getConnector() {
|
||||
if (this.connector == null) {
|
||||
this.connector = bindConnector();
|
||||
}
|
||||
return this.connector;
|
||||
}
|
||||
|
||||
private JMXConnector bindConnector() {
|
||||
|
||||
Map<String, Object> connectorEnv = new HashMap<>();
|
||||
|
||||
String username = cfg.getOptional("username")
|
||||
.map(u -> SecureUtils.readSecret("JMX username", u))
|
||||
.orElse(null);
|
||||
|
||||
String password = cfg.getOptional("password")
|
||||
.map(p -> SecureUtils.readSecret("JMX password", p))
|
||||
.orElse(null);
|
||||
|
||||
if (username != null && password != null) {
|
||||
connectorEnv.put(JMXConnector.CREDENTIALS, new String[]{username, password});
|
||||
}
|
||||
|
||||
JMXConnector connector = null;
|
||||
try {
|
||||
JMXServiceURL url = bindJMXServiceURL();
|
||||
connector = JMXConnectorFactory.connect(url, connectorEnv);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return connector;
|
||||
}
|
||||
|
||||
private JMXServiceURL bindJMXServiceURL() {
|
||||
JMXServiceURL url = null;
|
||||
url = cfg.getOptional("url")
|
||||
.map(
|
||||
u -> {
|
||||
try {
|
||||
return new JMXServiceURL(u);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new OpConfigError("Error with JMX URL: " + e);
|
||||
}
|
||||
})
|
||||
.orElse(null);
|
||||
if (url!=null) {
|
||||
return url;
|
||||
}
|
||||
|
||||
String host = cfg.get("host");
|
||||
String protocol = cfg.get("protocol");
|
||||
int port = cfg.getOrDefault("port", 0);
|
||||
String path = cfg.get("path");
|
||||
try {
|
||||
return new JMXServiceURL(protocol, host, port, path);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new OpConfigError("Error with JMX URL parameters: " + e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.driver.jmx;
|
||||
package io.nosqlbench.adapter.jmx;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
@@ -14,9 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.driver.jmx;
|
||||
|
||||
import java.util.function.Function;
|
||||
package io.nosqlbench.adapter.jmx;
|
||||
|
||||
public class ValueConverter {
|
||||
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.adapter.jmx.dispensers;
|
||||
|
||||
import io.nosqlbench.adapter.jmx.JMXSpace;
|
||||
import io.nosqlbench.adapter.jmx.operations.JMXExplainOperation;
|
||||
import io.nosqlbench.engine.api.activityimpl.BaseOpDispenser;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op;
|
||||
import io.nosqlbench.engine.api.templating.ParsedOp;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
public class JMXExplainDispenser extends BaseOpDispenser<Op> {
|
||||
private final LongFunction<JMXSpace> spaceF;
|
||||
private final LongFunction<ObjectName> nameF;
|
||||
|
||||
public JMXExplainDispenser(LongFunction<JMXSpace> spaceF, LongFunction<ObjectName> nameF, ParsedOp op) {
|
||||
super(op);
|
||||
this.spaceF =spaceF;
|
||||
this.nameF = nameF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Op apply(long value) {
|
||||
return new JMXExplainOperation(
|
||||
spaceF.apply(value).getConnector(),
|
||||
nameF.apply(value)
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.adapter.jmx.dispensers;
|
||||
|
||||
import io.nosqlbench.adapter.jmx.JMXSpace;
|
||||
import io.nosqlbench.adapter.jmx.operations.JMXPrintOperation;
|
||||
import io.nosqlbench.engine.api.activityimpl.BaseOpDispenser;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op;
|
||||
import io.nosqlbench.engine.api.templating.ParsedOp;
|
||||
import io.nosqlbench.virtdata.library.basics.core.threadstate.SharedState;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
public class JMXPrintDispenser extends BaseOpDispenser<Op> {
|
||||
private final LongFunction<JMXSpace> spaceF;
|
||||
private final LongFunction<ObjectName> nameF;
|
||||
private final LongFunction<String> readvarF;
|
||||
private final LongFunction<String> asTypeF;
|
||||
private final LongFunction<String> asNameF;
|
||||
private final LongFunction<SharedState.Scope> scopeF;
|
||||
|
||||
public JMXPrintDispenser(LongFunction<JMXSpace> spaceF, LongFunction<ObjectName> nameF, ParsedOp op) {
|
||||
super(op);
|
||||
this.spaceF =spaceF;
|
||||
this.nameF = nameF;
|
||||
this.readvarF = op.getAsFunctionOr("readvar","Value");
|
||||
this.asTypeF = op.getAsFunctionOr("as_type","String");
|
||||
this.asNameF = op.getAsOptionalFunction("as_name", String.class).orElse(readvarF);
|
||||
this.scopeF = op.getAsOptionalEnumFunction("scope", SharedState.Scope.class).orElse(l -> SharedState.Scope.thread);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Op apply(long value) {
|
||||
return new JMXPrintOperation(
|
||||
spaceF.apply(value),
|
||||
nameF.apply(value),
|
||||
readvarF.apply(value),
|
||||
asTypeF.apply(value),
|
||||
asNameF.apply(value),
|
||||
scopeF.apply(value)
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.adapter.jmx.dispensers;
|
||||
|
||||
import io.nosqlbench.adapter.jmx.JMXSpace;
|
||||
import io.nosqlbench.adapter.jmx.operations.JMXReadOperation;
|
||||
import io.nosqlbench.engine.api.activityimpl.BaseOpDispenser;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op;
|
||||
import io.nosqlbench.engine.api.templating.ParsedOp;
|
||||
import io.nosqlbench.virtdata.library.basics.core.threadstate.SharedState;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
public class JMXReadDispenser extends BaseOpDispenser<Op> {
|
||||
private final LongFunction<JMXSpace> spaceF;
|
||||
private final LongFunction<ObjectName> nameF;
|
||||
private final LongFunction<String> readvarF;
|
||||
private final LongFunction<String> asTypeF;
|
||||
private final LongFunction<String> asNameF;
|
||||
private final LongFunction<SharedState.Scope> scopeF;
|
||||
|
||||
public JMXReadDispenser(LongFunction<JMXSpace> spaceF, LongFunction<ObjectName> nameF, ParsedOp op) {
|
||||
super(op);
|
||||
this.spaceF =spaceF;
|
||||
this.nameF = nameF;
|
||||
this.readvarF = op.getAsFunctionOr("readvar","Value");
|
||||
this.asTypeF = op.getAsFunctionOr("as_type","String");
|
||||
this.asNameF = op.getAsOptionalFunction("as_name", String.class).orElse(readvarF);
|
||||
this.scopeF = op.getAsOptionalEnumFunction("scope", SharedState.Scope.class).orElse(l -> SharedState.Scope.thread);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Op apply(long value) {
|
||||
return new JMXReadOperation(
|
||||
spaceF.apply(value),
|
||||
nameF.apply(value),
|
||||
readvarF.apply(value),
|
||||
asTypeF.apply(value),
|
||||
asNameF.apply(value),
|
||||
scopeF.apply(value)
|
||||
);
|
||||
}
|
||||
}
|
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.driver.jmx.formats;
|
||||
package io.nosqlbench.adapter.jmx.formats;
|
||||
|
||||
import javax.management.*;
|
||||
import java.util.Map;
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.adapter.jmx.mappers;
|
||||
|
||||
import io.nosqlbench.adapter.jmx.JMXOpTypes;
|
||||
import io.nosqlbench.adapter.jmx.JMXSpace;
|
||||
import io.nosqlbench.adapter.jmx.dispensers.JMXExplainDispenser;
|
||||
import io.nosqlbench.adapter.jmx.dispensers.JMXPrintDispenser;
|
||||
import io.nosqlbench.adapter.jmx.dispensers.JMXReadDispenser;
|
||||
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
|
||||
import io.nosqlbench.engine.api.activityimpl.OpMapper;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.DriverSpaceCache;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op;
|
||||
import io.nosqlbench.engine.api.templating.ParsedOp;
|
||||
import io.nosqlbench.engine.api.templating.TypeAndTarget;
|
||||
import io.nosqlbench.nb.api.errors.OpConfigError;
|
||||
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
public class JMXOpMapper implements OpMapper<Op> {
|
||||
|
||||
private final DriverSpaceCache<? extends JMXSpace> jmxCache;
|
||||
|
||||
public JMXOpMapper(DriverSpaceCache<? extends JMXSpace> jmxCache) {
|
||||
this.jmxCache = jmxCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpDispenser<? extends Op> apply(ParsedOp op) {
|
||||
|
||||
LongFunction<String> spaceNameFunc = op.getAsFunctionOr("space","default");
|
||||
LongFunction<JMXSpace> spaceFunc = l -> jmxCache.get(spaceNameFunc.apply(l));
|
||||
|
||||
LongFunction<? extends String> nameFunction = op.getAsRequiredFunction("object");
|
||||
LongFunction<ObjectName> oNameFunc = n -> {
|
||||
try {
|
||||
String name = nameFunction.apply(n);
|
||||
return new ObjectName(name);
|
||||
} catch (MalformedObjectNameException e) {
|
||||
throw new OpConfigError("You must specify a valid object name for any JMX operation:" + e);
|
||||
}
|
||||
};
|
||||
|
||||
TypeAndTarget<JMXOpTypes, String> optype = op.getTypeAndTarget(JMXOpTypes.class, String.class, "type", "target");
|
||||
return switch (optype.enumId) {
|
||||
case Read -> new JMXReadDispenser(spaceFunc, oNameFunc, op);
|
||||
case Print -> new JMXPrintDispenser(spaceFunc, oNameFunc, op);
|
||||
case Explain -> new JMXExplainDispenser(spaceFunc, oNameFunc, op);
|
||||
};
|
||||
}
|
||||
}
|
@@ -14,13 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.driver.jmx.ops;
|
||||
package io.nosqlbench.adapter.jmx.operations;
|
||||
|
||||
import io.nosqlbench.driver.jmx.formats.MBeanInfoConsoleFormat;
|
||||
import io.nosqlbench.adapter.jmx.formats.MBeanInfoConsoleFormat;
|
||||
|
||||
import javax.management.*;
|
||||
import javax.management.remote.JMXConnector;
|
||||
import java.io.IOException;
|
||||
|
||||
public class JMXExplainOperation extends JmxOp {
|
||||
public final static String EXPLAIN = "explain";
|
@@ -14,33 +14,38 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.driver.jmx.ops;
|
||||
package io.nosqlbench.adapter.jmx.operations;
|
||||
|
||||
import io.nosqlbench.driver.jmx.ValueConverter;
|
||||
import io.nosqlbench.adapter.jmx.JMXSpace;
|
||||
import io.nosqlbench.adapter.jmx.ValueConverter;
|
||||
import io.nosqlbench.virtdata.library.basics.core.threadstate.SharedState;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.remote.JMXConnector;
|
||||
import java.util.Map;
|
||||
|
||||
public class JMXPrintOperation extends JMXReadOperation {
|
||||
public static final String PRINTVAR = "printvar";
|
||||
|
||||
public JMXPrintOperation(JMXConnector connector, ObjectName objectName, String attribute, Map<String, String> cfg) {
|
||||
super(connector, objectName, attribute, cfg);
|
||||
public JMXPrintOperation(
|
||||
JMXSpace space,
|
||||
ObjectName oname,
|
||||
String readvar,
|
||||
String asType,
|
||||
String asName,
|
||||
SharedState.Scope scope
|
||||
) {
|
||||
super(space, oname, readvar, asType, asName, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Object value = readObject(attribute);
|
||||
System.out.println("# read JMX attribute '" + attribute + "' as " + value.getClass() +
|
||||
Object value = readObject(readvar);
|
||||
System.out.println("# read JMX attribute '" + readvar + "' as " + value.getClass() +
|
||||
((asType != null) ? " as_type=" + asType : "") +
|
||||
((asName != null) ? " as_name=" + asName : ""));
|
||||
|
||||
if (asType != null) {
|
||||
value = ValueConverter.convert(asType, value);
|
||||
}
|
||||
String storedName = (asName == null) ? attribute : asName;
|
||||
String storedName = (asName == null) ? readvar : asName;
|
||||
|
||||
System.out.println(storedName + "=" + value + "\n");
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.adapter.jmx.operations;
|
||||
|
||||
import io.nosqlbench.adapter.jmx.JMXSpace;
|
||||
import io.nosqlbench.adapter.jmx.ValueConverter;
|
||||
import io.nosqlbench.virtdata.library.basics.core.threadstate.SharedState;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
public class JMXReadOperation extends JmxOp {
|
||||
|
||||
protected final String readvar;
|
||||
protected final String asType;
|
||||
protected final String asName;
|
||||
protected final SharedState.Scope scope;
|
||||
|
||||
public JMXReadOperation(
|
||||
JMXSpace space,
|
||||
ObjectName oname,
|
||||
String readvar,
|
||||
String asType,
|
||||
String asName,
|
||||
SharedState.Scope scope
|
||||
) {
|
||||
super(space.getConnector(), oname);
|
||||
this.readvar = readvar;
|
||||
this.asType = asType;
|
||||
this.asName = asName;
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Object value = readObject(readvar);
|
||||
value = ValueConverter.convert(asType, value);
|
||||
String storedName = asName;
|
||||
SharedState.put(scope, storedName, value);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.nosqlbench.driver.jmx.ops;
|
||||
package io.nosqlbench.adapter.jmx.operations;
|
||||
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op;
|
||||
import org.apache.logging.log4j.LogManager;
|
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 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 io.nosqlbench.engine.api.activityimpl.OpDispenser;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
public class JMXAction implements SyncAction {
|
||||
|
||||
private final static Logger logger = LogManager.getLogger(JMXAction.class);
|
||||
|
||||
private final ActivityDef activityDef;
|
||||
private final int slot;
|
||||
private final JMXActivity activity;
|
||||
private OpSequence<OpDispenser<? extends JmxOp>> 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 cycle) {
|
||||
LongFunction<? extends JmxOp> readyJmxOp = sequencer.apply(cycle);
|
||||
JmxOp jmxOp = readyJmxOp.apply(cycle);
|
||||
jmxOp.execute();
|
||||
return 0;
|
||||
}
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.driver.jmx;
|
||||
|
||||
import io.nosqlbench.driver.jmx.ops.JmxOp;
|
||||
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.OpDispenser;
|
||||
import io.nosqlbench.engine.api.activityimpl.SimpleActivity;
|
||||
import io.nosqlbench.engine.api.util.SSLKsFactory;
|
||||
import io.nosqlbench.nb.api.config.standard.NBConfiguration;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
public class JMXActivity extends SimpleActivity implements Activity {
|
||||
|
||||
private OpSequence<OpDispenser<? extends JmxOp>> sequence;
|
||||
private SSLContext sslContext;
|
||||
|
||||
public JMXActivity(ActivityDef activityDef) {
|
||||
super(activityDef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initActivity() {
|
||||
super.initActivity();
|
||||
this.sequence = createOpSequenceFromCommands(ReadyJmxOp::new, false);
|
||||
setDefaultsFromOpSequence(sequence);
|
||||
NBConfiguration sslCfg = SSLKsFactory.get().getConfigModel().extractConfig(activityDef.getParams());
|
||||
this.sslContext= SSLKsFactory.get().getContext(sslCfg);
|
||||
|
||||
// TODO: Require qualified default with an op sequence as the input
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is null, then no SSL is requested.
|
||||
* @return The SSLContext for this activity
|
||||
*/
|
||||
public SSLContext getSslContext() {
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
public OpSequence<OpDispenser<? extends JmxOp>> getSequencer() {
|
||||
return sequence;
|
||||
}
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 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(value = ActivityType.class, selector = "jmx")
|
||||
public class JMXActivityType implements ActivityType<JMXActivity> {
|
||||
|
||||
@Override
|
||||
public JMXActivity getActivity(ActivityDef activityDef) {
|
||||
return new JMXActivity(activityDef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionDispenser getActionDispenser(JMXActivity activity) {
|
||||
return new JMXActionDispenser(activity);
|
||||
}
|
||||
}
|
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.driver.jmx;
|
||||
|
||||
import io.nosqlbench.driver.jmx.ops.JMXExplainOperation;
|
||||
import io.nosqlbench.driver.jmx.ops.JMXPrintOperation;
|
||||
import io.nosqlbench.driver.jmx.ops.JMXReadOperation;
|
||||
import io.nosqlbench.driver.jmx.ops.JmxOp;
|
||||
import io.nosqlbench.engine.api.activityimpl.BaseOpDispenser;
|
||||
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.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ReadyJmxOp extends BaseOpDispenser<JmxOp> {
|
||||
|
||||
private final CommandTemplate command;
|
||||
|
||||
public ReadyJmxOp(CommandTemplate command) {
|
||||
super(command);
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public JmxOp apply(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(JMXReadOperation.READVAR)) {
|
||||
return new JMXReadOperation(connector, objectName, cmdmap.get(JMXReadOperation.READVAR), cmdmap);
|
||||
} else if (cmdmap.containsKey(JMXPrintOperation.PRINTVAR)) {
|
||||
return new JMXPrintOperation(connector, objectName, cmdmap.get(JMXPrintOperation.PRINTVAR), cmdmap);
|
||||
} else if (cmdmap.containsKey(JMXExplainOperation.EXPLAIN)) {
|
||||
return new JMXExplainOperation(connector, objectName);
|
||||
}
|
||||
|
||||
throw new RuntimeException("No valid form of JMX operation was determined from the provided command details:" + cmdmap);
|
||||
}
|
||||
|
||||
private JMXConnector bindConnector(Map<String, String> cmdmap) {
|
||||
|
||||
Map<String, Object> connectorEnv = new HashMap<>();
|
||||
String username = cmdmap.remove("username");
|
||||
String password = cmdmap.remove("password");
|
||||
username = SecureUtils.readSecret("JMX username", username);
|
||||
password = SecureUtils.readSecret("JMX password", password);
|
||||
if (username != null && password != null) {
|
||||
connectorEnv.put(JMXConnector.CREDENTIALS, new String[]{username, password});
|
||||
}
|
||||
|
||||
JMXConnector connector = null;
|
||||
try {
|
||||
JMXServiceURL url = bindJMXServiceURL(cmdmap);
|
||||
connector = JMXConnectorFactory.connect(url, connectorEnv);
|
||||
} 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;
|
||||
}
|
||||
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.driver.jmx.ops;
|
||||
|
||||
import io.nosqlbench.driver.jmx.ValueConverter;
|
||||
import io.nosqlbench.virtdata.library.basics.core.threadstate.SharedState;
|
||||
|
||||
import javax.management.*;
|
||||
import javax.management.remote.JMXConnector;
|
||||
import java.util.Map;
|
||||
|
||||
public class JMXReadOperation extends JmxOp {
|
||||
public final static String READVAR = "readvar";
|
||||
public final static String AS_TYPE = "as_type";
|
||||
public final static String AS_NAME = "as_name";
|
||||
public final static String SCOPE = "scope";
|
||||
|
||||
protected final String attribute;
|
||||
protected final String asType;
|
||||
protected final String asName;
|
||||
protected final SharedState.Scope scope;
|
||||
|
||||
public JMXReadOperation(JMXConnector connector, ObjectName objectName, String attribute, Map<String, String> cfg) {
|
||||
super(connector, objectName);
|
||||
this.attribute = attribute;
|
||||
this.asType = cfg.remove(AS_TYPE);
|
||||
this.asName = cfg.remove(AS_NAME);
|
||||
|
||||
String scopeName = cfg.remove(SCOPE);
|
||||
if (scopeName != null) {
|
||||
scope = SharedState.Scope.valueOf(scopeName);
|
||||
} else {
|
||||
scope = SharedState.Scope.process;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Object value = readObject(attribute);
|
||||
|
||||
if (asType != null) {
|
||||
value = ValueConverter.convert(asType, value);
|
||||
}
|
||||
|
||||
String storedName = (asName == null) ? attribute : asName;
|
||||
|
||||
switch (scope) {
|
||||
case process:
|
||||
SharedState.gl_ObjectMap.put(storedName, value);
|
||||
break;
|
||||
case thread:
|
||||
SharedState.tl_ObjectMap.get().put(storedName, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -16,18 +16,7 @@
|
||||
|
||||
package io.nosqlbench.driver.jmx;
|
||||
|
||||
import io.nosqlbench.engine.api.activityapi.core.Action;
|
||||
import io.nosqlbench.engine.api.activityapi.core.ActionDispenser;
|
||||
import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.Op;
|
||||
|
||||
public class JMXActionDispenser implements ActionDispenser {
|
||||
private final JMXActivity activity;
|
||||
|
||||
public JMXActionDispenser(JMXActivity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action getAction(int slot) {
|
||||
return new JMXAction(activity.getActivityDef(),slot,activity);
|
||||
}
|
||||
public class BaseJMXOp implements Op {
|
||||
}
|
122
driver-jmx/src/test/java/io/nosqlbench/driver/jmx/JMXSpace.java
Normal file
122
driver-jmx/src/test/java/io/nosqlbench/driver/jmx/JMXSpace.java
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2022 nosqlbench
|
||||
*
|
||||
* 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 io.nosqlbench.driver.jmx;
|
||||
|
||||
import io.nosqlbench.adapter.jmx.SecureUtils;
|
||||
import io.nosqlbench.engine.api.util.SSLKsFactory;
|
||||
import io.nosqlbench.nb.api.config.standard.*;
|
||||
import io.nosqlbench.nb.api.errors.OpConfigError;
|
||||
|
||||
import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXConnectorFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class JMXSpace implements NBConfigurable {
|
||||
private final String name;
|
||||
private NBConfiguration config;
|
||||
private SSLContext sslContext;
|
||||
private JMXConnector connector;
|
||||
|
||||
public JMXSpace(String name, NBConfiguration config) {
|
||||
this.name = name;
|
||||
this.config = config;
|
||||
|
||||
SSLKsFactory.get().getContext(config);
|
||||
}
|
||||
|
||||
public synchronized JMXConnector getConnector() {
|
||||
if (this.connector == null) {
|
||||
this.connector = bindConnector();
|
||||
}
|
||||
return this.connector;
|
||||
}
|
||||
|
||||
private JMXConnector bindConnector() {
|
||||
|
||||
Map<String, Object> connectorEnv = new HashMap<>();
|
||||
String username = config.get("username", String.class);
|
||||
String password = config.get("password", String.class);
|
||||
username = SecureUtils.readSecret("JMX username", username);
|
||||
password = SecureUtils.readSecret("JMX password", password);
|
||||
if (username != null && password != null) {
|
||||
connectorEnv.put(JMXConnector.CREDENTIALS, new String[]{username, password});
|
||||
}
|
||||
|
||||
JMXConnector connector = null;
|
||||
try {
|
||||
JMXServiceURL url = bindJMXServiceURL();
|
||||
connector = JMXConnectorFactory.connect(url, connectorEnv);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return connector;
|
||||
}
|
||||
|
||||
private JMXServiceURL bindJMXServiceURL() {
|
||||
JMXServiceURL url = null;
|
||||
try {
|
||||
url = config.getOptional("url")
|
||||
.map(u -> {
|
||||
try {
|
||||
return new JMXServiceURL(u);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new OpConfigError("Error while configuring JMX service URL: " + e.getMessage());
|
||||
}
|
||||
})
|
||||
.orElse(null);
|
||||
|
||||
if (url==null) {
|
||||
String host = config.get("host");
|
||||
String protocol = config.get("protocol");
|
||||
int port = config.get("port", Integer.class);
|
||||
String path = config.get("path");
|
||||
url = new JMXServiceURL(protocol, host, port, path);
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyConfig(NBConfiguration config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBConfigModel getConfigModel() {
|
||||
return ConfigModel.of(JMXSpace.class)
|
||||
.add(Param.optional("url"))
|
||||
.add(Param.optional("host"))
|
||||
.add(Param.optional("protocol"))
|
||||
.add(Param.optional("port",Integer.class))
|
||||
.add(Param.optional("path"))
|
||||
.add(Param.optional("username"))
|
||||
.add(Param.optional("password"))
|
||||
.add(SSLKsFactory.get().getConfigModel())
|
||||
.asReadOnly();
|
||||
}
|
||||
|
||||
// NBConfiguration sslCfg = SSLKsFactory.get().getConfigModel().extractConfig(activityDef.getParams());
|
||||
// this.sslContext= SSLKsFactory.get().getContext(sslCfg);
|
||||
|
||||
}
|
@@ -16,6 +16,7 @@
|
||||
|
||||
package io.nosqlbench.driver.jmx;
|
||||
|
||||
import io.nosqlbench.adapter.jmx.ValueConverter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
Reference in New Issue
Block a user