mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
provide a more condensed session identifier for metrics
This commit is contained in:
@@ -69,7 +69,7 @@ public class RawOpDef extends RawOpFields {
|
|||||||
Object op = map.remove(keyName);
|
Object op = map.remove(keyName);
|
||||||
if (op instanceof CharSequence s) {
|
if (op instanceof CharSequence s) {
|
||||||
if (!keyName.equals("stmt")) {
|
if (!keyName.equals("stmt")) {
|
||||||
logger.warn("Used implied stmt field under name '" + keyName + "'. You can just use 'stmt: ... "+ s +"' or the equivalent to avoid this warning.");
|
logger.info("Used implied stmt field under name '" + keyName + "'. You can just use 'stmt: ... "+ s +"' or the equivalent to avoid this warning.");
|
||||||
}
|
}
|
||||||
map.put("stmt",s.toString());
|
map.put("stmt",s.toString());
|
||||||
// setOp(new LinkedHashMap<String,Object>(Map.of("stmt",s.toString())));
|
// setOp(new LinkedHashMap<String,Object>(Map.of("stmt",s.toString())));
|
||||||
@@ -79,7 +79,7 @@ public class RawOpDef extends RawOpFields {
|
|||||||
}
|
}
|
||||||
if (found.size() > 1) {
|
if (found.size() > 1) {
|
||||||
throw new BasicError("You used " + found + " as an op name, but only one of these is allowed at a time.");
|
throw new BasicError("You used " + found + " as an op name, but only one of these is allowed at a time.");
|
||||||
} else if ((getName() == null || getName().isEmpty()) && op == null && map.size() > 0) {
|
} else if ((getName() == null || getName().isEmpty()) && op == null && !map.isEmpty()) {
|
||||||
Map.Entry<String, Object> first = map.entrySet().iterator().next();
|
Map.Entry<String, Object> first = map.entrySet().iterator().next();
|
||||||
setName(first.getKey());
|
setName(first.getKey());
|
||||||
setOp(first.getValue());
|
setOp(first.getValue());
|
||||||
@@ -90,7 +90,7 @@ public class RawOpDef extends RawOpFields {
|
|||||||
|
|
||||||
if (_op) {
|
if (_op) {
|
||||||
if (_params) {
|
if (_params) {
|
||||||
if (map.size() > 0) {
|
if (!map.isEmpty()) {
|
||||||
throw new OpConfigError("If you have scoped op and params, you may not have dangling fields. Op template named '" + this.getName() + "' is invalid. Move dangling params ("+ map.keySet() +") under another field.");
|
throw new OpConfigError("If you have scoped op and params, you may not have dangling fields. Op template named '" + this.getName() + "' is invalid. Move dangling params ("+ map.keySet() +") under another field.");
|
||||||
}
|
}
|
||||||
} else { // no params. Op was a scoped field and there are dangling fields, so assume they belong to params
|
} else { // no params. Op was a scoped field and there are dangling fields, so assume they belong to params
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
|||||||
|
|
||||||
private NBLabels labels;
|
private NBLabels labels;
|
||||||
private String sessionName;
|
private String sessionName;
|
||||||
|
private String sessionCode;
|
||||||
|
private long sessionTime;
|
||||||
|
|
||||||
public NBCLI(final String commandName) {
|
public NBCLI(final String commandName) {
|
||||||
this.commandName = commandName;
|
this.commandName = commandName;
|
||||||
@@ -153,10 +155,17 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
|||||||
// logger = LogManager.getLogger("NBCLI");
|
// logger = LogManager.getLogger("NBCLI");
|
||||||
|
|
||||||
NBCLI.loggerConfig.setConsoleLevel(NBLogLevel.ERROR);
|
NBCLI.loggerConfig.setConsoleLevel(NBLogLevel.ERROR);
|
||||||
|
this.sessionTime = System.currentTimeMillis();
|
||||||
final NBCLIOptions globalOptions = new NBCLIOptions(args, Mode.ParseGlobalsOnly);
|
final NBCLIOptions globalOptions = new NBCLIOptions(args, Mode.ParseGlobalsOnly);
|
||||||
this.labels=NBLabels.forKV("command",commandName).and(globalOptions.getLabelMap());
|
|
||||||
this.sessionName = SessionNamer.format(globalOptions.getSessionName());
|
this.sessionCode = SystemId.genSessionCode(sessionTime);
|
||||||
|
this.sessionName = SessionNamer.format(globalOptions.getSessionName(),sessionTime).replaceAll("SESSIONCODE",sessionCode);
|
||||||
|
this.labels = NBLabels.forKV("command", commandName, "appname", "nosqlbench")
|
||||||
|
.andInstances("node",SystemId.getNodeId())
|
||||||
|
.andInstances("nodeid",SystemId.getPackedNodeId())
|
||||||
|
// .andInstances("sesscode",sessionCode)
|
||||||
|
.andInstances("session",sessionName)
|
||||||
|
.and(globalOptions.getLabelMap());
|
||||||
|
|
||||||
NBCLI.loggerConfig
|
NBCLI.loggerConfig
|
||||||
.setSessionName(sessionName)
|
.setSessionName(sessionName)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 nosqlbench
|
* Copyright (c) 2022-2023 nosqlbench
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -23,6 +23,7 @@ import oshi.hardware.CentralProcessor;
|
|||||||
import oshi.hardware.HardwareAbstractionLayer;
|
import oshi.hardware.HardwareAbstractionLayer;
|
||||||
import oshi.hardware.NetworkIF;
|
import oshi.hardware.NetworkIF;
|
||||||
|
|
||||||
|
import java.net.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
@@ -36,32 +37,37 @@ public class SystemId {
|
|||||||
* when you are managing configuration or results for a set of systems which
|
* when you are managing configuration or results for a set of systems which
|
||||||
* share a common IP addressing scheme. This identifier should be stable as long
|
* share a common IP addressing scheme. This identifier should be stable as long
|
||||||
* as the node's addresses do not change.
|
* as the node's addresses do not change.
|
||||||
*
|
* <p>
|
||||||
* If you are needing an identifier for a node but wish to expose any address data,
|
* If you are needing an identifier for a node but do not with wish to expose any address data,
|
||||||
* you can use the {@link #getNodeFingerprint()} which takes this value and hashes
|
* you can use the {@link #getNodeFingerprint()} which takes this value and hashes
|
||||||
* it with SHA-1 to produce a hex string.
|
* it with SHA-1 to produce a hex string.
|
||||||
|
*
|
||||||
* @return A address for the node, likely to be unique and stable for its lifetime
|
* @return A address for the node, likely to be unique and stable for its lifetime
|
||||||
*/
|
*/
|
||||||
public static String getNodeId() {
|
public static String getNodeId() {
|
||||||
|
return getMainInetAddrDirect().map(InetAddress::getHostAddress).orElse("UNKNOWN_HOST_ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getNodeIdOSHI() {
|
||||||
SystemInfo sysinfo = new SystemInfo();
|
SystemInfo sysinfo = new SystemInfo();
|
||||||
HardwareAbstractionLayer hal = sysinfo.getHardware();
|
HardwareAbstractionLayer hal = sysinfo.getHardware();
|
||||||
List<NetworkIF> interfaces = hal.getNetworkIFs();
|
List<NetworkIF> interfaces = hal.getNetworkIFs();
|
||||||
|
|
||||||
Optional<String> first = interfaces.stream()
|
Optional<String> first = interfaces.stream()
|
||||||
.filter(i -> !i.getName().startsWith("docker" ))
|
.filter(i -> !i.getName().startsWith("docker"))
|
||||||
.filter(i -> !i.getName().equals("lo" ))
|
.filter(i -> !i.getName().equals("lo"))
|
||||||
.sorted((o1, o2) -> {
|
.sorted((o1, o2) -> {
|
||||||
if (o1.getName().startsWith("e" ) && o2.getName().startsWith("e" )) {
|
if (o1.getName().startsWith("e") && o2.getName().startsWith("e")) {
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (o1.getName().startsWith("e" )) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (o2.getName().startsWith("e" )) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
})
|
}
|
||||||
|
if (o1.getName().startsWith("e")) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (o2.getName().startsWith("e")) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
.flatMap(iface -> Arrays.stream(iface.getIPv4addr().clone()))
|
.flatMap(iface -> Arrays.stream(iface.getIPv4addr().clone()))
|
||||||
.filter(addr -> !(addr.startsWith("127.")))
|
.filter(addr -> !(addr.startsWith("127.")))
|
||||||
.findFirst();
|
.findFirst();
|
||||||
@@ -69,10 +75,51 @@ public class SystemId {
|
|||||||
return systemID;
|
return systemID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Optional<InetAddress> getMainInetAddrDirect() {
|
||||||
|
List<NetworkInterface> ifaces = getInterfacesDirect();
|
||||||
|
Optional<NetworkInterface> first = ifaces.stream()
|
||||||
|
.filter(i -> !i.getName().startsWith("docker"))
|
||||||
|
.filter(i -> !i.getName().equals("lo"))
|
||||||
|
.sorted((o1, o2) -> {
|
||||||
|
if (o1.getName().startsWith("e") && o2.getName().startsWith("e")) return 0;
|
||||||
|
if (o1.getName().startsWith("e")) return -1;
|
||||||
|
if (o2.getName().startsWith("e")) return 1;
|
||||||
|
return 0;
|
||||||
|
}).findFirst();
|
||||||
|
if (first.isEmpty()) return Optional.empty();
|
||||||
|
|
||||||
|
Optional<InetAddress> firstInetAddrForInterface = first.get().getInterfaceAddresses().stream()
|
||||||
|
.map(ia -> ia.getAddress())
|
||||||
|
.sorted((i1, i2) -> {
|
||||||
|
if (i1 instanceof Inet4Address && i2 instanceof Inet4Address) return 0;
|
||||||
|
if (i1 instanceof Inet4Address) return -1;
|
||||||
|
if (i2 instanceof Inet4Address) return 1;
|
||||||
|
return 0;
|
||||||
|
}).findFirst();
|
||||||
|
return firstInetAddrForInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using this to bypass OSHI because it calls logger init before we want it.
|
||||||
|
* TODO: Maybe remove OSHI altogether if there is a reasonable Java HAL view in current Java editions.
|
||||||
|
*
|
||||||
|
* @return a list of network interfaces
|
||||||
|
*/
|
||||||
|
private static List<NetworkInterface> getInterfacesDirect() {
|
||||||
|
try {
|
||||||
|
Enumeration<NetworkInterface> ni = NetworkInterface.getNetworkInterfaces();
|
||||||
|
return new ArrayList<>(Collections.list(ni));
|
||||||
|
} catch (SocketException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a stable string identifier consisting of hexadecimal characters.
|
* Produce a stable string identifier consisting of hexadecimal characters.
|
||||||
* The internal data used for this value is based on a stable ordering of non-local
|
* The internal data used for this value is based on a stable ordering of non-local
|
||||||
* ip addresses available on the system.
|
* ip addresses available on the system.
|
||||||
|
*
|
||||||
* @return A stable node identifier
|
* @return A stable node identifier
|
||||||
*/
|
*/
|
||||||
public static String getNodeFingerprint() {
|
public static String getNodeFingerprint() {
|
||||||
@@ -81,9 +128,9 @@ public class SystemId {
|
|||||||
MessageDigest sha1_digest = MessageDigest.getInstance("SHA-1");
|
MessageDigest sha1_digest = MessageDigest.getInstance("SHA-1");
|
||||||
byte[] addrBytes = sha1_digest.digest(addrId.getBytes(StandardCharsets.UTF_8));
|
byte[] addrBytes = sha1_digest.digest(addrId.getBytes(StandardCharsets.UTF_8));
|
||||||
String fingerprint = "";
|
String fingerprint = "";
|
||||||
for (int i=0; i < addrBytes.length; i++) {
|
for (int i = 0; i < addrBytes.length; i++) {
|
||||||
fingerprint +=
|
fingerprint +=
|
||||||
Integer.toString( ( addrBytes[i] & 0xff ) + 0x100, 16).substring( 1 );
|
Integer.toString((addrBytes[i] & 0xff) + 0x100, 16).substring(1);
|
||||||
}
|
}
|
||||||
return fingerprint.toUpperCase(Locale.ROOT);
|
return fingerprint.toUpperCase(Locale.ROOT);
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
@@ -125,4 +172,75 @@ public class SystemId {
|
|||||||
return gson.toJson(details);
|
return gson.toJson(details);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final static String radixSymbols = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~-"; // 64 symbols, for 2^6!
|
||||||
|
private final int brailleStart = '⠀';
|
||||||
|
private final int brailleEnd = '⣿';
|
||||||
|
private final int brailleRadix = brailleEnd - brailleStart;
|
||||||
|
|
||||||
|
public static String getBrailleNodeId() {
|
||||||
|
String nodeId = getNodeId();
|
||||||
|
String[] fields = nodeId.split("\\.");
|
||||||
|
byte[] addr;
|
||||||
|
try {
|
||||||
|
InetAddress inetAddr = Inet4Address.getByName(nodeId);
|
||||||
|
addr = inetAddr.getAddress();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return braille((addr[0] << 24) + (addr[1] << 16) + (addr[2] << 8) + addr[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String braille(int value) {
|
||||||
|
StringBuilder buf = new StringBuilder(4);
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
int mask = value & 0xF;
|
||||||
|
value >>= 8;
|
||||||
|
int charat = '⠀' + mask;
|
||||||
|
buf.append((char) charat);
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String braille(long value) {
|
||||||
|
StringBuilder buf = new StringBuilder(8);
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
int mask = (int) value & 0xF;
|
||||||
|
value >>= 8;
|
||||||
|
int charat = '⠀' + mask;
|
||||||
|
buf.append((char) charat);
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String genSessionCode(long epochMillis) {
|
||||||
|
return pack(epochMillis) + "_" + getPackedNodeId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPackedNodeId() {
|
||||||
|
String nodeId = getNodeId();
|
||||||
|
String[] fields = nodeId.split("\\.");
|
||||||
|
byte[] addr;
|
||||||
|
try {
|
||||||
|
InetAddress inetAddr = Inet4Address.getByName(nodeId);
|
||||||
|
addr = inetAddr.getAddress();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return pack((addr[0] << 24) + (addr[1] << 16) + (addr[2] << 8) + addr[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String pack(long bitfield) {
|
||||||
|
StringBuilder sb = new StringBuilder(11);
|
||||||
|
while (bitfield > 0) {
|
||||||
|
long tail = bitfield & 0b00111111;
|
||||||
|
bitfield >>= 6;
|
||||||
|
sb.append(radixSymbols.charAt((int) tail));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String genSessionBits() {
|
||||||
|
return getBrailleNodeId() + ":" + braille(System.currentTimeMillis());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 nosqlbench
|
* Copyright (c) 2022-2023 nosqlbench
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,28 +17,61 @@
|
|||||||
package io.nosqlbench.nb.api;
|
package io.nosqlbench.nb.api;
|
||||||
|
|
||||||
import io.nosqlbench.api.metadata.SystemId;
|
import io.nosqlbench.api.metadata.SystemId;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
public class SystemIdTest {
|
public class SystemIdTest {
|
||||||
|
private static final Logger logger = LogManager.getLogger(SystemIdTest.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHostInfo() {
|
public void testHostInfo() {
|
||||||
String info = SystemId.getHostSummary();
|
String hostSummary = SystemId.getHostSummary();
|
||||||
System.out.println(info);
|
logger.info("host summary: " + hostSummary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNostId() {
|
public void testNostId() {
|
||||||
String info = SystemId.getNodeId();
|
String nodeId = SystemId.getNodeId();
|
||||||
assertThat(info).matches("\\d+\\.\\d+\\.\\d+\\.\\d+");
|
assertThat(nodeId).matches("\\d+\\.\\d+\\.\\d+\\.\\d+");
|
||||||
|
logger.info("node id: " + nodeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNodeFingerprint() {
|
public void testNodeFingerprint() {
|
||||||
String hash = SystemId.getNodeFingerprint();
|
String nodeFingerprint = SystemId.getNodeFingerprint();
|
||||||
assertThat(hash).matches("[A-Z0-9]+");
|
assertThat(nodeFingerprint).matches("[A-Z0-9]+");
|
||||||
|
logger.info("node fingerprint: " + nodeFingerprint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBrailleNodeId() {
|
||||||
|
String brailleNodeId = SystemId.getBrailleNodeId();
|
||||||
|
assertThat(brailleNodeId).matches("[⠀-⣿]{4}"); // note, that is not a space. It is the starting braille value of empty
|
||||||
|
logger.info("braille node id: " + brailleNodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPackedNodeId() {
|
||||||
|
String packedNodeId = SystemId.getPackedNodeId();
|
||||||
|
assertThat(packedNodeId).matches("[0-9A-Za-z_-]+");
|
||||||
|
logger.info("packed node id: " + packedNodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenSessionCode() {
|
||||||
|
String sessionCode=SystemId.genSessionCode(234L);
|
||||||
|
assertThat(sessionCode).matches("[0-9a-zA-Z~-]+_[0-9a-zA-Z~-]+");
|
||||||
|
logger.info("session code: " + sessionCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenSessionBits() {
|
||||||
|
String sessionBits = SystemId.genSessionBits();
|
||||||
|
assertThat(sessionBits).matches("[⠀-⣿]+:[⠀-⣿]+");
|
||||||
|
logger.info("session bits: " + sessionBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
4
pom.xml
4
pom.xml
@@ -61,7 +61,7 @@
|
|||||||
<module.adapter-tcp>adapter-tcp</module.adapter-tcp>
|
<module.adapter-tcp>adapter-tcp</module.adapter-tcp>
|
||||||
<module.adapter-dynamodb>adapter-dynamodb</module.adapter-dynamodb>
|
<module.adapter-dynamodb>adapter-dynamodb</module.adapter-dynamodb>
|
||||||
<module.adapter-mongodb>adapter-mongodb</module.adapter-mongodb>
|
<module.adapter-mongodb>adapter-mongodb</module.adapter-mongodb>
|
||||||
<module.adapter-venice>adapter-venice</module.adapter-venice>
|
<!-- <module.adapter-venice>adapter-venice</module.adapter-venice>-->
|
||||||
<module.adapter-pulsar>adapter-pulsar</module.adapter-pulsar>
|
<module.adapter-pulsar>adapter-pulsar</module.adapter-pulsar>
|
||||||
<module.adapter-s4j>adapter-s4j</module.adapter-s4j>
|
<module.adapter-s4j>adapter-s4j</module.adapter-s4j>
|
||||||
<module.adapter-kafka>adapter-kafka</module.adapter-kafka>
|
<module.adapter-kafka>adapter-kafka</module.adapter-kafka>
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
<module>adapters-api</module>
|
<module>adapters-api</module>
|
||||||
|
|
||||||
<!-- driver modules -->
|
<!-- driver modules -->
|
||||||
<module>adapter-venice</module>
|
<!-- <module>adapter-venice</module>-->
|
||||||
<module>adapter-diag</module>
|
<module>adapter-diag</module>
|
||||||
<module>adapter-stdout</module>
|
<module>adapter-stdout</module>
|
||||||
<module>adapter-cqld4</module>
|
<module>adapter-cqld4</module>
|
||||||
|
|||||||
Reference in New Issue
Block a user