mirror of
https://github.com/NationalSecurityAgency/timely.git
synced 2026-11-09 17:36:01 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d35ae08188 | ||
|
|
e448657afb | ||
|
|
1dcd893711 | ||
|
|
409f5375d1 | ||
|
|
c5df8139ca | ||
|
|
dcd23d4fc8 | ||
|
|
cc7326fc19 | ||
|
|
0d2b6e61c8 | ||
|
|
b7cd8765c5 | ||
|
|
a9d27d5b1b | ||
|
|
7d67eb218d | ||
|
|
5fb7e3dd2b |
No files matched your search
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
<artifactId>timely-analytics</artifactId>
|
||||
<!--
|
||||
|
||||
@@ -27,15 +27,14 @@ fi
|
||||
mkdir -p ${NATIVE_DIR}
|
||||
|
||||
pushd ${BASE_DIR}/bin
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-tcnative*.jar META-INF/native/libnetty_tcnative.${TCNATIVE_SUFFIX}
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-transport-native-epoll*.jar META-INF/native/libnetty_transport_native_epoll_x86_64.${TCNATIVE_SUFFIX}
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-tcnative-boringssl-static*.jar META-INF/native/libnetty_tcnative_linux_x86_64.${TCNATIVE_SUFFIX}
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-all*.jar META-INF/native/libnetty_transport_native_epoll_x86_64.${TCNATIVE_SUFFIX}
|
||||
popd
|
||||
|
||||
export CLASSPATH="${CONF_DIR}:${LIB_DIR}/*:${HADOOP_CONF_DIR}"
|
||||
JVM_ARGS="-Xmx1G -Xms1G -Dio.netty.eventLoopThreads=${NUM_SERVER_THREADS}"
|
||||
JVM_ARGS="-Xmx1G -Xms1G -Dio.netty.eventLoopThreads=${NUM_SERVER_THREADS} -Dlog4j.configurationFile=${CONF_DIR}/log4j2-spring.xml"
|
||||
JVM_ARGS="${JVM_ARGS} -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
|
||||
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
|
||||
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}/libnetty-${TCNATIVE_SUFFIX}"
|
||||
|
||||
#JVM_ARGS="${JVM_ARGS} -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ timely-balancer:
|
||||
assignmentFile: /timely/balancer/assignments.csv
|
||||
security:
|
||||
session-max-age: 86400
|
||||
cache-expiration-minutes: 60
|
||||
cache-refresh-minutes: 5
|
||||
allow-anonymous-http-access: true
|
||||
allow-anonymous-ws-access: true
|
||||
serverSsl:
|
||||
|
||||
+3
-38
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
<artifactId>timely-balancer</artifactId>
|
||||
<dependencies>
|
||||
@@ -161,9 +161,8 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-tcnative</artifactId>
|
||||
<artifactId>netty-tcnative-boringssl-static</artifactId>
|
||||
<version>${version.netty-tcnative}</version>
|
||||
<classifier>${os.detected.classifier}</classifier>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -247,9 +246,8 @@
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-tcnative</artifactId>
|
||||
<artifactId>netty-tcnative-boringssl-static</artifactId>
|
||||
<version>${version.netty-tcnative}</version>
|
||||
<classifier>${os.detected.classifier}</classifier>
|
||||
<type>jar</type>
|
||||
<overWrite>false</overWrite>
|
||||
<outputDirectory>${project.build.directory}/native</outputDirectory>
|
||||
@@ -291,37 +289,4 @@
|
||||
</extension>
|
||||
</extensions>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>native-epoll-linux</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>!mac</family>
|
||||
</os>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport-native-epoll</artifactId>
|
||||
<version>${version.netty}</version>
|
||||
<classifier>linux-x86_64</classifier>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>native-epoll</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>mac</family>
|
||||
</os>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport-native-epoll</artifactId>
|
||||
<version>${version.netty}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -364,7 +364,7 @@ public class Balancer {
|
||||
curatorFramework.start();
|
||||
ensureZkPaths(curatorFramework, zkPaths);
|
||||
|
||||
AuthCache.setSessionMaxAge(balancerConfig.getSecurity());
|
||||
AuthCache.configure(balancerConfig.getSecurity());
|
||||
final boolean useEpoll = useEpoll();
|
||||
Class<? extends ServerSocketChannel> channelClass;
|
||||
Class<? extends Channel> datagramChannelClass;
|
||||
@@ -567,7 +567,7 @@ public class Balancer {
|
||||
ch.pipeline().addLast("idle-handler",
|
||||
new IdleStateHandler(balancerConfig.getWebsocket().getTimeout(), 0, 0));
|
||||
ch.pipeline().addLast("ws-protocol",
|
||||
new WebSocketServerProtocolHandler(WS_PATH, null, true, 65536, true));
|
||||
new WebSocketServerProtocolHandler(WS_PATH, null, true, 65536, false, true));
|
||||
ch.pipeline().addLast("wsDecoder", new WebSocketRequestDecoder(balancerConfig.getSecurity()));
|
||||
ch.pipeline().addLast("httpRelay", new WsRelayHandler(balancerConfig, metricResolver, wsClientPool));
|
||||
ch.pipeline().addLast("error", new WSTimelyExceptionHandler());
|
||||
|
||||
+3
-2
@@ -4,12 +4,13 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
<artifactId>timely-client</artifactId>
|
||||
<properties>
|
||||
<!-- PEP 440 compliant version gets substituted into src/main/python/template/setup.py -->
|
||||
<python.client.version>1.2.1</python.client.version>
|
||||
<!-- use .dev0 instead of -SNAPSHOT -->
|
||||
<python.client.version>1.2.4</python.client.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
<artifactId>collectd-nsq-plugin</artifactId>
|
||||
<dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
<artifactId>collectd-plugin-parent</artifactId>
|
||||
<dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
<artifactId>collectd-timely-plugin</artifactId>
|
||||
<dependencies>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
<artifactId>timely-common</artifactId>
|
||||
<dependencies>
|
||||
|
||||
@@ -27,15 +27,14 @@ fi
|
||||
mkdir -p ${NATIVE_DIR}
|
||||
|
||||
pushd ${BASE_DIR}/bin
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-tcnative*.jar META-INF/native/libnetty_tcnative.${TCNATIVE_SUFFIX}
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-transport-native-epoll*.jar META-INF/native/libnetty_transport_native_epoll_x86_64.${TCNATIVE_SUFFIX}
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-tcnative-boringssl-static*.jar META-INF/native/libnetty_tcnative_linux_x86_64.${TCNATIVE_SUFFIX}
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-all*.jar META-INF/native/libnetty_transport_native_epoll_x86_64.${TCNATIVE_SUFFIX}
|
||||
popd
|
||||
|
||||
export CLASSPATH="${CONF_DIR}:${LIB_DIR}/*:${HADOOP_CONF_DIR}"
|
||||
JVM_ARGS="-Xmx1G -Xms1G -Dio.netty.eventLoopThreads=${NUM_SERVER_THREADS}"
|
||||
JVM_ARGS="-Xmx1G -Xms1G -Dio.netty.eventLoopThreads=${NUM_SERVER_THREADS} Dlog4j.configurationFile=${CONF_DIR}/log4j2-spring.xml"
|
||||
JVM_ARGS="${JVM_ARGS} -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
|
||||
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
|
||||
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}/libnetty-${TCNATIVE_SUFFIX}"
|
||||
|
||||
#JVM_ARGS="${JVM_ARGS} -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ grafana-auth:
|
||||
port: 3001
|
||||
security:
|
||||
session-max-age: 86400
|
||||
cache-expiration-minutes: 60
|
||||
cache-refresh-minutes: 5
|
||||
allow-anonymous-http-access: true
|
||||
allow-anonymous-ws-access: true
|
||||
serverSsl:
|
||||
|
||||
+3
-38
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
<artifactId>grafana-auth</artifactId>
|
||||
<dependencies>
|
||||
@@ -165,9 +165,8 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-tcnative</artifactId>
|
||||
<artifactId>netty-tcnative-boringssl-static</artifactId>
|
||||
<version>${version.netty-tcnative}</version>
|
||||
<classifier>${os.detected.classifier}</classifier>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -251,9 +250,8 @@
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-tcnative</artifactId>
|
||||
<artifactId>netty-tcnative-boringssl-static</artifactId>
|
||||
<version>${version.netty-tcnative}</version>
|
||||
<classifier>${os.detected.classifier}</classifier>
|
||||
<type>jar</type>
|
||||
<overWrite>false</overWrite>
|
||||
<outputDirectory>${project.build.directory}/native</outputDirectory>
|
||||
@@ -295,37 +293,4 @@
|
||||
</extension>
|
||||
</extensions>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>native-epoll-linux</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>!mac</family>
|
||||
</os>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport-native-epoll</artifactId>
|
||||
<version>${version.netty}</version>
|
||||
<classifier>linux-x86_64</classifier>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>native-epoll</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>mac</family>
|
||||
</os>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport-native-epoll</artifactId>
|
||||
<version>${version.netty}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -226,7 +226,7 @@ public class GrafanaAuth {
|
||||
|
||||
public void run() throws Exception {
|
||||
|
||||
AuthCache.setSessionMaxAge(grafanaAuthConfig.getSecurity());
|
||||
AuthCache.configure(grafanaAuthConfig.getSecurity());
|
||||
final boolean useEpoll = useEpoll();
|
||||
Class<? extends ServerSocketChannel> channelClass;
|
||||
if (useEpoll) {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
<artifactId>timely-app</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
Vendored
+2
-2
@@ -23,8 +23,8 @@
|
||||
{"name": "Project site", "url": "https://github.com/NationalSecurityAgency/timely"},
|
||||
{"name": "License & Terms", "url": "https://raw.githubusercontent.com/NationalSecurityAgency/timely/master/LICENSE"}
|
||||
],
|
||||
"version": "1.2.1",
|
||||
"updated": "2019-04-02"
|
||||
"version": "1.2.4",
|
||||
"updated": "2019-05-22"
|
||||
},
|
||||
|
||||
"includes": [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "timely-app",
|
||||
"private": true,
|
||||
"version": "1.2.1",
|
||||
"version": "1.2.4",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
{"name": "Project site", "url": "https://github.com/NationalSecurityAgency/timely"},
|
||||
{"name": "License & Terms", "url": "https://raw.githubusercontent.com/NationalSecurityAgency/timely/master/LICENSE"}
|
||||
],
|
||||
"version": "1.2.1",
|
||||
"updated": "2019-04-02"
|
||||
"version": "1.2.4",
|
||||
"updated": "2019-05-22"
|
||||
},
|
||||
|
||||
"includes": [
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.4</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Timely</name>
|
||||
<description>A secure and scalable time series database based on Apache Accumulo</description>
|
||||
@@ -75,10 +75,10 @@
|
||||
<version.maven-rpm>2.1.4</version.maven-rpm>
|
||||
<version.maven-shade>2.4.2</version.maven-shade>
|
||||
<version.maven-surefire>2.19.1</version.maven-surefire>
|
||||
<version.netty>4.1.33.Final</version.netty>
|
||||
<version.netty-tcnative>2.0.20.Final</version.netty-tcnative>
|
||||
<version.netty>4.1.35.Final</version.netty>
|
||||
<version.netty-tcnative>2.0.25.Final</version.netty-tcnative>
|
||||
<version.os-maven>1.5.0.Final</version.os-maven>
|
||||
<version.powermock>1.6.6</version.powermock>
|
||||
<version.powermock>1.6.4</version.powermock>
|
||||
<version.slf4j>1.7.26</version.slf4j>
|
||||
<version.spotbugs-maven>3.1.7</version.spotbugs-maven>
|
||||
<version.spring-boot>2.1.3.RELEASE</version.spring-boot>
|
||||
@@ -155,6 +155,12 @@
|
||||
<groupId>org.apache.accumulo</groupId>
|
||||
<artifactId>accumulo-core</artifactId>
|
||||
<version>${version.accumulo}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.accumulo</groupId>
|
||||
@@ -450,7 +456,7 @@
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>${version.maven-surefire}</version>
|
||||
<configuration>
|
||||
<argLine>${failsafeArgLine} -Djava.library.path=${project.build.directory}/native/META-INF/native/libnetty-tcnative.so -Dzookeeper.sasl.client=false</argLine>
|
||||
<argLine>${failsafeArgLine} -Djava.library.path=${project.build.directory}/native/META-INF/native/libnetty_tcnative_linux_x86_64.so -Dzookeeper.sasl.client=false</argLine>
|
||||
<includes>
|
||||
<include>**/*.java</include>
|
||||
</includes>
|
||||
@@ -493,7 +499,7 @@
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${version.maven-surefire}</version>
|
||||
<configuration>
|
||||
<argLine>${sureFireArgLine} -Djava.library.path=${project.build.directory}/native/META-INF/native/libnetty-tcnative.so -Dzookeeper.sasl.client=false</argLine>
|
||||
<argLine>${sureFireArgLine} -Djava.library.path=${project.build.directory}/native/META-INF/native/libnetty-tcnative_linux_x86_64.so -Dzookeeper.sasl.client=false</argLine>
|
||||
<excludedGroups>timely.test.IntegrationTest</excludedGroups>
|
||||
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||
</configuration>
|
||||
|
||||
@@ -27,15 +27,14 @@ fi
|
||||
mkdir -p ${NATIVE_DIR}
|
||||
|
||||
pushd ${BASE_DIR}/bin
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-tcnative*.jar META-INF/native/libnetty_tcnative.${TCNATIVE_SUFFIX}
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-transport-native-epoll*.jar META-INF/native/libnetty_transport_native_epoll_x86_64.${TCNATIVE_SUFFIX}
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-tcnative-boringssl-static*.jar META-INF/native/libnetty_tcnative_linux_x86_64.${TCNATIVE_SUFFIX}
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-all*.jar META-INF/native/libnetty_transport_native_epoll_x86_64.${TCNATIVE_SUFFIX}
|
||||
popd
|
||||
|
||||
export CLASSPATH="${CONF_DIR}:${LIB_DIR}/*"
|
||||
JVM_ARGS="-Xmx256m -Xms256m -Dio.netty.eventLoopThreads=${NUM_SERVER_THREADS}"
|
||||
export CLASSPATH="${CONF_DIR}:${LIB_DIR}/*:${HADOOP_CONF_DIR}"
|
||||
JVM_ARGS="-Xmx256m -Xms256m -Dio.netty.eventLoopThreads=${NUM_SERVER_THREADS} -Dlog4j.configurationFile=${CONF_DIR}/log4j2-spring.xml"
|
||||
JVM_ARGS="${JVM_ARGS} -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
|
||||
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
|
||||
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}/libnetty-${TCNATIVE_SUFFIX}"
|
||||
|
||||
echo "$JAVA_HOME/bin/java ${JVM_ARGS} timely.Server --spring.config.name=timely"
|
||||
$JAVA_HOME/bin/java ${JVM_ARGS} timely.Server --spring.config.name=timely
|
||||
|
||||
@@ -2,17 +2,12 @@
|
||||
|
||||
if [[ `uname` == "Darwin" ]]; then
|
||||
THIS_SCRIPT=`python -c 'import os,sys; print os.path.realpath(sys.argv[1])' $0`
|
||||
TCNATIVE_SUFFIX="tcnative.jnilib"
|
||||
TCNATIVE_SUFFIX="jnilib"
|
||||
else
|
||||
THIS_SCRIPT=`readlink -f $0`
|
||||
TCNATIVE_SUFFIX="tcnative.so"
|
||||
TCNATIVE_SUFFIX="so"
|
||||
fi
|
||||
|
||||
# netty tcnative file reference
|
||||
#netty-tcnative-1.1.33.Fork18-linux-x86_64-fedora.jar -> libnetty-tcnative.so
|
||||
#netty-tcnative-1.1.33.Fork18-linux-x86_64.jar -> libnetty-tcnative.so
|
||||
#netty-tcnative-1.1.33.Fork18-osx-x86_64.jar -> libnetty-tcnative.jnilib
|
||||
|
||||
THIS_DIR="${THIS_SCRIPT%/*}"
|
||||
NATIVE_DIR="${THIS_DIR}/META-INF/native"
|
||||
BASE_DIR=${THIS_DIR}/..
|
||||
@@ -32,11 +27,12 @@ fi
|
||||
mkdir -p ${NATIVE_DIR}
|
||||
|
||||
pushd ${BASE_DIR}/bin
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-tcnative*.jar META-INF/native/libnetty-${TCNATIVE_SUFFIX}
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-tcnative-boringssl-static*.jar META-INF/native/libnetty_tcnative_linux_x86_64.${TCNATIVE_SUFFIX}
|
||||
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-all*.jar META-INF/native/libnetty_transport_native_epoll_x86_64.${TCNATIVE_SUFFIX}
|
||||
popd
|
||||
|
||||
export CLASSPATH="${CONF_DIR}:${LIB_DIR}/*"
|
||||
JVM_ARGS="-Xmx256m -Xms256m -Dio.netty.eventLoopThreads=${NUM_SERVER_THREADS}"
|
||||
export CLASSPATH="${CONF_DIR}:${LIB_DIR}/*:${HADOOP_CONF_DIR}"
|
||||
JVM_ARGS="-Xmx256m -Xms256m -Dio.netty.eventLoopThreads=${NUM_SERVER_THREADS} -Dlog4j.configurationFile=${CONF_DIR}/log4j2-spring.xml"
|
||||
JVM_ARGS="${JVM_ARGS} -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
|
||||
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
|
||||
# for debugging
|
||||
|
||||
@@ -18,6 +18,8 @@ timely:
|
||||
max-downsample-memory: 10000000
|
||||
security:
|
||||
session-max-age: 86400
|
||||
cache-expiration-minutes: 60
|
||||
cache-refresh-minutes: 5
|
||||
allow-anonymous-http-access: true
|
||||
allow-anonymous-ws-access: true
|
||||
ssl:
|
||||
@@ -50,9 +52,9 @@ timely:
|
||||
timeout: 60
|
||||
subscription-lag: 120
|
||||
meta-cache:
|
||||
expiration-minutes: 60
|
||||
initial-capacity: 2000
|
||||
max-capacity: 10000
|
||||
expiration-minutes: 1440
|
||||
cache-refresh-minutes: 60
|
||||
max-tag-values: 100
|
||||
visibility-cache:
|
||||
expiration-minutes: 60
|
||||
initial-capacity: 2000
|
||||
|
||||
@@ -18,6 +18,8 @@ timely:
|
||||
max-downsample-memory: 10000000
|
||||
security:
|
||||
session-max-age: 86400
|
||||
cache-expiration-minutes: 60
|
||||
cache-refresh-minutes: 5
|
||||
allow-anonymous-http-access: true
|
||||
allow-anonymous-ws-access: true
|
||||
ssl:
|
||||
@@ -54,9 +56,9 @@ timely:
|
||||
scanner-read-ahead: 1
|
||||
subscription-batch-size: 5000
|
||||
meta-cache:
|
||||
expiration-minutes: 60
|
||||
initial-capacity: 2000
|
||||
max-capacity: 10000
|
||||
expiration-minutes: 1440
|
||||
cache-refresh-minutes: 60
|
||||
max-tag-values: 100
|
||||
visibility-cache:
|
||||
expiration-minutes: 60
|
||||
initial-capacity: 2000
|
||||
|
||||
@@ -23,6 +23,8 @@ timely:
|
||||
max-downsample-memory: 10000000
|
||||
security:
|
||||
session-max-age: 86400
|
||||
cache-expiration-minutes: 60
|
||||
cache-refresh-minutes: 5
|
||||
allow-anonymous-http-access: true
|
||||
allow-anonymous-ws-access: true
|
||||
serverSsl:
|
||||
@@ -60,10 +62,9 @@ timely:
|
||||
scanner-read-ahead: 1
|
||||
subscription-batch-size: 5000
|
||||
meta-cache:
|
||||
expiration-minutes: 60
|
||||
initial-capacity: 2000
|
||||
max-capacity: 10000
|
||||
expiration-minutes: 1440
|
||||
cache-refresh-minutes: 60
|
||||
max-tag-values: 100
|
||||
visibility-cache:
|
||||
expiration-minutes: 60
|
||||
initial-capacity: 2000
|
||||
max-capacity: 10000
|
||||
|
||||
+3
-38
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>timely</groupId>
|
||||
<artifactId>timely</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.4</version>
|
||||
</parent>
|
||||
<artifactId>timely-server</artifactId>
|
||||
<dependencies>
|
||||
@@ -149,9 +149,8 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-tcnative</artifactId>
|
||||
<artifactId>netty-tcnative-boringssl-static</artifactId>
|
||||
<version>${version.netty-tcnative}</version>
|
||||
<classifier>${os.detected.classifier}</classifier>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -240,9 +239,8 @@
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-tcnative</artifactId>
|
||||
<artifactId>netty-tcnative-boringssl-static</artifactId>
|
||||
<version>${version.netty-tcnative}</version>
|
||||
<classifier>${os.detected.classifier}</classifier>
|
||||
<type>jar</type>
|
||||
<overWrite>false</overWrite>
|
||||
<outputDirectory>${project.build.directory}/native</outputDirectory>
|
||||
@@ -284,37 +282,4 @@
|
||||
</extension>
|
||||
</extensions>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>native-epoll-linux</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>!mac</family>
|
||||
</os>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport-native-epoll</artifactId>
|
||||
<version>${version.netty}</version>
|
||||
<classifier>linux-x86_64</classifier>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>native-epoll</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>mac</family>
|
||||
</os>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport-native-epoll</artifactId>
|
||||
<version>${version.netty}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -431,7 +431,7 @@ public class Server {
|
||||
// Initialize the MetaCache
|
||||
MetaCacheFactory.getCache(config);
|
||||
// initialize the auth cache
|
||||
AuthCache.setSessionMaxAge(config.getSecurity());
|
||||
AuthCache.configure(config.getSecurity());
|
||||
// Initialize the VisibilityCache
|
||||
VisibilityCache.init(config);
|
||||
final boolean useEpoll = useEpoll();
|
||||
@@ -668,7 +668,7 @@ public class Server {
|
||||
ch.pipeline().addLast("sessionExtractor", new WebSocketFullRequestHandler());
|
||||
ch.pipeline().addLast("idle-handler", new IdleStateHandler(conf.getWebsocket().getTimeout(), 0, 0));
|
||||
ch.pipeline().addLast("ws-protocol",
|
||||
new WebSocketServerProtocolHandler(WS_PATH, null, true, 65536, true));
|
||||
new WebSocketServerProtocolHandler(WS_PATH, null, true, 65536, false, true));
|
||||
ch.pipeline().addLast("wsDecoder", new WebSocketRequestDecoder(config.getSecurity()));
|
||||
ch.pipeline().addLast("aggregators", new WSAggregatorsRequestHandler());
|
||||
ch.pipeline().addLast("metrics", new WSMetricsRequestHandler(config));
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package timely.adapter.accumulo;
|
||||
|
||||
import org.apache.accumulo.core.client.lexicoder.LongLexicoder;
|
||||
import org.apache.accumulo.core.client.lexicoder.PairLexicoder;
|
||||
import org.apache.accumulo.core.client.lexicoder.StringLexicoder;
|
||||
import org.apache.accumulo.core.data.Key;
|
||||
import timely.api.model.Meta;
|
||||
import timely.model.Metric;
|
||||
import timely.model.parse.TagListParser;
|
||||
import timely.model.parse.TagParser;
|
||||
|
||||
/**
|
||||
* Creates Accumulo data structures from {@link Metric}
|
||||
*/
|
||||
public class MetaAdapter {
|
||||
|
||||
private static final PairLexicoder<String, Long> rowCoder = new PairLexicoder<>(new StringLexicoder(),
|
||||
new LongLexicoder());
|
||||
|
||||
private static final PairLexicoder<Long, String> colQualCoder = new PairLexicoder<>(new LongLexicoder(),
|
||||
new StringLexicoder());
|
||||
|
||||
private static final TagParser tagParser = new TagParser();
|
||||
private static final TagListParser tagListParser = new TagListParser();
|
||||
|
||||
public static Key createMetricKey(String metricName, Long timestamp) {
|
||||
return new Key(Meta.METRIC_PREFIX + metricName, "", "", timestamp);
|
||||
}
|
||||
|
||||
public static Key createTagKey(String metricName, String tagName, Long timestamp) {
|
||||
return new Key(Meta.TAG_PREFIX + metricName, tagName, "", timestamp);
|
||||
}
|
||||
|
||||
public static Key createValueKey(String metricName, String tagName, String tagValue, Long timestamp) {
|
||||
return new Key(Meta.VALUE_PREFIX + metricName, tagName, tagValue, timestamp);
|
||||
}
|
||||
|
||||
public static Meta parse(Key key) {
|
||||
String row = key.getRow().toString();
|
||||
if (row.startsWith(Meta.METRIC_PREFIX)) {
|
||||
return Meta.parse(key, null, Meta.METRIC_PREFIX);
|
||||
} else if (row.startsWith(Meta.TAG_PREFIX)) {
|
||||
return Meta.parse(key, null, Meta.TAG_PREFIX);
|
||||
} else if (row.startsWith(Meta.VALUE_PREFIX)) {
|
||||
return Meta.parse(key, null, Meta.VALUE_PREFIX);
|
||||
}
|
||||
throw new IllegalStateException("Invalid key in meta " + key.toString());
|
||||
}
|
||||
|
||||
public static String decodeRowKey(Key key) {
|
||||
return parse(key).getMetric();
|
||||
}
|
||||
}
|
||||
@@ -55,16 +55,43 @@ public class Meta implements Comparable<Meta> {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public static Meta parse(Key k, Value v) {
|
||||
public static String prefix(Key key) {
|
||||
String row = key.getRow().toString();
|
||||
if (row.startsWith(Meta.METRIC_PREFIX)) {
|
||||
return Meta.METRIC_PREFIX;
|
||||
} else if (row.startsWith(Meta.TAG_PREFIX)) {
|
||||
return Meta.TAG_PREFIX;
|
||||
} else if (row.startsWith(Meta.VALUE_PREFIX)) {
|
||||
return Meta.VALUE_PREFIX;
|
||||
}
|
||||
throw new IllegalStateException("Invalid key in meta " + key.toString());
|
||||
}
|
||||
|
||||
public static Meta parse(Key key) {
|
||||
return parse(key, null);
|
||||
}
|
||||
|
||||
public static Meta parse(Key key, Value value) {
|
||||
String row = key.getRow().toString();
|
||||
if (row.startsWith(Meta.METRIC_PREFIX)) {
|
||||
return Meta.parse(key, value, Meta.METRIC_PREFIX);
|
||||
} else if (row.startsWith(Meta.TAG_PREFIX)) {
|
||||
return Meta.parse(key, value, Meta.TAG_PREFIX);
|
||||
} else if (row.startsWith(Meta.VALUE_PREFIX)) {
|
||||
return Meta.parse(key, value, Meta.VALUE_PREFIX);
|
||||
}
|
||||
throw new IllegalStateException("Invalid key in meta " + key.toString());
|
||||
}
|
||||
|
||||
public static Meta parse(Key k, Value v, String prefix) {
|
||||
if (k.getColumnQualifier().getLength() > 0) {
|
||||
return new Meta(k.getRow().toString().substring(METRIC_PREFIX.length()), k.getColumnFamily().toString(),
|
||||
return new Meta(k.getRow().toString().substring(prefix.length()), k.getColumnFamily().toString(),
|
||||
k.getColumnQualifier().toString());
|
||||
} else if (k.getColumnFamily().getLength() > 0) {
|
||||
return new Meta(k.getRow().toString().substring(METRIC_PREFIX.length()), k.getColumnFamily().toString(),
|
||||
null);
|
||||
return new Meta(k.getRow().toString().substring(prefix.length()), k.getColumnFamily().toString(), null);
|
||||
|
||||
} else {
|
||||
return new Meta(k.getRow().toString().substring(METRIC_PREFIX.length()), null, null);
|
||||
return new Meta(k.getRow().toString().substring(prefix.length()), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,32 +23,67 @@ public class AuthCache {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AuthCache.class);
|
||||
private static Cache<String, TimelyPrincipal> CACHE = null;
|
||||
|
||||
private static int sessionMaxAge = -1;
|
||||
private static int cacheExpirationMinutes = -1;
|
||||
private static int cacheRefreshMinutes = -1;
|
||||
|
||||
/**
|
||||
* For tests only
|
||||
*/
|
||||
public static void resetSessionMaxAge() {
|
||||
sessionMaxAge = -1;
|
||||
public static void resetConfiguration() {
|
||||
cacheExpirationMinutes = -1;
|
||||
cacheRefreshMinutes = -1;
|
||||
}
|
||||
|
||||
public static void setSessionMaxAge(Security security) {
|
||||
if (-1 != sessionMaxAge) {
|
||||
throw new IllegalStateException("Cache session max age already configured.");
|
||||
public static void configure(Security security) {
|
||||
if (-1 != cacheExpirationMinutes || -1 != cacheRefreshMinutes) {
|
||||
throw new IllegalStateException("Cache already configured.");
|
||||
}
|
||||
sessionMaxAge = security.getSessionMaxAge();
|
||||
cacheExpirationMinutes = security.getCacheExpirationMinutes();
|
||||
cacheRefreshMinutes = security.getCacheRefreshMinutes();
|
||||
}
|
||||
|
||||
private static Cache<String, TimelyPrincipal> getCache() {
|
||||
if (-1 == sessionMaxAge) {
|
||||
if (-1 == cacheExpirationMinutes) {
|
||||
throw new IllegalStateException("Cache session max age not configured.");
|
||||
}
|
||||
if (null == CACHE) {
|
||||
CACHE = Caffeine.newBuilder().expireAfterAccess(sessionMaxAge, TimeUnit.SECONDS).build();
|
||||
Caffeine<Object, Object> caffeine = Caffeine.newBuilder();
|
||||
caffeine.expireAfterWrite(cacheExpirationMinutes, TimeUnit.MINUTES);
|
||||
if (cacheRefreshMinutes > 0) {
|
||||
caffeine.refreshAfterWrite(cacheRefreshMinutes, TimeUnit.MINUTES);
|
||||
CACHE = caffeine.build(key -> getTimelyPrincipal(key));
|
||||
} else {
|
||||
CACHE = caffeine.build();
|
||||
}
|
||||
}
|
||||
return CACHE;
|
||||
}
|
||||
|
||||
private static TimelyPrincipal getTimelyPrincipal(String key) {
|
||||
LOG.debug("Refreshing TimelyPrincipal {}", key);
|
||||
TimelyPrincipal timelyPrincipal = null;
|
||||
String[] dnArray = key.split(" -> ");
|
||||
if (dnArray.length == 1) {
|
||||
SubjectIssuerDNPair pair = SubjectIssuerDNPair.parse(dnArray[0]);
|
||||
TimelyAuthenticationToken token = AuthenticationService.getAuthenticationToken(new Object(),
|
||||
pair.subjectDN(), pair.issuerDN());
|
||||
timelyPrincipal = AuthenticationService.authenticate(token, pair, token.getTimelyPrincipal().getName(),
|
||||
false);
|
||||
} else if (dnArray.length > 1) {
|
||||
Collection<TimelyUser> timelyUsers = new ArrayList<>();
|
||||
for (String s : dnArray) {
|
||||
SubjectIssuerDNPair pair = SubjectIssuerDNPair.parse(s);
|
||||
TimelyAuthenticationToken token = AuthenticationService.getAuthenticationToken(new Object(),
|
||||
pair.subjectDN(), pair.issuerDN());
|
||||
TimelyPrincipal p = AuthenticationService.authenticate(token, pair,
|
||||
token.getTimelyPrincipal().getName(), false);
|
||||
timelyUsers.addAll(p.getProxiedUsers());
|
||||
}
|
||||
timelyPrincipal = new TimelyPrincipal(timelyUsers);
|
||||
}
|
||||
return timelyPrincipal;
|
||||
}
|
||||
|
||||
public static boolean containsKey(String key) {
|
||||
return getCache().getIfPresent(key) != null;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor;
|
||||
import timely.api.request.AuthenticatedRequest;
|
||||
import timely.api.response.TimelyException;
|
||||
import timely.auth.util.DnUtils;
|
||||
@@ -35,7 +34,6 @@ public class AuthenticationService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AuthenticationService.class);
|
||||
private static ApplicationContext springContext = null;
|
||||
private static AuthenticationManager authManager = null;
|
||||
private static SubjectDnX509PrincipalExtractor x509 = null;
|
||||
private static ConcurrentHashMap<String, Object> fetchingEntity = new ConcurrentHashMap<>();
|
||||
private static ConcurrentHashMap<String, Object> fetchingPrincipal = new ConcurrentHashMap<>();
|
||||
private static Collection<String> requiredRoles;
|
||||
@@ -45,7 +43,6 @@ public class AuthenticationService {
|
||||
try {
|
||||
springContext = new ClassPathXmlApplicationContext("security.xml");
|
||||
authManager = springContext.getBean("authenticationManager", AuthenticationManager.class);
|
||||
x509 = springContext.getBean("x509PrincipalExtractor", SubjectDnX509PrincipalExtractor.class);
|
||||
requiredRoles = springContext.getBean("requiredRoles", List.class);
|
||||
requiredRoles.removeIf(String::isEmpty);
|
||||
requiredAuths = springContext.getBean("requiredAuths", List.class);
|
||||
@@ -65,9 +62,17 @@ public class AuthenticationService {
|
||||
}
|
||||
|
||||
public static TimelyPrincipal authenticate(Authentication authentication, SubjectIssuerDNPair pair, String entity) {
|
||||
return authenticate(authentication, pair, entity, true);
|
||||
}
|
||||
|
||||
public static TimelyPrincipal authenticate(Authentication authentication, SubjectIssuerDNPair pair, String entity,
|
||||
boolean useCache) {
|
||||
|
||||
// only one thread should call the authenticationManager for a given entity
|
||||
TimelyPrincipal principal = AuthCache.get(entity);
|
||||
TimelyPrincipal principal = null;
|
||||
if (useCache) {
|
||||
principal = AuthCache.get(entity);
|
||||
}
|
||||
// once an entity is in the AuthCache, we can bypass all of this
|
||||
if (principal == null) {
|
||||
Object newObj = new Object();
|
||||
@@ -79,12 +84,16 @@ public class AuthenticationService {
|
||||
synchronized (o) {
|
||||
// if multiple threads are waiting on this synchronized, then the 2nd and all
|
||||
// others will get the principal here
|
||||
principal = AuthCache.get(entity);
|
||||
if (useCache) {
|
||||
principal = AuthCache.get(entity);
|
||||
}
|
||||
if (principal == null) {
|
||||
Authentication token = getAuthenticationManager().authenticate(authentication);
|
||||
principal = getTimelyPrincipal(token, pair);
|
||||
LOG.trace("Got entity principal for {} from AuthenticationManager", entity);
|
||||
AuthCache.put(entity, principal);
|
||||
if (useCache) {
|
||||
AuthCache.put(entity, principal);
|
||||
}
|
||||
} else {
|
||||
LOG.trace("Got entity principal for {} from AuthCache on 2nd attempt", entity);
|
||||
}
|
||||
@@ -232,7 +241,7 @@ public class AuthenticationService {
|
||||
return authenticationToken;
|
||||
}
|
||||
|
||||
public static TimelyAuthenticationToken getAuthenticationToken(X509Certificate clientCert, String subjectDn,
|
||||
public static TimelyAuthenticationToken getAuthenticationToken(Object clientCert, String subjectDn,
|
||||
String issuerDn) {
|
||||
TimelyAuthenticationToken authenticationToken = null;
|
||||
try {
|
||||
|
||||
@@ -2,9 +2,9 @@ package timely.configuration;
|
||||
|
||||
public class MetaCache {
|
||||
|
||||
private long expirationMinutes = 60;
|
||||
private int initialCapacity = 2000;
|
||||
private long maxCapacity = 10000;
|
||||
private long expirationMinutes = 1440;
|
||||
private int cacheRefreshMinutes = -1;
|
||||
private long maxTagValues = 100;
|
||||
|
||||
public long getExpirationMinutes() {
|
||||
return expirationMinutes;
|
||||
@@ -14,19 +14,19 @@ public class MetaCache {
|
||||
this.expirationMinutes = expirationMinutes;
|
||||
}
|
||||
|
||||
public int getInitialCapacity() {
|
||||
return initialCapacity;
|
||||
public void setCacheRefreshMinutes(int cacheRefreshMinutes) {
|
||||
this.cacheRefreshMinutes = cacheRefreshMinutes;
|
||||
}
|
||||
|
||||
public void setInitialCapacity(int initialCapacity) {
|
||||
this.initialCapacity = initialCapacity;
|
||||
public int getCacheRefreshMinutes() {
|
||||
return cacheRefreshMinutes;
|
||||
}
|
||||
|
||||
public long getMaxCapacity() {
|
||||
return maxCapacity;
|
||||
public long getMaxTagValues() {
|
||||
return maxTagValues;
|
||||
}
|
||||
|
||||
public void setMaxCapacity(long maxCapacity) {
|
||||
this.maxCapacity = maxCapacity;
|
||||
public void setMaxTagValues(long maxTagValues) {
|
||||
this.maxTagValues = maxTagValues;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ public class Security {
|
||||
private boolean allowAnonymousHttpAccess = false;
|
||||
private boolean allowAnonymousWsAccess = false;
|
||||
private int sessionMaxAge = 86400;
|
||||
private int cacheExpirationMinutes = 60;
|
||||
private int cacheRefreshMinutes = 5;
|
||||
@Valid
|
||||
@NestedConfigurationProperty
|
||||
private ServerSsl serverSsl = new ServerSsl();
|
||||
@@ -37,6 +39,22 @@ public class Security {
|
||||
this.sessionMaxAge = sessionMaxAge;
|
||||
}
|
||||
|
||||
public void setCacheExpirationMinutes(int cacheExpirationMinutes) {
|
||||
this.cacheExpirationMinutes = cacheExpirationMinutes;
|
||||
}
|
||||
|
||||
public int getCacheExpirationMinutes() {
|
||||
return cacheExpirationMinutes;
|
||||
}
|
||||
|
||||
public void setCacheRefreshMinutes(int cacheRefreshMinutes) {
|
||||
this.cacheRefreshMinutes = cacheRefreshMinutes;
|
||||
}
|
||||
|
||||
public int getCacheRefreshMinutes() {
|
||||
return cacheRefreshMinutes;
|
||||
}
|
||||
|
||||
public ServerSsl getServerSsl() {
|
||||
return serverSsl;
|
||||
}
|
||||
|
||||
@@ -22,19 +22,20 @@ public class TimelyAuthenticationToken extends PreAuthenticatedAuthenticationTok
|
||||
public static final String PROXIED_ISSUERS_HEADER = "X-ProxiedIssuersChain";
|
||||
|
||||
private Multimap<String, String> httpHeaders = null;
|
||||
private X509Certificate clientCert;
|
||||
private X509Certificate clientCert = null;
|
||||
private TimelyPrincipal timelyPrincipal;
|
||||
|
||||
public TimelyAuthenticationToken(String subjectDn, X509Certificate clientCert,
|
||||
Multimap<String, String> httpHeaders) {
|
||||
public TimelyAuthenticationToken(String subjectDn, Object clientCert, Multimap<String, String> httpHeaders) {
|
||||
super(subjectDn, clientCert);
|
||||
if (httpHeaders == null) {
|
||||
this.httpHeaders = HashMultimap.create();
|
||||
} else {
|
||||
this.httpHeaders = httpHeaders;
|
||||
}
|
||||
this.clientCert = clientCert;
|
||||
String issuerDn = clientCert == null ? null : clientCert.getIssuerDN().getName();
|
||||
if (clientCert instanceof X509Certificate) {
|
||||
this.clientCert = (X509Certificate) clientCert;
|
||||
}
|
||||
String issuerDn = clientCert == null ? null : this.clientCert.getIssuerDN().getName();
|
||||
String proxiedEntities;
|
||||
String proxiedIssuers;
|
||||
try {
|
||||
@@ -61,9 +62,11 @@ public class TimelyAuthenticationToken extends PreAuthenticatedAuthenticationTok
|
||||
LOG.trace("Created TimelyAuthenticationToken: {}", timelyPrincipal.getName());
|
||||
}
|
||||
|
||||
public TimelyAuthenticationToken(String subjectDn, String issuerDn, X509Certificate clientCert) {
|
||||
public TimelyAuthenticationToken(String subjectDn, String issuerDn, Object clientCert) {
|
||||
super(subjectDn, clientCert);
|
||||
this.clientCert = clientCert;
|
||||
if (clientCert instanceof X509Certificate) {
|
||||
this.clientCert = (X509Certificate) clientCert;
|
||||
}
|
||||
TimelyUser.UserType userType = DnUtils.isServerDN(subjectDn) ? TimelyUser.UserType.SERVER
|
||||
: TimelyUser.UserType.USER;
|
||||
TimelyUser timelyUser = new TimelyUser(SubjectIssuerDNPair.of(subjectDn, issuerDn), userType, null, null, null,
|
||||
|
||||
@@ -208,7 +208,7 @@ public class DataStoreImpl implements DataStore {
|
||||
}
|
||||
try {
|
||||
this.removeAgeOffIterators(connector, metricsTable);
|
||||
this.applyAgeOffIterator(connector, metricsTable, true);
|
||||
this.applyMetricAgeOffIterator(connector, metricsTable);
|
||||
} catch (Exception e1) {
|
||||
Throwable cause = e1.getCause();
|
||||
if (cause.getMessage().contains("conflict")) {
|
||||
@@ -229,7 +229,7 @@ public class DataStoreImpl implements DataStore {
|
||||
}
|
||||
try {
|
||||
this.removeAgeOffIterators(connector, metaTable);
|
||||
this.applyAgeOffIterator(connector, metaTable, false);
|
||||
this.applyMetaAgeOffIterator(connector, metaTable);
|
||||
} catch (Exception e1) {
|
||||
Throwable cause = e1.getCause();
|
||||
if (cause.getMessage().contains("conflict")) {
|
||||
@@ -282,13 +282,15 @@ public class DataStoreImpl implements DataStore {
|
||||
}
|
||||
}
|
||||
|
||||
private void applyAgeOffIterator(Connector con, String tableName, boolean useIterator) throws Exception {
|
||||
IteratorSetting ageOffIteratorSettings = null;
|
||||
if (useIterator) {
|
||||
ageOffIteratorSettings = new IteratorSetting(100, "ageoff", MetricAgeOffIterator.class, this.ageOff);
|
||||
} else {
|
||||
ageOffIteratorSettings = new IteratorSetting(100, "ageoff", MetricAgeOffFilter.class, this.ageOff);
|
||||
}
|
||||
private void applyMetricAgeOffIterator(Connector con, String tableName) throws Exception {
|
||||
IteratorSetting ageOffIteratorSettings = new IteratorSetting(100, "ageoffmetrics", MetricAgeOffIterator.class,
|
||||
this.ageOff);
|
||||
connector.tableOperations().attachIterator(tableName, ageOffIteratorSettings, AGEOFF_SCOPES);
|
||||
}
|
||||
|
||||
private void applyMetaAgeOffIterator(Connector con, String tableName) throws Exception {
|
||||
IteratorSetting ageOffIteratorSettings = new IteratorSetting(100, "ageoffmeta", MetaAgeOffIterator.class,
|
||||
this.ageOff);
|
||||
connector.tableOperations().attachIterator(tableName, ageOffIteratorSettings, AGEOFF_SCOPES);
|
||||
}
|
||||
|
||||
@@ -438,6 +440,7 @@ public class DataStoreImpl implements DataStore {
|
||||
@Override
|
||||
public SuggestResponse suggest(SuggestRequest request) throws TimelyException {
|
||||
SuggestResponse result = new SuggestResponse();
|
||||
Scanner scanner = null;
|
||||
try {
|
||||
if (request.getType().equals("metrics")) {
|
||||
Range range;
|
||||
@@ -457,7 +460,7 @@ public class DataStoreImpl implements DataStore {
|
||||
end.append(lastBytes, 0, lastBytes.length);
|
||||
range = new Range(start, end);
|
||||
}
|
||||
Scanner scanner = connector.createScanner(metaTable, Authorizations.EMPTY);
|
||||
scanner = connector.createScanner(metaTable, Authorizations.EMPTY);
|
||||
scanner.setRange(range);
|
||||
List<String> metrics = new ArrayList<>();
|
||||
for (Entry<Key, Value> metric : scanner) {
|
||||
@@ -472,6 +475,10 @@ public class DataStoreImpl implements DataStore {
|
||||
LOG.error("Error during suggest: " + ex.getMessage(), ex);
|
||||
throw new TimelyException(HttpResponseStatus.INTERNAL_SERVER_ERROR.code(),
|
||||
"Error during suggest: " + ex.getMessage(), ex.getMessage(), ex);
|
||||
} finally {
|
||||
if (scanner != null) {
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -506,28 +513,34 @@ public class DataStoreImpl implements DataStore {
|
||||
tagPatterns.put(k, Pattern.compile(v));
|
||||
});
|
||||
try {
|
||||
List<Result> resultField = new ArrayList<>();
|
||||
Scanner scanner = connector.createScanner(metaTable, Authorizations.EMPTY);
|
||||
Key start = new Key(Meta.VALUE_PREFIX + msg.getQuery());
|
||||
Key end = start.followingKey(PartialKey.ROW);
|
||||
Range range = new Range(start, end);
|
||||
scanner.setRange(range);
|
||||
tags.keySet().forEach(k -> scanner.fetchColumnFamily(new Text(k)));
|
||||
int total = 0;
|
||||
for (Entry<Key, Value> entry : scanner) {
|
||||
Meta metaEntry = Meta.parse(entry.getKey(), entry.getValue());
|
||||
if (matches(metaEntry.getTagKey(), metaEntry.getTagValue(), tagPatterns)) {
|
||||
if (resultField.size() < msg.getLimit()) {
|
||||
Result r = new Result();
|
||||
r.putTag(metaEntry.getTagKey(), metaEntry.getTagValue());
|
||||
resultField.add(r);
|
||||
final Scanner scanner = connector.createScanner(metaTable, Authorizations.EMPTY);
|
||||
try {
|
||||
List<Result> resultField = new ArrayList<>();
|
||||
Key start = new Key(Meta.VALUE_PREFIX + msg.getQuery());
|
||||
Key end = start.followingKey(PartialKey.ROW);
|
||||
Range range = new Range(start, end);
|
||||
scanner.setRange(range);
|
||||
tags.keySet().forEach(k -> scanner.fetchColumnFamily(new Text(k)));
|
||||
int total = 0;
|
||||
for (Entry<Key, Value> entry : scanner) {
|
||||
Meta metaEntry = Meta.parse(entry.getKey(), entry.getValue());
|
||||
if (matches(metaEntry.getTagKey(), metaEntry.getTagValue(), tagPatterns)) {
|
||||
if (resultField.size() < msg.getLimit()) {
|
||||
Result r = new Result();
|
||||
r.putTag(metaEntry.getTagKey(), metaEntry.getTagValue());
|
||||
resultField.add(r);
|
||||
}
|
||||
total++;
|
||||
}
|
||||
total++;
|
||||
}
|
||||
result.setResults(resultField);
|
||||
result.setTotalResults(total);
|
||||
result.setTime((int) (System.currentTimeMillis() - startMillis));
|
||||
} finally {
|
||||
if (scanner != null) {
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
result.setResults(resultField);
|
||||
result.setTotalResults(total);
|
||||
result.setTime((int) (System.currentTimeMillis() - startMillis));
|
||||
} catch (Exception ex) {
|
||||
LOG.error("Error during lookup: " + ex.getMessage(), ex);
|
||||
throw new TimelyException(HttpResponseStatus.INTERNAL_SERVER_ERROR.code(),
|
||||
@@ -798,70 +811,77 @@ public class DataStoreImpl implements DataStore {
|
||||
|
||||
public Set<Tag> getColumnFamilies(String metric, Map<String, String> requestedTags) throws TableNotFoundException {
|
||||
|
||||
Map<String, String> tags = (requestedTags == null) ? new LinkedHashMap<>() : requestedTags;
|
||||
LOG.trace("Looking for requested tags: {}", tags);
|
||||
Scanner meta = connector.createScanner(metaTable, Authorizations.EMPTY);
|
||||
Text start = new Text(Meta.VALUE_PREFIX + metric);
|
||||
Text end = new Text(Meta.VALUE_PREFIX + metric + "\\x0000");
|
||||
end.append(new byte[] { (byte) 0xff }, 0, 1);
|
||||
meta.setRange(new Range(start, end));
|
||||
// Only look for the meta entries that match our tags, if any
|
||||
boolean onlyFirstRow = false;
|
||||
Entry<String, String> first = null;
|
||||
// Set the columns on the meta scanner based on the first tag
|
||||
// in the set of tags passed in the query. If no tags are present
|
||||
// then we are only going to return the first tag name present in the
|
||||
// meta table.
|
||||
Iterator<Entry<String, String>> tagIter = tags.entrySet().iterator();
|
||||
if (tagIter.hasNext()) {
|
||||
first = tagIter.next();
|
||||
if (isTagValueRegex(first.getValue())) {
|
||||
meta.fetchColumnFamily(new Text(first.getKey()));
|
||||
} else {
|
||||
meta.fetchColumn(new Text(first.getKey()), new Text(first.getValue()));
|
||||
}
|
||||
} else {
|
||||
// grab all of the values found for the first tag for the metric
|
||||
onlyFirstRow = true;
|
||||
}
|
||||
final boolean ONLY_RETURN_FIRST_TAG = onlyFirstRow;
|
||||
Iterator<Entry<Key, Value>> iter = meta.iterator();
|
||||
Iterator<Pair<String, String>> knownKeyValues = new Iterator<Pair<String, String>>() {
|
||||
|
||||
Text firstTag = null;
|
||||
Text tagName = null;
|
||||
Text tagValue = null;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (iter.hasNext()) {
|
||||
Entry<Key, Value> metaEntry = iter.next();
|
||||
if (null == firstTag) {
|
||||
firstTag = metaEntry.getKey().getColumnFamily();
|
||||
}
|
||||
tagName = metaEntry.getKey().getColumnFamily();
|
||||
tagValue = metaEntry.getKey().getColumnQualifier();
|
||||
LOG.trace("Found tag entry {}={}", tagName, tagValue);
|
||||
|
||||
if (ONLY_RETURN_FIRST_TAG && !tagName.equals(firstTag)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
Scanner meta = null;
|
||||
try {
|
||||
Map<String, String> tags = (requestedTags == null) ? new LinkedHashMap<>() : requestedTags;
|
||||
LOG.trace("Looking for requested tags: {}", tags);
|
||||
meta = connector.createScanner(metaTable, Authorizations.EMPTY);
|
||||
Text start = new Text(Meta.VALUE_PREFIX + metric);
|
||||
Text end = new Text(Meta.VALUE_PREFIX + metric + "\\x0000");
|
||||
end.append(new byte[] { (byte) 0xff }, 0, 1);
|
||||
meta.setRange(new Range(start, end));
|
||||
// Only look for the meta entries that match our tags, if any
|
||||
boolean onlyFirstRow = false;
|
||||
Entry<String, String> first = null;
|
||||
// Set the columns on the meta scanner based on the first tag
|
||||
// in the set of tags passed in the query. If no tags are present
|
||||
// then we are only going to return the first tag name present in the
|
||||
// meta table.
|
||||
Iterator<Entry<String, String>> tagIter = tags.entrySet().iterator();
|
||||
if (tagIter.hasNext()) {
|
||||
first = tagIter.next();
|
||||
if (isTagValueRegex(first.getValue())) {
|
||||
meta.fetchColumnFamily(new Text(first.getKey()));
|
||||
} else {
|
||||
meta.fetchColumn(new Text(first.getKey()), new Text(first.getValue()));
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
// grab all of the values found for the first tag for the metric
|
||||
onlyFirstRow = true;
|
||||
}
|
||||
final boolean ONLY_RETURN_FIRST_TAG = onlyFirstRow;
|
||||
Iterator<Entry<Key, Value>> iter = meta.iterator();
|
||||
Iterator<Pair<String, String>> knownKeyValues = new Iterator<Pair<String, String>>() {
|
||||
|
||||
@Override
|
||||
public Pair<String, String> next() {
|
||||
LOG.trace("Returning tag {}={}", tagName, tagValue);
|
||||
return new Pair<>(tagName.toString(), tagValue.toString());
|
||||
Text firstTag = null;
|
||||
Text tagName = null;
|
||||
Text tagValue = null;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (iter.hasNext()) {
|
||||
Entry<Key, Value> metaEntry = iter.next();
|
||||
if (null == firstTag) {
|
||||
firstTag = metaEntry.getKey().getColumnFamily();
|
||||
}
|
||||
tagName = metaEntry.getKey().getColumnFamily();
|
||||
tagValue = metaEntry.getKey().getColumnQualifier();
|
||||
LOG.trace("Found tag entry {}={}", tagName, tagValue);
|
||||
|
||||
if (ONLY_RETURN_FIRST_TAG && !tagName.equals(firstTag)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<String, String> next() {
|
||||
LOG.trace("Returning tag {}={}", tagName, tagValue);
|
||||
return new Pair<>(tagName.toString(), tagValue.toString());
|
||||
}
|
||||
};
|
||||
// Expand the list of tags in the meta table for this metric that
|
||||
// matches
|
||||
// the pattern of the first tag in the query. The resulting set of tags
|
||||
// will be used to fetch specific columns from the metric table.
|
||||
return expandTagValues(first, knownKeyValues);
|
||||
} finally {
|
||||
if (meta != null) {
|
||||
meta.close();
|
||||
}
|
||||
};
|
||||
// Expand the list of tags in the meta table for this metric that
|
||||
// matches
|
||||
// the pattern of the first tag in the query. The resulting set of tags
|
||||
// will be used to fetch specific columns from the metric table.
|
||||
return expandTagValues(first, knownKeyValues);
|
||||
}
|
||||
}
|
||||
|
||||
private void setQueryColumns(ScannerBase scanner, String metric, Map<String, String> tags, Set<Tag> colFamValues)
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package timely.store;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.accumulo.core.data.ByteSequence;
|
||||
import org.apache.accumulo.core.data.Key;
|
||||
import org.apache.accumulo.core.data.Range;
|
||||
import org.apache.accumulo.core.data.Value;
|
||||
import org.apache.accumulo.core.iterators.IteratorEnvironment;
|
||||
import org.apache.accumulo.core.iterators.OptionDescriber;
|
||||
import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
|
||||
import org.apache.accumulo.core.iterators.WrappingIterator;
|
||||
import org.apache.commons.collections4.trie.PatriciaTrie;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import timely.api.model.Meta;
|
||||
|
||||
public class MetaAgeOffIterator extends WrappingIterator implements OptionDescriber {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MetaAgeOffIterator.class);
|
||||
public static final String AGE_OFF_PREFIX = "ageoff.";
|
||||
public static final String DEFAULT_AGEOFF_KEY = "default";
|
||||
|
||||
/* set in init */
|
||||
private PatriciaTrie<Long> ageoffs = null;
|
||||
private Long currentTime = 0L;
|
||||
private Long defaultAgeOff = 0L;
|
||||
private Long minAgeOff = Long.MAX_VALUE;
|
||||
private Long maxAgeOff = Long.MIN_VALUE;
|
||||
|
||||
@Override
|
||||
public SortedKeyValueIterator<Key, Value> deepCopy(IteratorEnvironment env) {
|
||||
MetaAgeOffIterator iter = new MetaAgeOffIterator();
|
||||
iter.ageoffs = this.ageoffs;
|
||||
iter.defaultAgeOff = this.defaultAgeOff;
|
||||
iter.currentTime = this.currentTime;
|
||||
iter.minAgeOff = this.minAgeOff;
|
||||
iter.maxAgeOff = this.maxAgeOff;
|
||||
return iter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(SortedKeyValueIterator<Key, Value> source, Map<String, String> options, IteratorEnvironment env)
|
||||
throws IOException {
|
||||
super.init(source, options, env);
|
||||
validateOptions(options);
|
||||
ageoffs = new PatriciaTrie<>();
|
||||
options.forEach((k, v) -> {
|
||||
if (k.startsWith(AGE_OFF_PREFIX)) {
|
||||
String name = k.substring(AGE_OFF_PREFIX.length());
|
||||
LOG.trace("Adding {} to Trie with value {}", name, Long.parseLong(v));
|
||||
long ageoff = Long.parseLong(v);
|
||||
this.minAgeOff = Math.min(this.minAgeOff, ageoff);
|
||||
this.maxAgeOff = Math.max(this.maxAgeOff, ageoff);
|
||||
ageoffs.put(name, ageoff);
|
||||
}
|
||||
});
|
||||
defaultAgeOff = ageoffs.get(DEFAULT_AGEOFF_KEY);
|
||||
currentTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void next() throws IOException {
|
||||
super.next();
|
||||
skipExpiredData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seek(Range range, Collection<ByteSequence> columnFamilies, boolean inclusive) throws IOException {
|
||||
super.seek(range, columnFamilies, inclusive);
|
||||
skipExpiredData();
|
||||
}
|
||||
|
||||
private void skipExpiredData() throws IOException {
|
||||
|
||||
boolean done = false;
|
||||
while (!done && super.hasTop()) {
|
||||
Key top = super.getTopKey();
|
||||
long dataAge = this.currentTime - top.getTimestamp();
|
||||
// If less than any configured ageoff, then we want to return this K,V
|
||||
if (dataAge < this.minAgeOff) {
|
||||
done = true;
|
||||
} else {
|
||||
String metricName = Meta.parse(top).getMetric();
|
||||
long metaAgeOff = ageoffs.getOrDefault(metricName, defaultAgeOff);
|
||||
if (dataAge > metaAgeOff) {
|
||||
// data beyond ageOff, so skip
|
||||
super.next();
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IteratorOptions describeOptions() {
|
||||
return new IteratorOptions("meta-age-off", "Iterator that ages off meta entries for Timely metrics",
|
||||
Collections.singletonMap(AGE_OFF_PREFIX + DEFAULT_AGEOFF_KEY, "default age off days"),
|
||||
Collections.singletonList("Additional meta age off properties where the value is specified as "
|
||||
+ AGE_OFF_PREFIX
|
||||
+ " the metric name and the value is an integer representing the number of days to keep"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateOptions(Map<String, String> options) {
|
||||
if (null == options.get(AGE_OFF_PREFIX + DEFAULT_AGEOFF_KEY)) {
|
||||
throw new IllegalArgumentException(DEFAULT_AGEOFF_KEY + " must be configured for MetaAgeOffFilter");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +1,123 @@
|
||||
package timely.store;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import org.apache.accumulo.core.client.ClientConfiguration;
|
||||
import org.apache.accumulo.core.client.Connector;
|
||||
import org.apache.accumulo.core.client.Instance;
|
||||
import org.apache.accumulo.core.client.Scanner;
|
||||
import org.apache.accumulo.core.client.ZooKeeperInstance;
|
||||
import org.apache.accumulo.core.client.security.tokens.PasswordToken;
|
||||
import org.apache.accumulo.core.data.Key;
|
||||
import org.apache.accumulo.core.data.Range;
|
||||
import org.apache.accumulo.core.data.Value;
|
||||
import org.apache.accumulo.core.security.Authorizations;
|
||||
import org.apache.commons.configuration.BaseConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import timely.api.model.Meta;
|
||||
import timely.configuration.Accumulo;
|
||||
import timely.configuration.Configuration;
|
||||
|
||||
public class MetaCacheImpl implements MetaCache {
|
||||
|
||||
private static Logger LOG = LoggerFactory.getLogger(MetaCacheImpl.class);
|
||||
private static final Object DUMMY = new Object();
|
||||
private volatile boolean closed = false;
|
||||
private Cache<Meta, Object> cache = null;
|
||||
private Configuration configuration;
|
||||
private Timer timer = new Timer("MetaCacheImpl", true);
|
||||
|
||||
@Override
|
||||
public void init(Configuration config) {
|
||||
long expirationMinutes = config.getMetaCache().getExpirationMinutes();
|
||||
int initialCapacity = config.getMetaCache().getInitialCapacity();
|
||||
long maxCapacity = config.getMetaCache().getMaxCapacity();
|
||||
cache = Caffeine.newBuilder().expireAfterAccess(expirationMinutes, TimeUnit.MINUTES)
|
||||
.initialCapacity(initialCapacity).maximumSize(maxCapacity).build();
|
||||
configuration = config;
|
||||
cache = Caffeine.newBuilder().initialCapacity(1000).build();
|
||||
long cacheRefreshMinutes = configuration.getMetaCache().getCacheRefreshMinutes();
|
||||
if (cacheRefreshMinutes > 0) {
|
||||
timer.schedule(new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
refreshCache(config.getMetaCache().getExpirationMinutes());
|
||||
}
|
||||
}, 60000, cacheRefreshMinutes * 60 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshCache(long expirationMinutes) {
|
||||
long oldestTimestamp = System.currentTimeMillis() - (expirationMinutes * 60 * 1000);
|
||||
final BaseConfiguration apacheConf = new BaseConfiguration();
|
||||
Accumulo accumuloConf = configuration.getAccumulo();
|
||||
apacheConf.setProperty("instance.name", accumuloConf.getInstanceName());
|
||||
apacheConf.setProperty("instance.zookeeper.host", accumuloConf.getZookeepers());
|
||||
final ClientConfiguration aConf = new ClientConfiguration(Collections.singletonList(apacheConf));
|
||||
String metaTable = configuration.getMetaTable();
|
||||
Map<String, Map<String, Long>> metricMap = new HashMap<>();
|
||||
Scanner scanner = null;
|
||||
try {
|
||||
final Instance instance = new ZooKeeperInstance(aConf);
|
||||
Connector connector = instance.getConnector(accumuloConf.getUsername(),
|
||||
new PasswordToken(accumuloConf.getPassword()));
|
||||
scanner = connector.createScanner(metaTable, Authorizations.EMPTY);
|
||||
LOG.debug("Begin scanning " + metaTable);
|
||||
Range metricRange = new Range(new Key(Meta.METRIC_PREFIX), true, new Key(Meta.METRIC_PREFIX + '\0'), false);
|
||||
scanner.setRange(metricRange);
|
||||
Set<String> allMetrics = new TreeSet<>();
|
||||
for (Map.Entry<Key, Value> entry : scanner) {
|
||||
Meta meta = Meta.parse(entry.getKey(), entry.getValue(), Meta.METRIC_PREFIX);
|
||||
allMetrics.add(meta.getMetric());
|
||||
}
|
||||
for (String currMetric : allMetrics) {
|
||||
Key begin = new Key(Meta.VALUE_PREFIX + currMetric);
|
||||
Key end = new Key(Meta.VALUE_PREFIX + currMetric + '\0');
|
||||
Range range = new Range(begin, true, end, false);
|
||||
scanner.setRange(range);
|
||||
Iterator<Map.Entry<Key, Value>> itr = scanner.iterator();
|
||||
boolean maxedOutValues = false;
|
||||
while (itr.hasNext() && !maxedOutValues) {
|
||||
Map.Entry<Key, Value> entry = itr.next();
|
||||
Meta meta = Meta.parse(entry.getKey(), entry.getValue(), Meta.VALUE_PREFIX);
|
||||
String metric = meta.getMetric();
|
||||
String tagKey = meta.getTagKey();
|
||||
Map<String, Long> tagMap = metricMap.get(metric);
|
||||
if (tagMap == null) {
|
||||
tagMap = new HashMap<>();
|
||||
metricMap.put(metric, tagMap);
|
||||
}
|
||||
long numTagValues = tagMap.getOrDefault(tagKey, 0l);
|
||||
if (entry.getKey().getTimestamp() > oldestTimestamp) {
|
||||
tagMap.put(tagKey, ++numTagValues);
|
||||
if (numTagValues <= configuration.getMetaCache().getMaxTagValues()) {
|
||||
cache.put(meta, DUMMY);
|
||||
} else {
|
||||
// found maxTagValues on this refresh, so remove this key
|
||||
cache.invalidate(meta);
|
||||
maxedOutValues = true;
|
||||
}
|
||||
} else {
|
||||
// this entry is more than expirationMinutes old, so remove it
|
||||
cache.invalidate(meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG.debug("Finished scanning " + metaTable);
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
} finally {
|
||||
if (scanner != null) {
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,5 +149,4 @@ public class MetaCacheImpl implements MetaCache {
|
||||
public boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,19 +30,19 @@ public class AuthCacheTest {
|
||||
|
||||
@AfterClass
|
||||
public static void after() {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
AuthCache.setSessionMaxAge(config.getSecurity());
|
||||
AuthCache.configure(config.getSecurity());
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("test", "test1");
|
||||
AuthenticationService.authenticate(token, cookie);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
|
||||
@@ -22,8 +22,8 @@ public class AuthenticationServiceTest {
|
||||
public static void before() {
|
||||
config = TestConfiguration.createMinimalConfigurationForTest();
|
||||
config.getSecurity().setSessionMaxAge(Integer.MAX_VALUE);
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.setSessionMaxAge(config.getSecurity());
|
||||
AuthCache.resetConfiguration();
|
||||
AuthCache.configure(config.getSecurity());
|
||||
}
|
||||
|
||||
@Before
|
||||
@@ -34,7 +34,7 @@ public class AuthenticationServiceTest {
|
||||
|
||||
@AfterClass
|
||||
public static void after() {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Test(expected = BadCredentialsException.class)
|
||||
|
||||
@@ -70,14 +70,14 @@ public class HttpRequestDecoderTest {
|
||||
anonConfig = TestConfiguration.createMinimalConfigurationForTest();
|
||||
anonConfig.getSecurity().setAllowAnonymousHttpAccess(true);
|
||||
cookie = URLEncoder.encode(UUID.randomUUID().toString(), StandardCharsets.UTF_8.name());
|
||||
AuthCache.setSessionMaxAge(config.getSecurity());
|
||||
AuthCache.configure(config.getSecurity());
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("test", "test1");
|
||||
AuthenticationService.authenticate(token, cookie);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void after() {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Before
|
||||
|
||||
@@ -47,12 +47,12 @@ public class BasicAuthLoginRequestHandlerTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void before() throws Exception {
|
||||
AuthCache.setSessionMaxAge(TestConfiguration.createMinimalConfigurationForTest().getSecurity());
|
||||
AuthCache.configure(TestConfiguration.createMinimalConfigurationForTest().getSecurity());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void after() throws Exception {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Before
|
||||
|
||||
@@ -64,14 +64,14 @@ public class WebSocketRequestDecoderTest {
|
||||
anonConfig = TestConfiguration.createMinimalConfigurationForTest();
|
||||
anonConfig.getSecurity().setAllowAnonymousWsAccess(true);
|
||||
cookie = URLEncoder.encode(UUID.randomUUID().toString(), StandardCharsets.UTF_8.name());
|
||||
AuthCache.setSessionMaxAge(config.getSecurity());
|
||||
AuthCache.configure(config.getSecurity());
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("test", "test1");
|
||||
AuthCache.put(cookie, new TimelyPrincipal(TimelyUser.ANONYMOUS_USER));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void after() {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Before
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
package timely.store;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.accumulo.core.data.ByteSequence;
|
||||
import org.apache.accumulo.core.data.Key;
|
||||
import org.apache.accumulo.core.data.Range;
|
||||
import org.apache.accumulo.core.data.Value;
|
||||
import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
|
||||
import org.apache.accumulo.core.iterators.SortedMapIterator;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import timely.adapter.accumulo.MetaAdapter;
|
||||
import timely.adapter.accumulo.MetricAdapter;
|
||||
|
||||
public class MetaAgeOffIteratorTest {
|
||||
|
||||
private static final Long TEST_TIME = System.currentTimeMillis() - 1000;
|
||||
private static final Integer ONE_DAY = 86400000;
|
||||
private static final Value EMPTY_VALUE = new Value(new byte[0]);
|
||||
private static final Collection<ByteSequence> columnFamilies = new ArrayList<>();
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testDefaultMissing() throws Exception {
|
||||
SortedMap<Key, Value> table = new TreeMap<>();
|
||||
SortedKeyValueIterator<Key, Value> source = new SortedMapIterator(table);
|
||||
MetaAgeOffIterator iter = new MetaAgeOffIterator();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
iter.init(source, options, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefault() throws Exception {
|
||||
SortedMap<Key, Value> table = new TreeMap<>();
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 1), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 2), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 3), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 4), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 5), new Value(new byte[0]));
|
||||
|
||||
SortedKeyValueIterator<Key, Value> source = new SortedMapIterator(table);
|
||||
MetaAgeOffIterator iter = new MetaAgeOffIterator();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
options.put(MetaAgeOffIterator.AGE_OFF_PREFIX + "default", Integer.toString(1 * ONE_DAY));
|
||||
iter.init(source, options, null);
|
||||
iter.seek(new Range(), columnFamilies, true);
|
||||
int seen = 0;
|
||||
while (iter.hasTop()) {
|
||||
Key k = iter.getTopKey();
|
||||
Assert.assertTrue(k.getTimestamp() >= TEST_TIME && k.getTimestamp() <= TEST_TIME + 5);
|
||||
seen++;
|
||||
iter.next();
|
||||
}
|
||||
Assert.assertEquals(6, seen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMixed() throws Exception {
|
||||
SortedMap<Key, Value> table = new TreeMap<>();
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME + 1), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME + 2), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME + 3), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME + 4), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME + 5), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 1), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 2), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 3), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 4), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 5), new Value(new byte[0]));
|
||||
|
||||
SortedKeyValueIterator<Key, Value> source = new SortedMapIterator(table);
|
||||
MetaAgeOffIterator iter = new MetaAgeOffIterator();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
options.put(MetaAgeOffIterator.AGE_OFF_PREFIX + "default", Integer.toString(1 * ONE_DAY));
|
||||
iter.init(source, options, null);
|
||||
iter.seek(new Range(), columnFamilies, true);
|
||||
int seen = 0;
|
||||
while (iter.hasTop()) {
|
||||
Key k = iter.getTopKey();
|
||||
Assert.assertTrue(k.getTimestamp() >= TEST_TIME && k.getTimestamp() <= TEST_TIME + 5);
|
||||
seen++;
|
||||
iter.next();
|
||||
}
|
||||
Assert.assertEquals(12, seen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAgeoffMixedMetricKey() throws Exception {
|
||||
SortedMap<Key, Value> table = new TreeMap<>();
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME - (3 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME - (2 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME - (1 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME + (1 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.idle", TEST_TIME + (2 * ONE_DAY)), new Value(new byte[0]));
|
||||
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME - (3 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME - (2 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME - (1 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + (1 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + (2 * ONE_DAY)), new Value(new byte[0]));
|
||||
|
||||
SortedKeyValueIterator<Key, Value> source = new SortedMapIterator(table);
|
||||
MetaAgeOffIterator iter = new MetaAgeOffIterator();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
options.put(MetaAgeOffIterator.AGE_OFF_PREFIX + "default", Integer.toString(1 * ONE_DAY));
|
||||
options.put(MetaAgeOffIterator.AGE_OFF_PREFIX + "sys.cpu.user", Integer.toString(2 * ONE_DAY));
|
||||
iter.init(source, options, null);
|
||||
iter.seek(new Range(), columnFamilies, true);
|
||||
int seen = 0;
|
||||
while (iter.hasTop()) {
|
||||
Key k = iter.getTopKey();
|
||||
Assert.assertTrue(
|
||||
k.getTimestamp() >= (TEST_TIME - (2 * ONE_DAY)) && k.getTimestamp() <= TEST_TIME + (2 * ONE_DAY));
|
||||
seen++;
|
||||
iter.next();
|
||||
}
|
||||
Assert.assertEquals(7, seen);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAgeoffMixedTagKey() throws Exception {
|
||||
SortedMap<Key, Value> table = new TreeMap<>();
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.idle", "tag1", TEST_TIME - (3 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.idle", "tag2", TEST_TIME - (2 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.idle", "tag3", TEST_TIME - (1 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.idle", "tag4", TEST_TIME), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.idle", "tag5", TEST_TIME + (1 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.idle", "tag6", TEST_TIME + (2 * ONE_DAY)), new Value(new byte[0]));
|
||||
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.user", "tag1", TEST_TIME - (3 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.user", "tag2", TEST_TIME - (2 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.user", "tag3", TEST_TIME - (1 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.user", "tag4", TEST_TIME), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.user", "tag5", TEST_TIME + (1 * ONE_DAY)), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createTagKey("sys.cpu.user", "tag6", TEST_TIME + (2 * ONE_DAY)), new Value(new byte[0]));
|
||||
|
||||
SortedKeyValueIterator<Key, Value> source = new SortedMapIterator(table);
|
||||
MetaAgeOffIterator iter = new MetaAgeOffIterator();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
options.put(MetaAgeOffIterator.AGE_OFF_PREFIX + "default", Integer.toString(1 * ONE_DAY));
|
||||
options.put(MetaAgeOffIterator.AGE_OFF_PREFIX + "sys.cpu.user", Integer.toString(2 * ONE_DAY));
|
||||
iter.init(source, options, null);
|
||||
iter.seek(new Range(), columnFamilies, true);
|
||||
int seen = 0;
|
||||
while (iter.hasTop()) {
|
||||
Key k = iter.getTopKey();
|
||||
Assert.assertTrue(
|
||||
k.getTimestamp() >= (TEST_TIME - (2 * ONE_DAY)) && k.getTimestamp() <= TEST_TIME + (2 * ONE_DAY));
|
||||
seen++;
|
||||
iter.next();
|
||||
}
|
||||
Assert.assertEquals(7, seen);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAgeoffMixedValueKey() throws Exception {
|
||||
SortedMap<Key, Value> table = new TreeMap<>();
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.idle", "tag1", "value1", TEST_TIME - (3 * ONE_DAY)),
|
||||
new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.idle", "tag2", "value2", TEST_TIME - (2 * ONE_DAY)),
|
||||
new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.idle", "tag3", "value3", TEST_TIME - (1 * ONE_DAY)),
|
||||
new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.idle", "tag4", "value4", TEST_TIME), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.idle", "tag5", "value5", TEST_TIME + (1 * ONE_DAY)),
|
||||
new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.idle", "tag6", "value6", TEST_TIME + (2 * ONE_DAY)),
|
||||
new Value(new byte[0]));
|
||||
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.user", "tag1", "value1", TEST_TIME - (3 * ONE_DAY)),
|
||||
new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.user", "tag2", "value2", TEST_TIME - (2 * ONE_DAY)),
|
||||
new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.user", "tag3", "value3", TEST_TIME - (1 * ONE_DAY)),
|
||||
new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.user", "tag4", "value4", TEST_TIME), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.user", "tag5", "value5", TEST_TIME + (1 * ONE_DAY)),
|
||||
new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createValueKey("sys.cpu.user", "tag6", "value6", TEST_TIME + (2 * ONE_DAY)),
|
||||
new Value(new byte[0]));
|
||||
|
||||
SortedKeyValueIterator<Key, Value> source = new SortedMapIterator(table);
|
||||
MetaAgeOffIterator iter = new MetaAgeOffIterator();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
options.put(MetaAgeOffIterator.AGE_OFF_PREFIX + "default", Integer.toString(1 * ONE_DAY));
|
||||
options.put(MetaAgeOffIterator.AGE_OFF_PREFIX + "sys.cpu.user", Integer.toString(2 * ONE_DAY));
|
||||
iter.init(source, options, null);
|
||||
iter.seek(new Range(), columnFamilies, true);
|
||||
int seen = 0;
|
||||
while (iter.hasTop()) {
|
||||
Key k = iter.getTopKey();
|
||||
Assert.assertTrue(
|
||||
k.getTimestamp() >= (TEST_TIME - (2 * ONE_DAY)) && k.getTimestamp() <= TEST_TIME + (2 * ONE_DAY));
|
||||
seen++;
|
||||
iter.next();
|
||||
}
|
||||
Assert.assertEquals(7, seen);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeekPastEndKey() throws Exception {
|
||||
SortedMap<Key, Value> table = new TreeMap<>();
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 1), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 2), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 3), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 4), new Value(new byte[0]));
|
||||
table.put(MetaAdapter.createMetricKey("sys.cpu.user", TEST_TIME + 5), new Value(new byte[0]));
|
||||
|
||||
SortedKeyValueIterator<Key, Value> source = new SortedMapIterator(table);
|
||||
MetaAgeOffIterator iter = new MetaAgeOffIterator();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
options.put(MetaAgeOffIterator.AGE_OFF_PREFIX + "default", Integer.toString(1));
|
||||
iter.init(source, options, null);
|
||||
iter.seek(new Range(new Key("sys.cpu.user"), true,
|
||||
new Key(MetricAdapter.encodeRowKey("sys.cpu.user", TEST_TIME + 3), new byte[0], new byte[0],
|
||||
new byte[0], TEST_TIME + 3),
|
||||
true), columnFamilies, true);
|
||||
int seen = 0;
|
||||
while (iter.hasTop()) {
|
||||
Key k = iter.getTopKey();
|
||||
Assert.assertTrue(k.getTimestamp() >= TEST_TIME && k.getTimestamp() <= TEST_TIME + 5);
|
||||
seen++;
|
||||
iter.next();
|
||||
}
|
||||
Assert.assertEquals(0, seen);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public class OneWaySSLBase extends QueryBase {
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -87,7 +87,7 @@ public class OneWaySSLBasicAuthAccessIT extends OneWaySSLBase {
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -156,7 +156,7 @@ public class TwoWaySSLFailureIT extends QueryBase {
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Test(expected = UnauthorizedUserException.class)
|
||||
|
||||
@@ -160,7 +160,7 @@ public class TwoWaySSLIT extends QueryBase {
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -135,7 +135,7 @@ public class TwoWaySSLOpenSSLIT extends QueryBase {
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -43,7 +43,7 @@ public class TcpClientIT extends OneWaySSLBase {
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -57,7 +57,7 @@ public class UdpClientIT extends MacITBase {
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -73,7 +73,7 @@ public class WebSocketClientIT extends OneWaySSLBase {
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
s.shutdown();
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
public void testWorkflow(WebSocketSubscriptionClient client) throws Exception {
|
||||
|
||||
@@ -8,6 +8,7 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -20,6 +21,13 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.select.Elements;
|
||||
@@ -130,12 +138,44 @@ public class HttpApiIT extends OneWaySSLBase {
|
||||
String metrics = "https://localhost:54322/api/metrics";
|
||||
// Test prefix matching
|
||||
String result = query(metrics, "application/json");
|
||||
assertEquals(expected, result);
|
||||
|
||||
Gson gson = new Gson();
|
||||
JsonObject response = gson.fromJson(result, JsonObject.class);
|
||||
JsonArray metricsArray = response.getAsJsonArray("metrics");
|
||||
assertEquals(3, metricsArray.size());
|
||||
|
||||
for (JsonElement e : metricsArray) {
|
||||
JsonObject metricObject = e.getAsJsonObject();
|
||||
String metricName = metricObject.get("metric").getAsString();
|
||||
Iterator<JsonElement> tagItr = metricObject.get("tags").getAsJsonArray().iterator();
|
||||
Multimap<String, String> tagMap = HashMultimap.create();
|
||||
while (tagItr.hasNext()) {
|
||||
JsonObject tagObject = tagItr.next().getAsJsonObject();
|
||||
tagMap.put(tagObject.get("key").getAsString(), tagObject.get("value").getAsString());
|
||||
}
|
||||
switch (metricName) {
|
||||
case "sys.cpu.user":
|
||||
assertEquals(2, tagMap.size());
|
||||
assertTrue(CollectionUtils.isEqualCollection(Arrays.asList("value1"), tagMap.get("tag1")));
|
||||
assertTrue(CollectionUtils.isEqualCollection(Arrays.asList("value2"), tagMap.get("tag2")));
|
||||
break;
|
||||
case "sys.cpu.idle":
|
||||
assertEquals(2, tagMap.size());
|
||||
assertTrue(CollectionUtils.isEqualCollection(Arrays.asList("value3"), tagMap.get("tag3")));
|
||||
assertTrue(CollectionUtils.isEqualCollection(Arrays.asList("value4"), tagMap.get("tag4")));
|
||||
break;
|
||||
case "zzzz":
|
||||
assertEquals(1, tagMap.size());
|
||||
assertTrue(CollectionUtils.isEqualCollection(Arrays.asList("localhost"), tagMap.get("host")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
s.shutdown();
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -50,7 +50,7 @@ public class TimelyTcpIT extends MacITBase {
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -64,7 +64,7 @@ public class TimelyUdpIT extends MacITBase {
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -176,7 +176,7 @@ public class WebSocketIT extends OneWaySSLBase {
|
||||
|
||||
@AfterClass
|
||||
public static void after() {
|
||||
AuthCache.resetSessionMaxAge();
|
||||
AuthCache.resetConfiguration();
|
||||
}
|
||||
|
||||
private EventLoopGroup group = null;
|
||||
|
||||
Reference in new issue
Block a user