Compare commits

...
10 Commits
30 changed files with 437 additions and 291 deletions

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.1.2</version>
<version>2.1.4</version>
</parent>
<artifactId>timely-analytics</artifactId>
<!--
+9 -9
View File
@@ -4,7 +4,6 @@ if [[ $(uname) == "Darwin" ]]; then
THIS_SCRIPT=$(python -c 'import os,sys; print os.path.realpath(sys.argv[1])' "$0")
else
THIS_SCRIPT=$(readlink -f "$0")
TCNATIVE_SUFFIX="so"
HW=`uname -m`
OS_PATH=linux-${HW}
fi
@@ -54,16 +53,17 @@ if [ "$PID" == "" ]; then
JVM_ARGS="${JVM_ARGS} -Djava.net.preferIPv4Stack=true"
JVM_ARGS="${JVM_ARGS} -XX:+UseNUMA"
if [[ -n "$OS_PATH" ]]; then
pushd "${BASE_DIR}/bin" || exit
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-tcnative-boringssl-static-*.Final-"${OS_PATH}".jar META-INF/native/libnetty_tcnative_linux_"${HW}".so
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-transport-native-epoll-*-"${OS_PATH}".jar META-INF/native/libnetty_transport_native_epoll_"${HW}".so
popd || exit
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
# for linux varieties of OS, extract native libraries if not already present
if [[ -n "$OS_PATH" && (! -d ${NATIVE_DIR} || -z "$(ls -A ${NATIVE_DIR})") ]]; then
pushd "${BASE_DIR}/bin" || exit
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-tcnative-boringssl-static-*.Final-"${OS_PATH}".jar ${NATIVE_DIR}/libnetty_tcnative_linux_"${HW}".so
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-transport-native-epoll-*-"${OS_PATH}".jar ${NATIVE_DIR}/libnetty_transport_native_epoll_"${HW}".so
popd || exit
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
fi
echo "${JAVA_HOME}/bin/java ${JVM_ARGS} -jar ${THIS_DIR}/timely-balancer-*-exec.jar --instance=${INSTANCE}"
nohup "${JAVA_HOME}"/bin/java ${JVM_ARGS} -jar "${THIS_DIR}"/timely-balancer-*-exec.jar --instance="${INSTANCE}" >> "${LOG_DIR}/timely-balancer${INSTANCE}.out" 2>&1 &
echo "${JAVA_HOME}/bin/java ${JVM_ARGS} -jar ${BIN_DIR}/timely-balancer-*-exec.jar --instance=${INSTANCE}"
nohup "${JAVA_HOME}"/bin/java ${JVM_ARGS} -jar "${BIN_DIR}"/timely-balancer-*-exec.jar --instance="${INSTANCE}" >> "${LOG_DIR}/timely-balancer${INSTANCE}.out" 2>&1 &
else
echo "timely-balancer --instance=${INSTANCE} already running with pid ${PID}"
fi
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.1.2</version>
<version>2.1.4</version>
</parent>
<artifactId>timely-balancer</artifactId>
<description>Timely Balancer</description>
+2 -2
View File
@@ -4,13 +4,13 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.1.2</version>
<version>2.1.4</version>
</parent>
<artifactId>timely-client</artifactId>
<properties>
<!-- PEP 440 compliant version gets substituted into src/main/python/template/setup.py -->
<!-- use .dev0 instead of -SNAPSHOT -->
<python.client.version>2.1.2</python.client.version>
<python.client.version>2.1.4</python.client.version>
</properties>
<dependencies>
<dependency>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.1.2</version>
<version>2.1.4</version>
</parent>
<artifactId>collectd-nsq-plugin</artifactId>
<dependencies>
@@ -79,6 +79,7 @@ public class WriteNSQPlugin extends CollectDPluginParent implements CollectdConf
} catch (IOException e1) {}
try {
clientPool.invalidateObject(client);
client = null;
} catch (Exception e2) {}
}
} finally {
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.1.2</version>
<version>2.1.4</version>
</parent>
<artifactId>collectd-plugin-parent</artifactId>
<dependencies>
@@ -2,51 +2,58 @@ package timely.collectd.plugin;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Set;
import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.collectd.api.Collectd;
import org.collectd.api.DataSource;
import org.collectd.api.OConfigItem;
import org.collectd.api.ValueList;
public abstract class CollectDPluginParent {
private static final String PUT = "put {0} {1} {2}{3}\n";
private static final Pattern HADOOP_STATSD_PATTERN = Pattern.compile("([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)");
private static final String INSTANCE = " instance=";
private static final String NAME = " name=";
private static final String SAMPLE = " sample=";
private static final String CODE = " code=";
private static final String PUT = "put {0} {1} {2} {3}";
private static final String INSTANCE = "instance";
private static final String NAME = "name";
private static final String SAMPLE_TYPE = "sampleType";
private static final String CODE = "code";
private static final String PERIOD = ".";
private static final String SAMPLE_TYPE = " sampleType=";
private static final String COUNTER = "COUNTER";
private static final String GAUGE = "GAUGE";
private static final String DERIVE = "DERIVE";
private static final String ABSOLUTE = "ABSOLUTE";
private static final Pattern NSQ_PATTERN1 = Pattern.compile("([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)");
private static final Pattern NSQ_PATTERN2 = Pattern.compile("([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)");
private static final Pattern NSQ_PATTERN3 = Pattern.compile("([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_#]+)\\.([\\w-_]+)");
private static final Pattern STATSD_PATTERN_3_GROUPS = Pattern.compile("([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)");
private static final Pattern STATSD_PATTERN_4_GROUPS = Pattern.compile("([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)");
private static final Pattern STATSD_PATTERN_6_GROUPS = Pattern.compile("([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_]+)\\.([\\w-_#]+)\\.([\\w-_]+)");
private static final Pattern ETHSTAT_PATTERN = Pattern.compile("([\\w-_]+)_queue_([\\w-_]+)_([\\w-_]+)");
private static final String STATSD_PREFIX = "statsd";
private static final String NSQ_PREFIX = STATSD_PREFIX + ".nsq.";
private static final Pattern HAPROXY_PATTERN = Pattern.compile("\\[([\\w-_=]+),([\\w-_=]+)\\]");
private final SMARTCodeMapping smart = new SMARTCodeMapping();
protected Set<String> addlTags = new HashSet<>();
protected Map<String,String> addlTags = new TreeMap<>();
private boolean debug = false;
public int config(OConfigItem config) {
for (OConfigItem child : config.getChildren()) {
switch (child.getKey()) {
case "Tags":
case "tags":
String[] additionalTags = child.getValues().get(0).getString().split(",");
for (String t : additionalTags) {
addlTags.add(" " + t.trim());
}
String tagValue = child.getValues().get(0).getString();
Arrays.stream(tagValue.split(",")).map(String::trim).forEach(p -> {
String[] pair = p.split("=");
if (pair.length == 2) {
addTag(addlTags, pair[0], pair[1]);
}
});
break;
case "Debug":
case "debug":
debug = child.getValues().get(0).getBoolean();
break;
default:
}
}
@@ -55,196 +62,245 @@ public abstract class CollectDPluginParent {
public abstract void write(String metric, OutputStream out);
protected void addTag(Map<String,String> m, String k, String v) {
if (k != null && !k.isBlank() && v != null && !v.isBlank()) {
m.put(k.trim(), v.trim());
}
}
protected void addTag(Map<String,String> m, String kv) {
if (kv != null && !kv.isBlank()) {
String[] parts = kv.split("=");
if (parts.length == 2 && !parts[0].isBlank() && !parts[1].isBlank()) {
m.put(parts[0].trim(), parts[1].trim());
}
}
}
public void process(ValueList vl, OutputStream out) {
try {
processInternal(vl, out);
} catch (Exception e) {
Collectd.logError(e.getMessage());
e.printStackTrace(System.err);
}
}
private void processInternal(ValueList vl, OutputStream out) {
debugValueList(vl);
StringBuilder metric = new StringBuilder();
Long timestamp = vl.getTime();
StringBuilder tags = new StringBuilder();
Map<String,String> tagMap = new TreeMap<>();
String host = vl.getHost();
int idx = host.indexOf(PERIOD);
if (-1 != idx) {
tags.append(" host=").append(host.substring(0, idx));
addTag(tagMap, "host", host.substring(0, idx));
} else {
tags.append(" host=").append(host);
addTag(tagMap, "host", host);
}
int nIdx = host.indexOf('n');
int nIdx = host.lastIndexOf('n');
if (-1 != nIdx) {
tags.append(" rack=").append(host.substring(0, nIdx));
addTag(tagMap, "rack", host.substring(0, nIdx));
}
for (String tag : addlTags) {
tags.append(tag);
}
if (vl.getPlugin().equals(STATSD_PREFIX)) {
Matcher m = HADOOP_STATSD_PATTERN.matcher(vl.getTypeInstance());
Matcher n1 = NSQ_PATTERN1.matcher(vl.getTypeInstance());
Matcher n2 = NSQ_PATTERN2.matcher(vl.getTypeInstance());
Matcher n3 = NSQ_PATTERN3.matcher(vl.getTypeInstance());
String instance = null;
if (m.matches() && !vl.getTypeInstance().startsWith("nsq")) {
// Here we are processing the statsd metrics coming from the
// Hadoop Metrics2 StatsDSink without the host name.
// The format of metric is:
// serviceName.contextName.recordName.metricName. The recordName
// is typically duplicative and is dropped here. The serviceName
// is used as the instance.
metric.append(STATSD_PREFIX).append(PERIOD).append(m.group(2)).append(PERIOD).append(m.group(4));
instance = m.group(1);
} else if (n1.matches() && vl.getTypeInstance().startsWith("nsq")) {
metric.append(NSQ_PREFIX).append(n1.group(2)).append(PERIOD).append(n1.group(3));
} else if (n2.matches() && vl.getTypeInstance().startsWith("nsq")) {
metric.append(NSQ_PREFIX).append(n2.group(2)).append(PERIOD).append(n2.group(4));
instance = n2.group(3);
} else if (n3.matches() && vl.getTypeInstance().startsWith("nsq")) {
metric.append(NSQ_PREFIX).append(n3.group(4)).append(PERIOD).append(n3.group(6));
instance = n3.group(5);
} else {
// Handle StatsD metrics of unknown formats. If there is a
// period in the metric name, use everything up to that as
// the instance.
int period = vl.getTypeInstance().indexOf('.');
if (-1 == period) {
metric.append(STATSD_PREFIX).append(PERIOD).append(vl.getTypeInstance());
tagMap.putAll(addlTags);
String plugin = vl.getPlugin();
String pluginInstance = vl.getPluginInstance();
String type = vl.getType();
String typeInstance = vl.getTypeInstance();
switch (plugin) {
case STATSD_PREFIX:
Matcher statsd_3_groups = STATSD_PATTERN_3_GROUPS.matcher(typeInstance);
Matcher statsd_4_groups = STATSD_PATTERN_4_GROUPS.matcher(typeInstance);
Matcher statsd_6_groups = STATSD_PATTERN_6_GROUPS.matcher(typeInstance);
String instance = null;
if (!typeInstance.startsWith("nsq")) {
String[] parts = typeInstance.split("\\.");
if (parts.length % 2 == 1) {
if (parts[0].equals("dwquery") && parts.length >= 4) {
metric.append(STATSD_PREFIX).append(PERIOD).append(parts[1]).append(PERIOD).append(parts[3]);
addTag(tagMap, "queryId", parts[0]);
} else {
// EtsyStatsD format -- metric.(tagName.tagValue)*
metric.append(STATSD_PREFIX).append(PERIOD).append(parts[0]);
for (int x = 1; x < parts.length; x += 2) {
addTag(tagMap, parts[x], parts[x + 1]);
}
}
} else if (statsd_4_groups.matches()) {
// Here we are processing the statsd metrics coming from the Hadoop Metrics2 StatsDSink without the host name.
// The format of metric is: serviceName.contextName.recordName.metricName. The recordName is typically duplicative
// and is dropped here. The serviceName is used as the instance.
metric.append(STATSD_PREFIX).append(PERIOD).append(statsd_4_groups.group(2)).append(PERIOD).append(statsd_4_groups.group(4));
instance = statsd_4_groups.group(1);
}
} else if (statsd_3_groups.matches()) {
metric.append(NSQ_PREFIX).append(statsd_3_groups.group(2)).append(PERIOD).append(statsd_3_groups.group(3));
} else if (statsd_4_groups.matches()) {
metric.append(NSQ_PREFIX).append(statsd_4_groups.group(2)).append(PERIOD).append(statsd_4_groups.group(4));
instance = statsd_4_groups.group(3);
} else if (statsd_6_groups.matches()) {
metric.append(NSQ_PREFIX).append(statsd_6_groups.group(4)).append(PERIOD).append(statsd_6_groups.group(6));
instance = statsd_6_groups.group(5);
} else {
instance = vl.getTypeInstance().substring(0, period);
metric.append(STATSD_PREFIX).append(PERIOD).append(vl.getTypeInstance().substring(period + 1));
// Handle StatsD metrics of unknown formats. If there is a
// period in the metric name, use everything up to that as
// the instance.
int period = typeInstance.indexOf('.');
if (-1 == period) {
metric.append(STATSD_PREFIX).append(PERIOD).append(typeInstance);
} else {
instance = typeInstance.substring(0, period);
metric.append(STATSD_PREFIX).append(PERIOD).append(typeInstance.substring(period + 1));
}
}
}
timestamp = vl.getTime();
if (null != instance) {
tags.append(INSTANCE).append(instance);
}
} else if (vl.getPlugin().equals("ethstat")) {
metric.append("sys.ethstat.");
if (vl.getTypeInstance().contains("queue")) {
Matcher m = ETHSTAT_PATTERN.matcher(vl.getTypeInstance());
if (m.matches()) {
metric.append(m.group(1)).append("_").append(m.group(3));
tags.append(" queue=").append(m.group(2));
if (null != instance) {
addTag(tagMap, INSTANCE, instance);
}
break;
case "ethstat":
metric.append("sys.ethstat.");
if (typeInstance.contains("queue")) {
Matcher ethstat_m = ETHSTAT_PATTERN.matcher(typeInstance);
if (ethstat_m.matches()) {
metric.append(ethstat_m.group(1)).append("_").append(ethstat_m.group(3));
addTag(tagMap, "queue", ethstat_m.group(2));
} else {
metric.append(typeInstance);
}
} else {
metric.append(vl.getTypeInstance());
metric.append(typeInstance);
}
} else {
metric.append(vl.getTypeInstance());
}
tags.append(INSTANCE).append(vl.getPluginInstance());
} else if (vl.getPlugin().equals("hddtemp")) {
metric.append("sys.hddtemp.").append(vl.getType());
tags.append(INSTANCE).append(vl.getTypeInstance());
} else if (vl.getPlugin().equals("smart")) {
int code = -1;
String name = null;
if (vl.getTypeInstance().startsWith("attribute-")) {
int hyphen = vl.getTypeInstance().indexOf('-');
code = Integer.parseInt(vl.getTypeInstance().substring(hyphen + 1));
name = smart.get(code);
}
if (code == -1) {
if (notEmpty(vl.getTypeInstance())) {
metric.append("sys.smart.").append(vl.getTypeInstance());
addTag(tagMap, INSTANCE, pluginInstance);
break;
case "hddtemp":
metric.append("sys.hddtemp.").append(type);
addTag(tagMap, INSTANCE, typeInstance);
break;
case "smart":
int code = -1;
String name = null;
if (typeInstance.startsWith("attribute-")) {
int hyphen = typeInstance.indexOf('-');
code = Integer.parseInt(typeInstance.substring(hyphen + 1));
name = smart.get(code);
}
if (code == -1) {
if (notEmpty(typeInstance)) {
metric.append("sys.smart.").append(typeInstance);
} else {
metric.append("sys.smart.").append(type);
}
} else {
metric.append("sys.smart.").append(vl.getType());
metric.append("sys.smart.").append(name);
addTag(tagMap, CODE, Integer.toString(code));
}
} else {
metric.append("sys.smart.").append(name);
tags.append(CODE).append(code);
}
tags.append(INSTANCE).append(vl.getPluginInstance());
} else if (vl.getPlugin().equals("sensors")) {
String instance = "";
if (vl.getTypeInstance().startsWith("temp")) {
instance = vl.getTypeInstance().substring(4);
}
metric.append("sys.sensors.").append(vl.getType()).append(PERIOD).append(vl.getPluginInstance());
tags.append(INSTANCE).append(instance);
} else if (vl.getPlugin().equals("haproxy")) {
metric.append("sys.haproxy.").append(vl.getTypeInstance());
Matcher m = HAPROXY_PATTERN.matcher(vl.getPluginInstance());
if (m.matches()) {
tags.append(" ").append(m.group(1));
tags.append(" ").append(m.group(2));
}
} else if (vl.getPlugin().equals("ipmi")) {
metric.append("sys.ipmi.").append(vl.getType());
tags.append(INSTANCE).append(vl.getTypeInstance().replaceAll(" ", "_"));
} else if (vl.getPlugin().equals("snmp")) {
metric.append("sys.snmp.").append(vl.getType());
tags.append(INSTANCE).append(vl.getTypeInstance().replaceAll(" ", "_"));
} else if (vl.getPlugin().equals("GenericJMX")) {
metric.append("sys.").append(vl.getPlugin()).append(PERIOD).append(vl.getType()).append(PERIOD).append(vl.getTypeInstance());
String[] pluginInstanceSplit = vl.getPluginInstance().split("-");
if (pluginInstanceSplit.length > 0) {
tags.append(INSTANCE).append(pluginInstanceSplit[0].replaceAll(" ", "_"));
}
if (pluginInstanceSplit.length > 1) {
tags.append(NAME).append(pluginInstanceSplit[1].replaceAll(" ", "_"));
}
} else if (notEmpty(vl.getTypeInstance()) && notEmpty(vl.getType()) && notEmpty(vl.getPluginInstance()) && notEmpty(vl.getPlugin())) {
metric.append("sys.").append(vl.getPlugin()).append(PERIOD).append(vl.getType()).append(PERIOD).append(vl.getTypeInstance());
tags.append(INSTANCE).append(vl.getPluginInstance().replaceAll(" ", "_"));
} else if (notEmpty(vl.getTypeInstance()) && notEmpty(vl.getType()) && notEmpty(vl.getPlugin())) {
metric.append("sys.").append(vl.getPlugin()).append(PERIOD).append(vl.getType()).append(PERIOD).append(vl.getTypeInstance());
} else if (notEmpty(vl.getType()) && notEmpty(vl.getPluginInstance()) && notEmpty(vl.getPlugin())) {
metric.append("sys.").append(vl.getPlugin()).append(PERIOD).append(vl.getType());
tags.append(INSTANCE).append(vl.getPluginInstance().replaceAll(" ", "_"));
} else if (notEmpty(vl.getType()) && notEmpty(vl.getPlugin())) {
metric.append("sys.").append(vl.getPlugin()).append(PERIOD).append(vl.getType());
} else {
Collectd.logWarning("Unhandled metric: " + vl.toString());
return;
addTag(tagMap, INSTANCE, pluginInstance);
break;
case "sensors":
if (typeInstance.startsWith("temp")) {
addTag(tagMap, INSTANCE, typeInstance.substring(4));
}
metric.append("sys.sensors.").append(type).append(PERIOD).append(pluginInstance);
break;
case "haproxy":
metric.append("sys.haproxy.").append(typeInstance);
Matcher hadoop_m2 = HAPROXY_PATTERN.matcher(pluginInstance);
if (hadoop_m2.matches()) {
addTag(tagMap, hadoop_m2.group(1));
addTag(tagMap, hadoop_m2.group(2));
}
break;
case "ipmi":
case "snmp":
metric.append("sys.").append(plugin).append(PERIOD).append(type);
addTag(tagMap, INSTANCE, typeInstance.replaceAll(" ", "_"));
break;
case "GenericJMX":
metric.append("sys.").append(plugin).append(PERIOD).append(type).append(PERIOD).append(typeInstance);
String[] pluginInstanceSplit = pluginInstance.split("-");
if (pluginInstanceSplit.length > 0) {
addTag(tagMap, INSTANCE, pluginInstanceSplit[0].replaceAll(" ", "_"));
}
if (pluginInstanceSplit.length > 1) {
addTag(tagMap, NAME, pluginInstanceSplit[1].replaceAll(" ", "_"));
}
default:
if (notEmpty(type) && notEmpty(typeInstance) && notEmpty(plugin) && notEmpty(pluginInstance)) {
metric.append("sys.").append(plugin).append(PERIOD).append(type).append(PERIOD).append(typeInstance);
addTag(tagMap, INSTANCE, pluginInstance.replaceAll(" ", "_"));
} else if (notEmpty(type) && notEmpty(typeInstance) && notEmpty(plugin)) {
metric.append("sys.").append(plugin).append(PERIOD).append(type).append(PERIOD).append(typeInstance);
} else if (notEmpty(type) && notEmpty(plugin) && notEmpty(pluginInstance)) {
metric.append("sys.").append(plugin).append(PERIOD).append(type);
addTag(tagMap, INSTANCE, pluginInstance.replaceAll(" ", "_"));
} else if (notEmpty(type) && notEmpty(plugin)) {
metric.append("sys.").append(plugin).append(PERIOD).append(type);
} else {
Collectd.logWarning("Unhandled metric: " + vl);
return;
}
break;
}
final String metricName = metric.toString().replaceAll(" ", "_");
for (int i = 0; i < vl.getValues().size(); i++) {
StringBuilder tagsWithSample = new StringBuilder(tags.toString());
String sampleName = vl.getDataSet().getDataSources().get(i).getName();
int type = vl.getDataSet().getDataSources().get(i).getType();
String sampleType = convertType(type);
if (null != sampleName) {
tagsWithSample.append(SAMPLE).append(sampleName);
}
int dataSourceSampleType = vl.getDataSet().getDataSources().get(i).getType();
String sampleType = convertType(dataSourceSampleType);
if (null != sampleType) {
tagsWithSample.append(SAMPLE_TYPE).append(sampleType);
addTag(tagMap, SAMPLE_TYPE, sampleType);
}
Double value = vl.getValues().get(i).doubleValue();
String datapoint = MessageFormat.format(PUT, metricName, timestamp.toString(), value.toString(), tagsWithSample.toString());
Collectd.logDebug("Writing: " + datapoint);
write(datapoint, out);
String tagString = tagMap.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(" "));
String datapoint = MessageFormat.format(PUT, metricName, timestamp.toString(), value.toString(), tagString);
logDebug(String.format("Writing: %s", datapoint));
write(datapoint + "\n", out);
}
}
private void logDebug(String s) {
// collectd must be compiled with debug enabled in order for log level debug to work
if (debug) {
Collectd.logInfo(s);
} else {
Collectd.logDebug(s);
}
}
private void debugValueList(ValueList vl) {
Collectd.logDebug("Input: " + vl.toString());
Collectd.logDebug("Plugin: " + vl.getPlugin());
Collectd.logDebug("PluginInstance: " + vl.getPluginInstance());
Collectd.logDebug("Type: " + vl.getType());
Collectd.logDebug("TypeInstance: " + vl.getTypeInstance());
for (int i = 0; i < vl.getValues().size(); i++) {
Number value = vl.getValues().get(i);
DataSource ds = vl.getDataSet().getDataSources().get(i);
Collectd.logDebug(convertType(ds.getType()) + " " + ds.getName() + " = " + value);
try {
StringBuilder sb = new StringBuilder();
sb.append(String.format("Plugin:%s", vl.getPlugin()));
if (vl.getPluginInstance() != null && !vl.getPluginInstance().isBlank()) {
sb.append(String.format(" PluginInstance:%s", vl.getPluginInstance()));
}
sb.append(String.format(" Type:%s", vl.getType()));
sb.append(String.format(" TypeInstance:%s", vl.getTypeInstance()));
for (int i = 0; i < vl.getValues().size(); i++) {
Number value = vl.getValues().get(i);
sb.append(String.format(" Value:%s", value.toString()));
}
logDebug(sb.toString());
} catch (Exception e) {
e.printStackTrace();
logDebug(e.getMessage());
}
}
private String convertType(int type) {
String result = null;
switch (type) {
case 0:
result = COUNTER;
break;
return COUNTER;
case 1:
result = GAUGE;
break;
return GAUGE;
case 2:
result = DERIVE;
break;
return DERIVE;
case 3:
result = ABSOLUTE;
break;
return ABSOLUTE;
default:
result = GAUGE;
break;
return GAUGE;
}
return result;
}
private boolean notEmpty(String arg) {
@@ -26,7 +26,7 @@ public class PluginParentTest {
public class TestPlugin extends CollectDPluginParent {
public TestPlugin() {
super.addlTags.add(" addl1=foo");
super.addlTags.put("addl1", "foo");
}
@Override
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.1.2</version>
<version>2.1.4</version>
</parent>
<artifactId>collectd-timely-plugin</artifactId>
<dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.1.2</version>
<version>2.1.4</version>
</parent>
<artifactId>timely-common</artifactId>
<dependencies>
@@ -32,6 +32,7 @@ public class QueryRequest extends AuthenticatedRequest implements HttpGetRequest
private boolean counter = false;
private long counterMax = 0;
private long resetValue = 0;
private String interval = null;
public RateOption() {}
@@ -84,12 +85,21 @@ public class QueryRequest extends AuthenticatedRequest implements HttpGetRequest
this.resetValue = resetValue;
}
public String getInterval() {
return interval;
}
public void setInterval(String interval) {
this.interval = interval;
}
@Override
public String toString() {
ToStringBuilder tsb = new ToStringBuilder(this);
tsb.append("counter", counter);
tsb.append("counterMax", counterMax);
tsb.append("resetValue", resetValue);
tsb.append("interval", interval);
return tsb.toString();
}
@@ -99,6 +109,7 @@ public class QueryRequest extends AuthenticatedRequest implements HttpGetRequest
hcb.append(counter);
hcb.append(counterMax);
hcb.append(resetValue);
hcb.append(interval);
return hcb.toHashCode();
}
@@ -210,7 +221,7 @@ public class QueryRequest extends AuthenticatedRequest implements HttpGetRequest
private String aggregator;
private String metric;
private boolean rate = false;
private RateOption rateOptions = null;
private RateOption rateOptions = new RateOption();
private Optional<String> downsample = Optional.empty();
private Map<String,String> tags = new LinkedHashMap<>();
private Collection<Filter> filters = new ArrayList<>();
@@ -536,9 +547,12 @@ public class QueryRequest extends AuthenticatedRequest implements HttpGetRequest
options.setCounter(rateOptions[x].endsWith("counter"));
break;
case 1:
options.setCounterMax(Long.parseLong(rateOptions[x]));
options.setInterval(rateOptions[x]);
break;
case 2:
options.setCounterMax(Long.parseLong(rateOptions[x]));
break;
case 3:
options.setResetValue(Long.parseLong(rateOptions[x]));
break;
default:
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.1.2</version>
<version>2.1.4</version>
</parent>
<artifactId>timely-app</artifactId>
<packaging>pom</packaging>
+2 -2
View File
@@ -28,8 +28,8 @@
}
],
"screenshots": [],
"version": "2.1.2",
"updated": "2024-03-06"
"version": "2.1.4",
"updated": "2024-03-29"
},
"dependencies": {
"classnames": "2.2.6",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "timely-datasource",
"version": "2.1.2",
"version": "2.1.4",
"description": "Timely",
"backend": true,
"alerting": true,
+1 -1
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.1.2</version>
<version>2.1.4</version>
<packaging>pom</packaging>
<name>Timely</name>
<description>A secure and scalable time series database based on Apache Accumulo</description>
+9 -9
View File
@@ -4,7 +4,6 @@ if [[ $(uname) == "Darwin" ]]; then
THIS_SCRIPT=$(python -c 'import os,sys; print os.path.realpath(sys.argv[1])' "$0")
else
THIS_SCRIPT=$(readlink -f "$0")
TCNATIVE_SUFFIX="so"
HW=`uname -m`
OS_PATH=linux-${HW}
fi
@@ -54,16 +53,17 @@ if [ "$PID" == "" ]; then
JVM_ARGS="${JVM_ARGS} -Djava.net.preferIPv4Stack=true"
JVM_ARGS="${JVM_ARGS} -XX:+UseNUMA"
if [[ -n "$OS_PATH" ]]; then
pushd "${BASE_DIR}/bin" || exit
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-tcnative-boringssl-static-*-"${OS_PATH}".jar META-INF/native/libnetty_tcnative_linux_"${HW}".so
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-transport-native-epoll-*-"${OS_PATH}".jar META-INF/native/libnetty_transport_native_epoll_"${HW}".so
popd || exit
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
# for linux varieties of OS, extract native libraries if not already present
if [[ -n "$OS_PATH" && (! -d ${NATIVE_DIR} || -z "$(ls -A ${NATIVE_DIR})") ]]; then
pushd "${BASE_DIR}/bin" || exit
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-tcnative-boringssl-static-*.Final-"${OS_PATH}".jar ${NATIVE_DIR}/libnetty_tcnative_linux_"${HW}".so
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-transport-native-epoll-*-"${OS_PATH}".jar ${NATIVE_DIR}/libnetty_transport_native_epoll_"${HW}".so
popd || exit
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
fi
echo "${JAVA_HOME}/bin/java ${JVM_ARGS} -jar ${THIS_DIR}/timely-server*-exec.jar timelyserver --instance=${INSTANCE}"
nohup "${JAVA_HOME}"/bin/java ${JVM_ARGS} -jar "${THIS_DIR}"/timely-server-*-exec.jar timelyserver --instance="${INSTANCE}" >> "${LOG_DIR}/timely-server${INSTANCE}.out" 2>&1 &
echo "${JAVA_HOME}/bin/java ${JVM_ARGS} -jar ${BIN_DIR}/timely-server*-exec.jar timelyserver --instance=${INSTANCE}"
nohup "${JAVA_HOME}"/bin/java ${JVM_ARGS} -jar "${BIN_DIR}"/timely-server-*-exec.jar timelyserver --instance="${INSTANCE}" >> "${LOG_DIR}/timely-server${INSTANCE}.out" 2>&1 &
else
echo "timely-server --instance=${INSTANCE} already running with pid ${PID}"
fi
+17 -4
View File
@@ -1,11 +1,15 @@
#!/bin/bash
if [[ `uname` == "Darwin" ]]; then
THIS_SCRIPT=`python -c 'import os,sys; print os.path.realpath(sys.argv[1])' $0`
THIS_SCRIPT=`python -c 'import os,sys; print os.path.realpath(sys.argv[1])' $0`
else
THIS_SCRIPT=`readlink -f $0`
THIS_SCRIPT=`readlink -f $0`
HW=`uname -m`
OS_PATH=linux-${HW}
fi
export INSTANCE="1"
THIS_DIR="${THIS_SCRIPT%/*}"
BASE_DIR=$(cd $THIS_DIR/../.. && pwd)
LIB_DIR="${BASE_DIR}/lib"
@@ -21,5 +25,14 @@ JVM_ARGS="-Xmx256m -Xms128m"
JVM_ARGS="${JVM_ARGS} -Dlogging.config=${CONF_DIR}/log4j2-console.yml"
JVM_ARGS="${JVM_ARGS} -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
echo "$JAVA_HOME/bin/java ${JVM_ARGS} -jar ${THIS_DIR}/timely-server*-exec.jar metrics"
$JAVA_HOME/bin/java ${JVM_ARGS} -jar ${THIS_DIR}/timely-server-*-exec.jar metrics
# for linux varieties of OS, extract native libraries if not already present
if [[ -n "$OS_PATH" && (! -d ${NATIVE_DIR} || -z "$(ls -A ${NATIVE_DIR})") ]]; then
pushd "${BASE_DIR}/bin" || exit
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-tcnative-boringssl-static-*.Final-"${OS_PATH}".jar ${NATIVE_DIR}/libnetty_tcnative_linux_"${HW}".so
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-transport-native-epoll-*-"${OS_PATH}".jar ${NATIVE_DIR}/libnetty_transport_native_epoll_"${HW}".so
popd || exit
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
fi
echo "$JAVA_HOME/bin/java ${JVM_ARGS} -jar ${BIN_DIR}/timely-server*-exec.jar metrics"
$JAVA_HOME/bin/java ${JVM_ARGS} -jar ${BIN_DIR}/timely-server-*-exec.jar metrics
+17 -4
View File
@@ -1,11 +1,15 @@
#!/bin/bash
if [[ `uname` == "Darwin" ]]; then
THIS_SCRIPT=`python -c 'import os,sys; print os.path.realpath(sys.argv[1])' $0`
THIS_SCRIPT=`python -c 'import os,sys; print os.path.realpath(sys.argv[1])' $0`
else
THIS_SCRIPT=`readlink -f $0`
THIS_SCRIPT=`readlink -f $0`
HW=`uname -m`
OS_PATH=linux-${HW}
fi
export INSTANCE="1"
THIS_DIR="${THIS_SCRIPT%/*}"
BASE_DIR=$(cd $THIS_DIR/../.. && pwd)
LIB_DIR="${BASE_DIR}/lib"
@@ -21,5 +25,14 @@ JVM_ARGS="-Xmx1024m -Xms128m"
JVM_ARGS="${JVM_ARGS} -Dlogging.config=${CONF_DIR}/log4j2-console.yml"
JVM_ARGS="${JVM_ARGS} -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
echo "$JAVA_HOME/bin/java ${JVM_ARGS} -jar ${THIS_DIR}/timely-server*-exec.jar tablet --spring.profiles.active=timely,tablet"
$JAVA_HOME/bin/java ${JVM_ARGS} -jar ${THIS_DIR}/timely-server-*-exec.jar tablet --spring.profiles.active=timely,tablet
# for linux varieties of OS, extract native libraries if not already present
if [[ -n "$OS_PATH" && (! -d ${NATIVE_DIR} || -z "$(ls -A ${NATIVE_DIR})") ]]; then
pushd "${BASE_DIR}/bin" || exit
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-tcnative-boringssl-static-*.Final-"${OS_PATH}".jar ${NATIVE_DIR}/libnetty_tcnative_linux_"${HW}".so
"${JAVA_HOME}"/bin/jar xf "${LIB_DIR}"/netty-transport-native-epoll-*-"${OS_PATH}".jar ${NATIVE_DIR}/libnetty_transport_native_epoll_"${HW}".so
popd || exit
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
fi
echo "$JAVA_HOME/bin/java ${JVM_ARGS} -jar ${BIN_DIR}/timely-server*-exec.jar tablet --spring.profiles.active=timely,tablet"
$JAVA_HOME/bin/java ${JVM_ARGS} -jar ${BIN_DIR}/timely-server-*-exec.jar tablet --spring.profiles.active=timely,tablet
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.1.2</version>
<version>2.1.4</version>
</parent>
<artifactId>timely-server</artifactId>
<description>Timely Server</description>
@@ -53,11 +53,9 @@ public class MetricQuery {
}
public void setCounterOptions(long max, long resetValue) {
QueryRequest.RateOption rateOption = new QueryRequest.RateOption();
rateOption.setCounter(true);
rateOption.setCounterMax(max);
rateOption.setResetValue(resetValue);
this.subQuery.setRateOptions(rateOption);
this.subQuery.getRateOptions().setCounter(true);
this.subQuery.getRateOptions().setCounterMax(max);
this.subQuery.getRateOptions().setResetValue(resetValue);
}
public void setTags(Map<String,String> tags) {
@@ -1,5 +1,7 @@
package timely.server.sample.iterators;
import static org.apache.accumulo.core.conf.ConfigurationTypeHelper.getTimeInMillis;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
@@ -12,6 +14,7 @@ import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.iterators.IteratorEnvironment;
import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
import org.apache.accumulo.core.util.Pair;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -20,12 +23,14 @@ import timely.api.request.timeseries.QueryRequest;
public class RateIterator extends TimeSeriesGroupingIterator {
private static final Logger log = LoggerFactory.getLogger(RateIterator.class);
private static final String COUNTER_MAX = "rate.counter.max";
private static final String RATE_RESET_VALUE = "rate.reset.value";
public static final String COUNTER_MAX = "rate.counter.max";
public static final String RATE_RESET_VALUE = "rate.reset.value";
public static final String RATE_INTERVAL = "rate.interval";
private boolean isCounter = false;
private long maxCounter = 0;
private long resetValue = 0;
private long interval = 1000;
public static void setRateOptions(IteratorSetting is, QueryRequest.RateOption options) {
if (options != null && options.isCounter()) {
@@ -33,6 +38,11 @@ public class RateIterator extends TimeSeriesGroupingIterator {
is.addOption(COUNTER_MAX, Long.toString(options.getCounterMax()));
is.addOption(RATE_RESET_VALUE, Long.toString(options.getResetValue()));
}
if (options != null && StringUtils.isNotBlank(options.getInterval())) {
is.addOption(RATE_INTERVAL, Long.toString(getTimeInMillis(options.getInterval())));
} else {
is.addOption(RATE_INTERVAL, "1000");
}
}
@Override
@@ -41,8 +51,11 @@ public class RateIterator extends TimeSeriesGroupingIterator {
this.isCounter = true;
this.maxCounter = Long.parseLong(options.get(COUNTER_MAX));
this.resetValue = Long.parseLong(options.get(RATE_RESET_VALUE));
log.trace("Setting rate counter options cm:{}, rv:{}", this.maxCounter, this.resetValue);
}
if (options.containsKey(RATE_INTERVAL)) {
this.interval = Long.parseLong(options.get(RATE_INTERVAL));
}
log.trace("Setting rate options interval:{} isCounter:{} cm:{}, rv:{}", this.interval, this.isCounter, this.maxCounter, this.resetValue);
Map<String,String> opts = new HashMap<>(options);
opts.put(FILTER, "-1,1");
super.init(source, opts, env);
@@ -64,9 +77,12 @@ public class RateIterator extends TimeSeriesGroupingIterator {
if (isCounter && (secondVal < firstVal)) {
if (maxCounter > 0) {
// assume that the data has reset so add maxCounter to the lower value to calculate the difference
secondVal += maxCounter;
log.trace("second counter reset based on max:{} to ts:{}, value:{}", maxCounter, secondTs, secondVal);
} else {
// assume that the data has reset but no maxCounter set, so add the higher value
// (approximate maxCounter) to the lower value to calculate the difference
secondVal += firstVal;
log.trace("second counter reset based on first:{} to ts:{}, value:{}", firstVal, secondTs, secondVal);
}
@@ -76,7 +92,9 @@ public class RateIterator extends TimeSeriesGroupingIterator {
if (timeDiff == 0) {
return 0.0D;
}
Double result = ((secondVal - firstVal) / timeDiff);
// (secondVal - firstVal) / timeDiff will be value per millisecond, so multiply by interval to get
// value per interval. Example 60000 milliseconds in 1m, so multiply by 60000 milliseconds
Double result = ((secondVal - firstVal) / timeDiff * interval);
log.trace("compute - result: {}", result);
if (isCounter && resetValue > 0 && result > resetValue) {
@@ -700,6 +700,12 @@ public class DataStore {
if (query.isRate()) {
log.trace("Adding rate iterator");
IteratorSetting rate = new IteratorSetting(499, RateIterator.class);
// if there is no rate interval set, then use the downsample value
// so that the result is the change per downsample period
RateOption rateOptions = query.getRateOptions();
if (StringUtils.isBlank(rateOptions.getInterval())) {
rateOptions.setInterval(downsample + "ms");
}
RateIterator.setRateOptions(rate, query.getRateOptions());
scanner.addScanIterator(rate);
}
@@ -28,6 +28,7 @@ import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
import org.apache.accumulo.core.security.Authorizations;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.atomic.DistributedAtomicValue;
import org.apache.curator.framework.recipes.cache.TreeCache;
@@ -765,7 +766,13 @@ public class DataStoreCache {
if (subQuery.isRate()) {
log.trace("Adding rate iterator");
IteratorSetting rate = new IteratorSetting(499, RateIterator.class);
RateIterator.setRateOptions(rate, subQuery.getRateOptions());
// if there is no rate interval set, then use the downsample value
// so that the result is the change per downsample period
QueryRequest.RateOption rateOptions = subQuery.getRateOptions();
if (StringUtils.isBlank(rateOptions.getInterval())) {
rateOptions.setInterval(downsamplePeriod + "ms");
}
RateIterator.setRateOptions(rate, rateOptions);
RateIterator rateIterator = new RateIterator();
rateIterator.init(itr, rate.getOptions(), null);
itr = rateIterator;
@@ -189,10 +189,8 @@ public class DataStoreCacheIteratorIT extends ITBase {
subQuery.setDownsample(Optional.of("1ms-avg"));
subQuery.setMetric("metric.number.1");
subQuery.addTag("host", ".*");
QueryRequest.RateOption rateOption = new QueryRequest.RateOption();
rateOption.setCounter(false);
subQuery.setRate(true);
subQuery.setRateOptions(rateOption);
subQuery.getRateOptions().setCounter(false);
query.setQueries(Collections.singleton(subQuery));
SortedKeyValueIterator<org.apache.accumulo.core.data.Key,org.apache.accumulo.core.data.Value> itr;
@@ -702,25 +702,20 @@ public class HttpApiIT extends OneWaySSLBase {
assertEquals(1.0, entry2.getValue());
}
private void addRateData(String metric, String tagString, long testStartTime, long timeIncrement, long testStopTime, double startValue, double maxValue,
double valueIncrement) throws Exception {
long ts = testStartTime;
double value = startValue;
while (ts <= testStopTime) {
put(metric + " " + ts + " " + value + " " + tagString);
ts += timeIncrement;
value = (value >= maxValue) ? startValue : (value + valueIncrement);
}
}
@Test
public void testRateQuery() throws Exception {
// @formatter:off
put("sys.cpu.user " + (TEST_TIME) + " 1.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 1) + " 2.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 2) + " 3.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 3) + " 4.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 4) + " 5.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 5) + " 6.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 6) + " 7.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 7) + " 8.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 8) + " 9.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 9) + " 10.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 10) + " 11.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 11) + " 12.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 12) + " 13.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 13) + " 14.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME + 14) + " 15.0 tag1=value1 tag2=value2 rack=r1");
// @formatter:on
addRateData("sys.cpu.user", "tag1=value1 tag2=value2 rack=r1", TEST_TIME, 1, TEST_TIME + 14, 1.0, Double.MAX_VALUE, 1.0);
dataStore.flush();
dataStoreCache.flushCaches(-1);
// Latency in TestConfiguration is 2s, wait for it
@@ -751,23 +746,7 @@ public class HttpApiIT extends OneWaySSLBase {
@Test
public void testRateCounterQuery() throws Exception {
// @formatter:off
put("sys.cpu.user " + (TEST_TIME) + " 1.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+1) + " 2.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+2) + " 3.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+3) + " 4.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+4) + " 5.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+5) + " 6.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+6) + " 7.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+7) + " 8.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+8) + " 9.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+9) + " 10.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+10) + " 1.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+11) + " 2.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+12) + " 3.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+13) + " 4.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+14) + " 5.0 tag1=value1 tag2=value2 rack=r1");
// @formatter:on
addRateData("sys.cpu.user", "tag1=value1 tag2=value2 rack=r1", TEST_TIME, 1, TEST_TIME + 14, 1.0, 10.0, 1.0);
dataStore.flush();
dataStoreCache.flushCaches(-1);
// Latency in TestConfiguration is 2s, wait for it
@@ -782,7 +761,6 @@ public class HttpApiIT extends OneWaySSLBase {
subQuery.setTags(t);
subQuery.setDownsample(Optional.of("1ms-max"));
subQuery.setRate(true);
subQuery.setRateOptions(new QueryRequest.RateOption());
subQuery.getRateOptions().setCounter(true);
request.addQuery(subQuery);
List<QueryResponse> response = query(baseUrl + "/api/query", request);
@@ -799,24 +777,8 @@ public class HttpApiIT extends OneWaySSLBase {
}
@Test
public void testRateCounterWithOptions() throws Exception {
// @formatter:off
put("sys.cpu.user " + (TEST_TIME) + " 1.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+1) + " 2.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+2) + " 3.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+3) + " 4.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+4) + " 5.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+5) + " 6.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+6) + " 7.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+7) + " 8.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+8) + " 9.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+9) + " 10.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+10) + " 0.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+11) + " 1.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+12) + " 2.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+13) + " 3.0 tag1=value1 tag2=value2 rack=r1",
"sys.cpu.user " + (TEST_TIME+14) + " 4.0 tag1=value1 tag2=value2 rack=r1");
// @formatter:on
public void testRateCounterWithCounterMaxOption() throws Exception {
addRateData("sys.cpu.user", "tag1=value1 tag2=value2 rack=r1", TEST_TIME, 1, TEST_TIME + 14, 1.0, 10.0, 1.0);
dataStore.flush();
dataStoreCache.flushCaches(-1);
// Latency in TestConfiguration is 2s, wait for it
@@ -831,9 +793,8 @@ public class HttpApiIT extends OneWaySSLBase {
subQuery.setTags(t);
subQuery.setDownsample(Optional.of("1ms-max"));
subQuery.setRate(true);
subQuery.setRateOptions(new QueryRequest.RateOption());
subQuery.getRateOptions().setCounter(true);
subQuery.getRateOptions().setCounterMax(Long.MAX_VALUE);
subQuery.getRateOptions().setCounterMax(10);
subQuery.getRateOptions().setResetValue(2);
request.addQuery(subQuery);
List<QueryResponse> response = query(baseUrl + "/api/query", request);
@@ -844,7 +805,54 @@ public class HttpApiIT extends OneWaySSLBase {
int i = 1;
for (Entry<String,Object> e : dps.entrySet()) {
assertEquals(Long.toString(TEST_TIME + i), e.getKey());
assertEquals((i == 10 ? 0.0 : 1.0), e.getValue());
assertEquals(1.0, e.getValue());
i++;
}
}
@Test
public void testRateCounterWithRateIntervalOption() throws Exception {
Long TEST_TIME = (System.currentTimeMillis() / 60000) * 60000;
addRateData("sys.cpu.user", "tag1=value1 tag2=value2 rack=r1", TEST_TIME, 60000, TEST_TIME + 600000, 1.0, Double.MAX_VALUE, 5);
dataStore.flush();
dataStoreCache.flushCaches(-1);
// Latency in TestConfiguration is 2s, wait for it
sleepUninterruptibly(TestConfiguration.WAIT_SECONDS, TimeUnit.SECONDS);
QueryRequest request = new QueryRequest();
request.setStart(TEST_TIME);
request.setEnd(TEST_TIME + 600000);
request.setMsResolution(true);
SubQuery subQuery = new SubQuery();
subQuery.setMetric("sys.cpu.user");
subQuery.setDownsample(Optional.of("1m-max"));
subQuery.setRate(true);
subQuery.getRateOptions().setInterval("2m");
request.addQuery(subQuery);
// test interval (2m) that is different from the downsample period (1m)
List<QueryResponse> response = query(baseUrl + "/api/query", request);
assertEquals(1, response.size());
QueryResponse response1 = response.get(0);
Map<String,Object> dps = response1.getDps();
assertEquals(10, dps.size());
int i = 1;
for (Entry<String,Object> e : dps.entrySet()) {
assertEquals(Long.toString(TEST_TIME + (60000 * i)), e.getKey());
assertEquals(10.0, e.getValue());
i++;
}
// test that interval defaults to downsample period
subQuery.getRateOptions().setInterval(null);
response = query(baseUrl + "/api/query", request);
assertEquals(1, response.size());
response1 = response.get(0);
dps = response1.getDps();
assertEquals(10, dps.size());
i = 1;
for (Entry<String,Object> e : dps.entrySet()) {
assertEquals(Long.toString(TEST_TIME + (60000 * i)), e.getKey());
assertEquals(5.0, e.getValue());
i++;
}
}
@@ -499,7 +499,7 @@ public class HttpRequestDecoderIT extends ITBase {
public void testQueryURIAllAnonAccess() throws Exception {
decoder = new HttpRequestDecoder(authenticationService, anonymousSecurity, httpProperties);
DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET,
"/api/query?start=1356998400&end=1356998460&m=sum:rate{false,100,0}:sys.cpu.user{host=*}{rack=r1|r2}&tsuid=sum:000001000002000042,000001000002000043");
"/api/query?start=1356998400&end=1356998460&m=sum:rate{false,1s,100,0}:sys.cpu.user{host=*}{rack=r1|r2}&tsuid=sum:000001000002000042,000001000002000043");
decoder.decode(null, request, results);
Assert.assertEquals(1, results.size());
Assert.assertEquals(QueryRequest.class, results.iterator().next().getClass());
@@ -515,6 +515,7 @@ public class HttpRequestDecoderIT extends ITBase {
Assert.assertEquals("sys.cpu.user", first.getMetric());
Assert.assertEquals(true, first.isRate());
RateOption firstRateOption = first.getRateOptions();
Assert.assertEquals("1s", firstRateOption.getInterval());
Assert.assertEquals(false, firstRateOption.isCounter());
Assert.assertEquals(100, firstRateOption.getCounterMax());
Assert.assertEquals(0, firstRateOption.getResetValue());
@@ -545,7 +546,7 @@ public class HttpRequestDecoderIT extends ITBase {
public void testQueryURIAllWithSession() throws Exception {
decoder = new HttpRequestDecoder(authenticationService, requireUserSecurity, httpProperties);
DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET,
"/api/query?start=1356998400&end=1356998460&m=sum:rate{false,100,0}:sys.cpu.user{host=*}{rack=r1|r2}&tsuid=sum:000001000002000042,000001000002000043");
"/api/query?start=1356998400&end=1356998460&m=sum:rate{false,1s,100,0}:sys.cpu.user{host=*}{rack=r1|r2}&tsuid=sum:000001000002000042,000001000002000043");
addCookie(request);
decoder.decode(null, request, results);
Assert.assertEquals(1, results.size());
@@ -562,6 +563,7 @@ public class HttpRequestDecoderIT extends ITBase {
Assert.assertEquals("sys.cpu.user", first.getMetric());
Assert.assertEquals(true, first.isRate());
RateOption firstRateOption = first.getRateOptions();
Assert.assertEquals("1s", firstRateOption.getInterval());
Assert.assertEquals(false, firstRateOption.isCounter());
Assert.assertEquals(100, firstRateOption.getCounterMax());
Assert.assertEquals(0, firstRateOption.getResetValue());
@@ -185,7 +185,7 @@ public class ITBase {
TestDataStore.StoreCallback storeCallback = () -> PUT_REQUESTS.countDown();
try {
dataStore.addStoreCallback(storeCallback);
StringBuffer format = new StringBuffer();
StringBuilder format = new StringBuilder();
for (String line : lines) {
format.append("put ");
format.append(line);
@@ -46,14 +46,26 @@ public class RateIteratorTest extends IteratorTestBase {
@Test
public void testConstantTimeRate() throws Exception {
testInterval(null, 1.0D);
testInterval("1ms", 0.001D);
testInterval("1s", 1.0D);
testInterval("60s", 60.0D);
}
private void testInterval(String interval, double result) throws Exception {
SortedMapIterator source = new SortedMapIterator(table);
RateIterator iter = new RateIterator();
IteratorSetting settings = new IteratorSetting(100, RateIterator.class);
QueryRequest.RateOption rateOption = new QueryRequest.RateOption();
if (interval != null) {
rateOption.setInterval(interval);
}
RateIterator.setRateOptions(settings, rateOption);
iter.init(source, settings.getOptions(), SCAN_IE);
iter.seek(new Range(), EMPTY_COL_FAMS, true);
for (int i = 0; i < 99; i++) {
assertTrue(iter.hasTop());
assertEquals(0.001D, MetricAdapter.decodeValue(iter.getTopValue().get()), 0.0D);
assertEquals(result, MetricAdapter.decodeValue(iter.getTopValue().get()), 0.0D);
iter.next();
}
assertFalse(iter.hasTop());
@@ -83,7 +95,7 @@ public class RateIteratorTest extends IteratorTestBase {
Value v = source.getTopValue();
if (prevTs != -1L) {
Double thisValue = MetricAdapter.decodeValue(v.get());
expected.add((thisValue + (prevValue * -1)) / (k.getTimestamp() - prevTs));
expected.add((thisValue + (prevValue * -1)) / (k.getTimestamp() - prevTs) * 1000);
}
prevTs = k.getTimestamp();
prevValue = MetricAdapter.decodeValue(v.get());
@@ -132,7 +144,7 @@ public class RateIteratorTest extends IteratorTestBase {
iter.seek(new Range(), EMPTY_COL_FAMS, true);
for (int i = 0; i < 99; i++) {
assertTrue(iter.hasTop());
assertEquals(0.001D, MetricAdapter.decodeValue(iter.getTopValue().get()), 0.0D);
assertEquals(1.0D, MetricAdapter.decodeValue(iter.getTopValue().get()), 0.0D);
iter.next();
}
assertFalse(iter.hasTop());
@@ -166,7 +178,7 @@ public class RateIteratorTest extends IteratorTestBase {
iter.seek(new Range(), EMPTY_COL_FAMS, true);
for (int i = 0; i < 99; i++) {
assertTrue(iter.hasTop());
assertEquals(0.001D, MetricAdapter.decodeValue(iter.getTopValue().get()), 0.0D);
assertEquals(1.0D, MetricAdapter.decodeValue(iter.getTopValue().get()), 0.0D);
iter.next();
}
assertFalse(iter.hasTop());
@@ -201,7 +213,7 @@ public class RateIteratorTest extends IteratorTestBase {
iter.seek(new Range(), EMPTY_COL_FAMS, true);
for (int i = 0; i < 99; i++) {
assertTrue(iter.hasTop());
assertEquals(((i + 1) % 10 == 0 ? 0.0D : 0.001D), MetricAdapter.decodeValue(iter.getTopValue().get()), 0.0D);
assertEquals(((i + 1) % 10 == 0 ? 0.0D : 1.0D), MetricAdapter.decodeValue(iter.getTopValue().get()), 0.0D);
iter.next();
}
assertFalse(iter.hasTop());
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.1.2</version>
<version>2.1.4</version>
</parent>
<artifactId>timely-test</artifactId>
<properties>