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);
|
||||
if (op instanceof CharSequence s) {
|
||||
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());
|
||||
// setOp(new LinkedHashMap<String,Object>(Map.of("stmt",s.toString())));
|
||||
@@ -79,7 +79,7 @@ public class RawOpDef extends RawOpFields {
|
||||
}
|
||||
if (found.size() > 1) {
|
||||
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();
|
||||
setName(first.getKey());
|
||||
setOp(first.getValue());
|
||||
@@ -90,7 +90,7 @@ public class RawOpDef extends RawOpFields {
|
||||
|
||||
if (_op) {
|
||||
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.");
|
||||
}
|
||||
} 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 String sessionName;
|
||||
private String sessionCode;
|
||||
private long sessionTime;
|
||||
|
||||
public NBCLI(final String commandName) {
|
||||
this.commandName = commandName;
|
||||
@@ -153,10 +155,17 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
|
||||
// logger = LogManager.getLogger("NBCLI");
|
||||
|
||||
NBCLI.loggerConfig.setConsoleLevel(NBLogLevel.ERROR);
|
||||
|
||||
this.sessionTime = System.currentTimeMillis();
|
||||
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
|
||||
.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");
|
||||
* 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.NetworkIF;
|
||||
|
||||
import java.net.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -36,32 +37,37 @@ public class SystemId {
|
||||
* 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
|
||||
* as the node's addresses do not change.
|
||||
*
|
||||
* If you are needing an identifier for a node but wish to expose any address data,
|
||||
* <p>
|
||||
* 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
|
||||
* it with SHA-1 to produce a hex string.
|
||||
*
|
||||
* @return A address for the node, likely to be unique and stable for its lifetime
|
||||
*/
|
||||
public static String getNodeId() {
|
||||
return getMainInetAddrDirect().map(InetAddress::getHostAddress).orElse("UNKNOWN_HOST_ID");
|
||||
}
|
||||
|
||||
private static String getNodeIdOSHI() {
|
||||
SystemInfo sysinfo = new SystemInfo();
|
||||
HardwareAbstractionLayer hal = sysinfo.getHardware();
|
||||
List<NetworkIF> interfaces = hal.getNetworkIFs();
|
||||
|
||||
Optional<String> first = interfaces.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;
|
||||
}
|
||||
.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;
|
||||
})
|
||||
.flatMap(iface -> Arrays.stream(iface.getIPv4addr().clone()))
|
||||
.filter(addr -> !(addr.startsWith("127.")))
|
||||
.findFirst();
|
||||
@@ -69,10 +75,51 @@ public class 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.
|
||||
* The internal data used for this value is based on a stable ordering of non-local
|
||||
* ip addresses available on the system.
|
||||
*
|
||||
* @return A stable node identifier
|
||||
*/
|
||||
public static String getNodeFingerprint() {
|
||||
@@ -81,9 +128,9 @@ public class SystemId {
|
||||
MessageDigest sha1_digest = MessageDigest.getInstance("SHA-1");
|
||||
byte[] addrBytes = sha1_digest.digest(addrId.getBytes(StandardCharsets.UTF_8));
|
||||
String fingerprint = "";
|
||||
for (int i=0; i < addrBytes.length; i++) {
|
||||
for (int i = 0; i < addrBytes.length; i++) {
|
||||
fingerprint +=
|
||||
Integer.toString( ( addrBytes[i] & 0xff ) + 0x100, 16).substring( 1 );
|
||||
Integer.toString((addrBytes[i] & 0xff) + 0x100, 16).substring(1);
|
||||
}
|
||||
return fingerprint.toUpperCase(Locale.ROOT);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
@@ -125,4 +172,75 @@ public class SystemId {
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,28 +17,61 @@
|
||||
package io.nosqlbench.nb.api;
|
||||
|
||||
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 static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class SystemIdTest {
|
||||
private static final Logger logger = LogManager.getLogger(SystemIdTest.class);
|
||||
|
||||
@Test
|
||||
public void testHostInfo() {
|
||||
String info = SystemId.getHostSummary();
|
||||
System.out.println(info);
|
||||
String hostSummary = SystemId.getHostSummary();
|
||||
logger.info("host summary: " + hostSummary);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNostId() {
|
||||
String info = SystemId.getNodeId();
|
||||
assertThat(info).matches("\\d+\\.\\d+\\.\\d+\\.\\d+");
|
||||
String nodeId = SystemId.getNodeId();
|
||||
assertThat(nodeId).matches("\\d+\\.\\d+\\.\\d+\\.\\d+");
|
||||
logger.info("node id: " + nodeId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNodeFingerprint() {
|
||||
String hash = SystemId.getNodeFingerprint();
|
||||
assertThat(hash).matches("[A-Z0-9]+");
|
||||
String nodeFingerprint = SystemId.getNodeFingerprint();
|
||||
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-dynamodb>adapter-dynamodb</module.adapter-dynamodb>
|
||||
<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-s4j>adapter-s4j</module.adapter-s4j>
|
||||
<module.adapter-kafka>adapter-kafka</module.adapter-kafka>
|
||||
@@ -102,7 +102,7 @@
|
||||
<module>adapters-api</module>
|
||||
|
||||
<!-- driver modules -->
|
||||
<module>adapter-venice</module>
|
||||
<!-- <module>adapter-venice</module>-->
|
||||
<module>adapter-diag</module>
|
||||
<module>adapter-stdout</module>
|
||||
<module>adapter-cqld4</module>
|
||||
|
||||
Reference in New Issue
Block a user