diff --git a/.dlc.json b/.dlc.json index f2b124ebc1a9..9ee4908aa72a 100644 --- a/.dlc.json +++ b/.dlc.json @@ -5,6 +5,9 @@ }, { "pattern": "^https://github.com/apache/skywalking/blob/master/changes/changes-x.y.z.md$" + }, + { + "pattern": "^https://dist.apache.org/repos/dist/dev/skywalking/x.y.z$" } ], "timeout": "10s", diff --git a/.gitignore b/.gitignore index 181769e4cd3a..c442cb72fbb3 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ OALLexer.tokens /test/jacoco/classes /test/jacoco/*.exec oap-server/oal-grammar/**/gen/ +test/jacoco diff --git a/CHANGES.md b/CHANGES.md index 2581d65f6011..97231e22682b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -24,6 +24,10 @@ Release Notes. * Collect and report agent starting / shutdown events. * Support jedis pipeline in jedis-2.x-plugin. * Fix apm-toolkit-log4j-2.x-activation no trace Id in async log. +* Replace hbase-1.x-plugin with hbase-1.x-2.x-plugin to adapt hbase client 2.x +* Remove the close_before_method and close_after_method parameters of custom-enhance-plugin to avoid memory leaks. +* Fix bug that springmvn-annotation-4.x-plugin, witness class does not exist in some versions. +* Fix NullPointerException with `ReactiveRequestHolder.getHeaders`. #### OAP-Backend * Allow user-defined `JAVA_OPTS` in the startup script. @@ -57,6 +61,8 @@ Release Notes. * Support metrics grouped by scope labelValue in MAL, no need global same labelValue as before. * Add functions in MAL to filter metrics according to the metric value. * Optimize the self monitoring grafana dashboard. +* Enhance the export service. +* Add function `retagByK8sMeta` and opt type `K8sRetagType.Pod2Service` in MAL for k8s to relate pods and services. #### UI * Update selector scroller to show in all pages. @@ -73,6 +79,7 @@ Release Notes. * Fix log pages tags column not updated. * Fix the problem that the footer and topology group is shaded when the topology radiation is displayed. * When the topology radiation chart is displayed, the corresponding button should be highlighted. +* Refactor the route mapping, Dynamically import routing components, Improve first page loading performance. #### Documentation * Polish documentation due to we have covered all tracing, logging, and metrics fields. diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ids/GlobalIdGenerator.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ids/GlobalIdGenerator.java index 21a85b0a6a74..0adb77d3d34f 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ids/GlobalIdGenerator.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ids/GlobalIdGenerator.java @@ -18,8 +18,9 @@ package org.apache.skywalking.apm.agent.core.context.ids; -import java.util.Random; import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + import org.apache.skywalking.apm.util.StringUtil; public final class GlobalIdGenerator { @@ -58,7 +59,6 @@ private static class IDContext { // Just for considering time-shift-back only. private long runRandomTimestamp; private int lastRandomValue; - private Random random; private IDContext(long lastTimestamp, short threadSeq) { this.lastTimestamp = lastTimestamp; @@ -74,11 +74,8 @@ private long timestamp() { if (currentTimeMillis < lastTimestamp) { // Just for considering time-shift-back by Ops or OS. @hanahmily 's suggestion. - if (random == null) { - random = new Random(); - } if (runRandomTimestamp != currentTimeMillis) { - lastRandomValue = random.nextInt(); + lastRandomValue = ThreadLocalRandom.current().nextInt(); runRandomTimestamp = currentTimeMillis; } return lastRandomValue; diff --git a/apm-sniffer/apm-sdk-plugin/hbase-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml similarity index 91% rename from apm-sniffer/apm-sdk-plugin/hbase-1.x-plugin/pom.xml rename to apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml index 415be34578be..8913440eed00 100644 --- a/apm-sniffer/apm-sdk-plugin/hbase-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml @@ -26,12 +26,12 @@ 8.5.0-SNAPSHOT - apm-hbase-1.x-plugin + apm-hbase-1.x-2.x-plugin jar - hbase-1.x-plugin + hbase-1.x-2.x-plugin - 1.4.9 + 2.4.1 diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/mock/MockRedisClusterClientConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTable100Interceptor.java similarity index 51% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/mock/MockRedisClusterClientConstructorInterceptor.java rename to apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTable100Interceptor.java index 1e807afa8636..3b3528a8e2a2 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/mock/MockRedisClusterClientConstructorInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTable100Interceptor.java @@ -16,24 +16,26 @@ * */ -package org.apache.skywalking.apm.plugin.lettuce.v5.mock; +package org.apache.skywalking.apm.plugin.hbase; -import io.lettuce.core.RedisURI; +import java.lang.reflect.Field; +import java.util.Properties; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.client.ClusterConnection; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; -import org.apache.skywalking.apm.agent.core.context.util.PeerFormat; +import org.apache.skywalking.apm.util.StringUtil; -public class MockRedisClusterClientConstructorInterceptor implements InstanceConstructorInterceptor { +public class HTable100Interceptor extends HTableInterceptor { @Override - public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { - @SuppressWarnings("unchecked") Iterable redisURIs = (Iterable) allArguments[1]; - MockRedisClusterClient redisClusterClient = (MockRedisClusterClient) objInst; - StringBuilder peer = new StringBuilder(); - for (RedisURI redisURI : redisURIs) { - peer.append(redisURI.getHost()).append(":").append(redisURI.getPort()).append(";"); + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + Configuration configuration = ((ClusterConnection) allArguments[1]).getConfiguration(); + Field field = configuration.getClass().getDeclaredField("overlay"); + field.setAccessible(true); + Properties properties = (Properties) field.get(configuration); + String value = properties.getProperty("hbase.zookeeper.quorum"); + if (StringUtil.isNotBlank(value)) { + objInst.setSkyWalkingDynamicField(value); } - EnhancedInstance optionsInst = redisClusterClient.getOptions(); - optionsInst.setSkyWalkingDynamicField(PeerFormat.shorten(peer.toString())); } } diff --git a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTable200Interceptor.java b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTable200Interceptor.java new file mode 100644 index 000000000000..be23cba60029 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTable200Interceptor.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.hbase; + +import java.lang.reflect.Field; +import java.util.Properties; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.client.ClusterConnection; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.util.StringUtil; + +public class HTable200Interceptor extends HTableInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + Configuration configuration = ((ClusterConnection) allArguments[0]).getConfiguration(); + Field field = configuration.getClass().getDeclaredField("overlay"); + field.setAccessible(true); + Properties properties = (Properties) field.get(configuration); + String value = properties.getProperty("hbase.zookeeper.quorum"); + if (StringUtil.isNotBlank(value)) { + objInst.setSkyWalkingDynamicField(value); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTable220Interceptor.java b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTable220Interceptor.java new file mode 100644 index 000000000000..4d8e224410a0 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTable220Interceptor.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.hbase; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Properties; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.client.Connection; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.util.StringUtil; + +public class HTable220Interceptor extends HTableInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + Method getConfigurationMethod = Connection.class.getMethod("getConfiguration"); + Configuration configuration = (Configuration) getConfigurationMethod.invoke(allArguments[0]); + Field field = configuration.getClass().getDeclaredField("overlay"); + field.setAccessible(true); + Properties properties = (Properties) field.get(configuration); + String value = properties.getProperty("hbase.zookeeper.quorum"); + if (StringUtil.isNotBlank(value)) { + objInst.setSkyWalkingDynamicField(value); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/hbase-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTableInterceptor.java b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTableInterceptor.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/hbase-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTableInterceptor.java rename to apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/HTableInterceptor.java diff --git a/apm-sniffer/apm-sdk-plugin/hbase-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/define/HTableInstrumentation.java b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/define/HTableInstrumentation.java similarity index 58% rename from apm-sniffer/apm-sdk-plugin/hbase-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/define/HTableInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/define/HTableInstrumentation.java index af73efc9ac6f..7ca5d20d8f5a 100644 --- a/apm-sniffer/apm-sdk-plugin/hbase-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/define/HTableInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hbase/define/HTableInstrumentation.java @@ -47,11 +47,22 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +/** + * There have several interceptors to adapt different version hbase client. We use the minimal compatible version to + * name the Interceptor. eg. + *

HTable100Interceptor, 100 means version 1.0.0, compatible with version [1.0.0, 2.0.0)

+ *

HTable200Interceptor, 200 means version 2.0.0, compatible with version [2.0.0, 2.2.0)

+ *

HTable220Interceptor, 220 means version 2.2.0, compatible with version [2.2.0, )

+ */ public class HTableInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { private static final String ENHANCE_CLASS = "org.apache.hadoop.hbase.client.HTable"; private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.hbase.HTableInterceptor"; + private static final String INTERCEPT_CLASS_100 = "org.apache.skywalking.apm.plugin.hbase.HTable100Interceptor"; + private static final String INTERCEPT_CLASS_200 = "org.apache.skywalking.apm.plugin.hbase.HTable200Interceptor"; + private static final String INTERCEPT_CLASS_220 = "org.apache.skywalking.apm.plugin.hbase.HTable220Interceptor"; @Override protected ClassMatch enhanceClass() { @@ -60,16 +71,44 @@ protected ClassMatch enhanceClass() { @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return new ConstructorInterceptPoint[]{ + return new ConstructorInterceptPoint[] { + // compatible with version [1.0.0, 2.0.0) new ConstructorInterceptPoint() { @Override public ElementMatcher getConstructorMatcher() { - return takesArguments(6); + return takesArguments(6) + .and(takesArgumentWithType(0, "org.apache.hadoop.hbase.TableName")); } @Override public String getConstructorInterceptor() { - return INTERCEPT_CLASS; + return INTERCEPT_CLASS_100; + } + }, + // compatible with version [2.0.0, 2.2.0) + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(5) + .and(takesArgumentWithType(0, "org.apache.hadoop.hbase.client.ClusterConnection")); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPT_CLASS_200; + } + }, + // compatible with version [2.2.0, ) + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(5) + .and(takesArgumentWithType(0, "org.apache.hadoop.hbase.client.ConnectionImplementation")); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPT_CLASS_220; } } }; @@ -77,13 +116,16 @@ public String getConstructorInterceptor() { @Override public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[]{ + return new InstanceMethodsInterceptPoint[] { new InstanceMethodsInterceptPoint() { @Override public ElementMatcher getMethodsMatcher() { - return named("delete").or(named("put")).or(isPublic().and(named("get"))) - .or(named("getScanner").and(takesArguments(1)) - .and(takesArgument(0, named("org.apache.hadoop.hbase.client.Scan")))); + return named("delete") + .or(named("put")) + .or(isPublic().and(named("get"))) + .or(named("getScanner") + .and(takesArguments(1)) + .and(takesArgument(0, named("org.apache.hadoop.hbase.client.Scan")))); } @Override() diff --git a/apm-sniffer/apm-sdk-plugin/hbase-1.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/resources/skywalking-plugin.def similarity index 90% rename from apm-sniffer/apm-sdk-plugin/hbase-1.x-plugin/src/main/resources/skywalking-plugin.def rename to apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/resources/skywalking-plugin.def index aad5b0238c0a..7e1acdded3b4 100644 --- a/apm-sniffer/apm-sdk-plugin/hbase-1.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/src/main/resources/skywalking-plugin.def @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -hbase-1.x=org.apache.skywalking.apm.plugin.hbase.define.HTableInstrumentation \ No newline at end of file +hbase-1.x/2.x=org.apache.skywalking.apm.plugin.hbase.define.HTableInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorTest.java index 6cb512d2b70b..36132331c27d 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorTest.java @@ -33,8 +33,8 @@ import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.plugin.lettuce.v5.mock.MockClientOptions; import org.apache.skywalking.apm.plugin.lettuce.v5.mock.MockRedisClusterClient; -import org.apache.skywalking.apm.plugin.lettuce.v5.mock.MockRedisClusterClientConstructorInterceptor; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; import org.hamcrest.core.Is; @@ -120,11 +120,13 @@ public void testOnHugeClusterConsumerConfig() { redisURIs.add(RedisURI.create("localhost", i)); } MockRedisClusterClient mockRedisClusterClient = new MockRedisClusterClient(); - MockRedisClusterClientConstructorInterceptor constructorInterceptor = new MockRedisClusterClientConstructorInterceptor(); + MockClientOptions options = new MockClientOptions(); + mockRedisClusterClient.setOptions(options); + RedisClusterClientConstructorInterceptor constructorInterceptor = new RedisClusterClientConstructorInterceptor(); constructorInterceptor.onConstruct(mockRedisClusterClient, new Object[] { null, redisURIs }); - assertThat(mockRedisClusterClient.getOptions().getSkyWalkingDynamicField().toString().length(), Is.is(200)); + assertThat(options.getSkyWalkingDynamicField().toString().length(), Is.is(200)); } } diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/mock/MockClientOptions.java b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/mock/MockClientOptions.java new file mode 100644 index 000000000000..cb2a89e6f132 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/mock/MockClientOptions.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.lettuce.v5.mock; + +import io.lettuce.core.cluster.ClusterClientOptions; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +public class MockClientOptions extends ClusterClientOptions implements EnhancedInstance { + + private Object object; + + public MockClientOptions() { + this(ClusterClientOptions.builder()); + } + + protected MockClientOptions(Builder builder) { + super(builder); + } + + @Override + public Object getSkyWalkingDynamicField() { + return object; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.object = value; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/mock/MockRedisClusterClient.java b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/mock/MockRedisClusterClient.java index b0f584e58b07..b97132b21d8d 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/mock/MockRedisClusterClient.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/mock/MockRedisClusterClient.java @@ -18,41 +18,20 @@ package org.apache.skywalking.apm.plugin.lettuce.v5.mock; +import io.lettuce.core.cluster.RedisClusterClient; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; -public class MockRedisClusterClient implements EnhancedInstance { +public class MockRedisClusterClient extends RedisClusterClient implements EnhancedInstance { - private Object ms; - - private EnhancedInstance options = new EnhancedInstance() { - private Object os; - - @Override - public Object getSkyWalkingDynamicField() { - return os; - } - - @Override - public void setSkyWalkingDynamicField(Object value) { - this.os = value; - } - }; - - public EnhancedInstance getOptions() { - return options; - } - - public void setOptions(EnhancedInstance options) { - this.options = options; - } + private Object object; @Override public Object getSkyWalkingDynamicField() { - return ms; + return object; } @Override public void setSkyWalkingDynamicField(Object value) { - this.ms = value; + this.object = value; } } diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 202ddef85078..2676756b95d2 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -97,7 +97,7 @@ mariadb-2.x-plugin influxdb-2.x-plugin baidu-brpc-plugin - hbase-1.x-plugin + hbase-1.x-2.x-plugin graphql-plugin xxl-job-2.x-plugin thrift-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/ControllerForLowVersionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/ControllerForLowVersionInstrumentation.java index 81b57780fe6a..c27cfc860ee1 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/ControllerForLowVersionInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/ControllerForLowVersionInstrumentation.java @@ -25,7 +25,7 @@ import static net.bytebuddy.matcher.ElementMatchers.any; public class ControllerForLowVersionInstrumentation extends AbstractControllerInstrumentation { - public static final String WITNESS_CLASSES_LOW_VERSION = "org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer"; + public static final String WITNESS_CLASSES_LOW_VERSION = "org.springframework.web.method.HandlerMethodSelector"; public static final String ENHANCE_ANNOTATION = "org.springframework.stereotype.Controller"; diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/RestControllerForLowVersionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/RestControllerForLowVersionInstrumentation.java index 97863ec69b8d..55e62ec55f32 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/RestControllerForLowVersionInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/RestControllerForLowVersionInstrumentation.java @@ -25,7 +25,7 @@ import static net.bytebuddy.matcher.ElementMatchers.any; public class RestControllerForLowVersionInstrumentation extends AbstractControllerInstrumentation { - public static final String WITNESS_CLASSES_LOW_VERSION = "org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer"; + public static final String WITNESS_CLASSES_LOW_VERSION = "org.springframework.web.method.HandlerMethodSelector"; public static final String ENHANCE_ANNOTATION = "org.springframework.web.bind.annotation.RestController"; diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ReactiveRequestHolder.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ReactiveRequestHolder.java index d7130775cb82..b5e1876ae0ff 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ReactiveRequestHolder.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ReactiveRequestHolder.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.springframework.http.server.reactive.ServerHttpRequest; @@ -37,7 +38,11 @@ public String getHeader(final String headerName) { @Override public Enumeration getHeaders(final String headerName) { - return Collections.enumeration(this.serverHttpRequest.getHeaders().get(headerName)); + List values = this.serverHttpRequest.getHeaders().get(headerName); + if (values == null) { + return Collections.enumeration(Collections.EMPTY_LIST); + } + return Collections.enumeration(values); } @Override diff --git a/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/CustomizeConfiguration.java b/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/CustomizeConfiguration.java index 2c1864b8c5ff..ba48a9280e80 100644 --- a/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/CustomizeConfiguration.java +++ b/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/CustomizeConfiguration.java @@ -172,22 +172,6 @@ private Map resolverMethodNodeDesc(String className, Node method Constants.XML_ELEMENT_OPERATION_NAME) .getNodeValue()); } - if (methodDesc.getAttributes().getNamedItem(Constants.XML_ELEMENT_CLOSE_BEFORE_METHOD) != null) { - MethodConfiguration.setCloseBeforeMethod(configuration, Boolean.valueOf(methodDesc.getAttributes() - .getNamedItem( - Constants.XML_ELEMENT_CLOSE_BEFORE_METHOD) - .getNodeValue())); - } else { - MethodConfiguration.setCloseBeforeMethod(configuration, false); - } - if (methodDesc.getAttributes().getNamedItem(Constants.XML_ELEMENT_CLOSE_AFTER_METHOD) != null) { - MethodConfiguration.setCloseAfterMethod(configuration, Boolean.valueOf(methodDesc.getAttributes() - .getNamedItem( - Constants.XML_ELEMENT_CLOSE_AFTER_METHOD) - .getNodeValue())); - } else { - MethodConfiguration.setCloseAfterMethod(configuration, false); - } if (methodDesc.getAttributes().getNamedItem(Constants.XML_ELEMENT_METHOD_IS_STATIC) != null) { MethodConfiguration.setStatic(configuration, Boolean.valueOf(methodDesc.getAttributes() .getNamedItem( diff --git a/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/MethodConfiguration.java b/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/MethodConfiguration.java index 89d544b88c95..375672ed90bc 100644 --- a/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/MethodConfiguration.java +++ b/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/MethodConfiguration.java @@ -55,14 +55,6 @@ static void setOperationName(Map configuration, String operation configuration.put(Constants.CONFIGURATION_ATTRIBUTE_OPERATION_NAME, operationName); } - static void setCloseBeforeMethod(Map configuration, Boolean closeBeforeMethod) { - configuration.put(Constants.CONFIGURATION_ATTRIBUTE_CLOSE_BEFORE_METHOD, closeBeforeMethod); - } - - static void setCloseAfterMethod(Map configuration, Boolean closeAfterMethod) { - configuration.put(Constants.CONFIGURATION_ATTRIBUTE_CLOSE_AFTER_METHOD, closeAfterMethod); - } - static void setStatic(Map configuration, Boolean isStatic) { configuration.put(Constants.CONFIGURATION_ATTRIBUTE_IS_STATIC, isStatic); } @@ -123,14 +115,6 @@ public static String getOperationName(Map configuration) { return (String) configuration.get(Constants.CONFIGURATION_ATTRIBUTE_OPERATION_NAME); } - public static boolean isCloseBeforeMethod(Map configuration) { - return (Boolean) configuration.get(Constants.CONFIGURATION_ATTRIBUTE_CLOSE_BEFORE_METHOD); - } - - public static boolean isCloseAfterMethod(Map configuration) { - return (Boolean) configuration.get(Constants.CONFIGURATION_ATTRIBUTE_CLOSE_AFTER_METHOD); - } - @SuppressWarnings("unchecked") public static Map getTags(Map configuration) { return (Map) configuration.get(Constants.CONFIGURATION_ATTRIBUTE_TAGS); diff --git a/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/constants/Constants.java b/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/constants/Constants.java index b9f18634d56d..87e5c8759eee 100644 --- a/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/constants/Constants.java +++ b/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/constants/Constants.java @@ -42,10 +42,6 @@ public class Constants { public static final String XML_ELEMENT_OPERATION_NAME = "operation_name"; - public static final String XML_ELEMENT_CLOSE_BEFORE_METHOD = "close_before_method"; - - public static final String XML_ELEMENT_CLOSE_AFTER_METHOD = "close_after_method"; - public static final String XML_ELEMENT_OPERATION_NAME_SUFFIX = "operation_name_suffix"; public static final String XML_ELEMENT_TAG = "tag"; @@ -70,10 +66,6 @@ public class Constants { public static final String CONFIGURATION_ATTRIBUTE_OPERATION_NAME = "CONFIGURATION_ATTRIBUTE_OPERATION_NAME"; - public static final String CONFIGURATION_ATTRIBUTE_CLOSE_BEFORE_METHOD = "CONFIGURATION_ATTRIBUTE_CLOSE_BEFORE_METHOD"; - - public static final String CONFIGURATION_ATTRIBUTE_CLOSE_AFTER_METHOD = "CONFIGURATION_ATTRIBUTE_CLOSE_AFTER_METHOD"; - public static final String CONFIGURATION_ATTRIBUTE_OPERATION_NAME_SUFFIXES = "CONFIGURATION_ATTRIBUTE_OPERATION_NAME_SUFFIXES"; public static final String CONFIGURATION_ATTRIBUTE_TAGS = "CONFIGURATION_ATTRIBUTE_TAGS"; diff --git a/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/interceptor/BaseInterceptorMethods.java b/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/interceptor/BaseInterceptorMethods.java index 109766349fc5..dcef43ec71f6 100644 --- a/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/interceptor/BaseInterceptorMethods.java +++ b/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/interceptor/BaseInterceptorMethods.java @@ -35,56 +35,52 @@ class BaseInterceptorMethods { void beforeMethod(Method method, Object[] allArguments) { Map configuration = CustomizeConfiguration.INSTANCE.getConfiguration(method); - if (!MethodConfiguration.isCloseBeforeMethod(configuration)) { - String operationName = MethodConfiguration.getOperationName(configuration); - Map context = CustomizeExpression.evaluationContext(allArguments); - if (context == null || context.isEmpty()) { - ContextManager.createLocalSpan(operationName); - } else { + String operationName = MethodConfiguration.getOperationName(configuration); + Map context = CustomizeExpression.evaluationContext(allArguments); + if (context == null || context.isEmpty()) { + ContextManager.createLocalSpan(operationName); + } else { - Map tags = MethodConfiguration.getTags(configuration); - Map spanTags = new HashMap(); - Map logs = MethodConfiguration.getLogs(configuration); - Map spanLogs = new HashMap(); + Map tags = MethodConfiguration.getTags(configuration); + Map spanTags = new HashMap(); + Map logs = MethodConfiguration.getLogs(configuration); + Map spanLogs = new HashMap(); - List operationNameSuffixes = MethodConfiguration.getOperationNameSuffixes(configuration); - StringBuilder operationNameSuffix = new StringBuilder(); - if (operationNameSuffixes != null && !operationNameSuffixes.isEmpty()) { - for (String expression : operationNameSuffixes) { - operationNameSuffix.append(Constants.OPERATION_NAME_SEPARATOR); - operationNameSuffix.append(CustomizeExpression.parseExpression(expression, context)); - } + List operationNameSuffixes = MethodConfiguration.getOperationNameSuffixes(configuration); + StringBuilder operationNameSuffix = new StringBuilder(); + if (operationNameSuffixes != null && !operationNameSuffixes.isEmpty()) { + for (String expression : operationNameSuffixes) { + operationNameSuffix.append(Constants.OPERATION_NAME_SEPARATOR); + operationNameSuffix.append(CustomizeExpression.parseExpression(expression, context)); } - if (tags != null && !tags.isEmpty()) { - for (Map.Entry expression: tags.entrySet()) { - spanTags.put(expression.getKey(), CustomizeExpression.parseExpression(expression.getValue(), context)); - } + } + if (tags != null && !tags.isEmpty()) { + for (Map.Entry expression : tags.entrySet()) { + spanTags.put(expression.getKey(), CustomizeExpression.parseExpression(expression.getValue(), context)); } - if (logs != null && !logs.isEmpty()) { - for (Map.Entry entries : logs.entrySet()) { - String expression = logs.get(entries.getKey()); - spanLogs.put(entries.getKey(), CustomizeExpression.parseExpression(expression, context)); - } + } + if (logs != null && !logs.isEmpty()) { + for (Map.Entry entries : logs.entrySet()) { + String expression = logs.get(entries.getKey()); + spanLogs.put(entries.getKey(), CustomizeExpression.parseExpression(expression, context)); } - operationName = operationNameSuffix.insert(0, operationName).toString(); + } + operationName = operationNameSuffix.insert(0, operationName).toString(); - AbstractSpan span = ContextManager.createLocalSpan(operationName); - if (!spanTags.isEmpty()) { - for (Map.Entry tag : spanTags.entrySet()) { - span.tag(Tags.ofKey(tag.getKey()), tag.getValue()); - } - } - if (!spanLogs.isEmpty()) { - span.log(System.currentTimeMillis(), spanLogs); + AbstractSpan span = ContextManager.createLocalSpan(operationName); + if (!spanTags.isEmpty()) { + for (Map.Entry tag : spanTags.entrySet()) { + span.tag(Tags.ofKey(tag.getKey()), tag.getValue()); } } + if (!spanLogs.isEmpty()) { + span.log(System.currentTimeMillis(), spanLogs); + } } } void afterMethod(Method method) { - if (!MethodConfiguration.isCloseAfterMethod(CustomizeConfiguration.INSTANCE.getConfiguration(method))) { - ContextManager.stopSpan(); - } + ContextManager.stopSpan(); } void handleMethodException(Throwable t) { diff --git a/docs/en/concepts-and-designs/backend-overview.md b/docs/en/concepts-and-designs/backend-overview.md index a60b3aaed245..1889b70ef0f2 100644 --- a/docs/en/concepts-and-designs/backend-overview.md +++ b/docs/en/concepts-and-designs/backend-overview.md @@ -1,17 +1,16 @@ # Observability Analysis Platform -We define SkyWalking as an Observability Analysis Platform, which provides a full observability to the services running -either in brown zone, or green zone, even hybrid. +SkyWalking is an Observability Analysis Platform that provides full observability to services running in both brown and green zones, as well as services using a hybrid model. ## Capabilities -SkyWalking covers all 3 fields of observability, including, **Tracing**, **Metrics** and **logging**. +SkyWalking covers all 3 areas of observability, including, **Tracing**, **Metrics** and **Logging**. -- **Tracing**. Including, SkyWalking native data formats. Zipkin v1,v2 data formats and Jaeger data formats. -- **Metrics**. SkyWalking integrates with Service Mesh platforms, such as Istio, Envoy, Linkerd, to provide observability from data panel -or control panel. Also, SkyWalking native agents can run in metrics mode, which highly improve the performance. -- **Logging**. Including the logs collected from disk or through network. Native agent could bind the tracing context with logs automatically, +- **Tracing**. SkyWalking native data formats, including Zipkin v1 and v2, as well as Jaeger. +- **Metrics**. SkyWalking integrates with Service Mesh platforms, such as Istio, Envoy, and Linkerd, to build observability into the data panel +or control panel. Also, SkyWalking native agents can run in the metrics mode, which greatly improves performances. +- **Logging**. Includes logs collected from disk or through network. Native agents could bind the tracing context with logs automatically, or use SkyWalking to bind the trace and log through the text content. -There are 3 powerful and native language engines to focus on analyzing observability data from above fields. -1. [Observability Analysis Language](oal.md) processes the native traces and service mesh data. -1. [Meter Analysis Language](mal.md) does metrics calculation for native meter data, and adopts stable and widely used metrics system, such as Prometheus and OpenTelemetry. -1. [Log Analysis Language](lal.md) focuses on log contents and collaborate with Meter Analysis Language. \ No newline at end of file +There are 3 powerful and native language engines designed to analyze observability data from the above areas. +1. [Observability Analysis Language](oal.md) processes native traces and service mesh data. +1. [Meter Analysis Language](mal.md) is responsible for metrics calculation for native meter data, and adopts a stable and widely used metrics system, such as Prometheus and OpenTelemetry. +1. [Log Analysis Language](lal.md) focuses on log contents and collaborate with Meter Analysis Language. diff --git a/docs/en/concepts-and-designs/event.md b/docs/en/concepts-and-designs/event.md index 87c9174b79cb..6ea5c93d658e 100644 --- a/docs/en/concepts-and-designs/event.md +++ b/docs/en/concepts-and-designs/event.md @@ -2,43 +2,43 @@ SkyWalking already supports the three pillars of observability, namely logs, metrics, and traces. In reality, a production system experiences many other events that may affect the performance of the system, such as upgrading, rebooting, chaos testing, etc. -Although some of these events are reflected in the logs, there are many other events that can not. Hence, SkyWalking provides a more native way to collect these events. -This doc covers the design of how SkyWalking collects events and what events look like in SkyWalking. +Although some of these events are reflected in the logs, many others are not. Hence, SkyWalking provides a more native way to collect these events. +This doc details how SkyWalking collects events and what events look like in SkyWalking. ## How to Report Events -SkyWalking backend supports three protocols to collect events, gRPC, HTTP, and Kafka. Any agent or CLI that implements one of these protocols can report events to SkyWalking. +The SkyWalking backend supports three protocols to collect events: gRPC, HTTP, and Kafka. Any agent or CLI that implements one of these protocols can report events to SkyWalking. Currently, the officially supported clients to report events are: -- [ ] Java Agent Toolkit: Use the Java agent toolkit to report events from inside the applications. -- [x] SkyWalking CLI: Use the CLI to report events from the command line interface. -- [ ] Kubernetes Event Exporter: Deploy an event exporter to refine and report Kubernetes events. +- [ ] Java Agent Toolkit: Using the Java agent toolkit to report events within the applications. +- [x] SkyWalking CLI: Using the CLI to report events from the command line interface. +- [ ] Kubernetes Event Exporter: Deploying an event exporter to refine and report Kubernetes events. -## Event Definition +## Event Definitions -An event contains the following fields. The definitions of event can be found at the [protocol repo](https://github.com/apache/skywalking-data-collect-protocol/tree/master/event) +An event contains the following fields. The definitions of event can be found at the [protocol repo](https://github.com/apache/skywalking-data-collect-protocol/tree/master/event). ### UUID -Unique ID of the event. Because an event may span a long period of time, the UUID is necessary to associate the start time with the end time of the same event. +Unique ID of the event. Since an event may span a long period of time, the UUID is necessary to associate the start time with the end time of the same event. ### Source -The source object that the event occurs on. In the concepts of SkyWalking, the object is typically service, service instance, etc. +The source object on which the event occurs. In SkyWalking, the object is typically a service, service instance, etc. ### Name -The name of the event. For example, `Start`, `Stop`, `Crash`, `Reboot`, `Upgrade` etc. +Name of the event. For example, `Start`, `Stop`, `Crash`, `Reboot`, `Upgrade`, etc. ### Type -The type of the event. This field is friendly for UI visualization, where events of type `Normal` are considered as normal operations, -while `Error` is considered as unexpected operations, such as `Crash` events, therefore we can mark them with different colors to be easier identified. +Type of the event. This field is friendly for UI visualization, where events of type `Normal` are considered normal operations, +while `Error` is considered unexpected operations, such as `Crash` events. Marking them with different colors allows us to more easily identify them. ### Message The detail of the event that describes why this event happened. This should be a one-line message that briefly describes why the event is reported. Examples of an `Upgrade` event may be something like `Upgrade from ${from_version} to ${to_version}`. -It's NOT encouraged to include the detailed logs of this event, such as the exception stack trace. +It's NOT recommended to include the detailed logs of this event, such as the exception stack trace. ### Parameters @@ -50,7 +50,7 @@ The start time of the event. This field is mandatory when an event occurs. ### End Time -The end time of the event. This field may be empty if the event has not stopped yet, otherwise it should be a valid timestamp after `startTime`. +The end time of the event. This field may be empty if the event has not ended yet, otherwise there should be a valid timestamp after `startTime`. -**NOTE:** When reporting an event, you typically call the report function twice, one for starting of the event and the other one for ending of the event, with the same UUID. -There are also cases where you have both the start time and end time already, for example, when exporting events from a 3rd-party system, the start time and end time are already known so that you can call the report function only once. +**NOTE:** When reporting an event, you typically call the report function twice, the first time for starting of the event and the second time for ending of the event, both with the same UUID. +There are also cases where you would already have both the start time and end time. For example, when exporting events from a third-party system, the start time and end time are already known so you may simply call the report function once. diff --git a/docs/en/concepts-and-designs/lal.md b/docs/en/concepts-and-designs/lal.md index c3f1af4b96eb..ac6e1b764e1d 100644 --- a/docs/en/concepts-and-designs/lal.md +++ b/docs/en/concepts-and-designs/lal.md @@ -1,32 +1,31 @@ # Log Analysis Language Log Analysis Language (LAL) in SkyWalking is essentially a Domain-Specific Language (DSL) to analyze logs. You can use -LAL to parse, extract, and save the logs, as well as collaborate the logs with traces (by extracting the trace id, -segment id and span id) and metrics (by generating metrics from the logs and send them to the meter system). +LAL to parse, extract, and save the logs, as well as collaborate the logs with traces (by extracting the trace ID, +segment ID and span ID) and metrics (by generating metrics from the logs and sending them to the meter system). -The LAL config files are in YAML format, and are located under directory `lal`, you can +The LAL config files are in YAML format, and are located under directory `lal`. You can set `log-analyzer/default/lalFiles` in the `application.yml` file or set environment variable `SW_LOG_LAL_FILES` to activate specific LAL config files. ## Filter A filter is a group of [parser](#parser), [extractor](#extractor) and [sink](#sink). Users can use one or more filters -to organize their processing logics. Every piece of log will be sent to all filters in an LAL rule. The piece of log -sent into the filter is available as property `log` in the LAL, therefore you can access the log service name -via `log.service`, for all available fields of `log`, please refer to [the protocol definition](https://github.com/apache/skywalking-data-collect-protocol/blob/master/logging/Logging.proto#L41). +to organize their processing logic. Every piece of log will be sent to all filters in an LAL rule. A piece of log +sent to the filter is available as property `log` in the LAL, therefore you can access the log service name +via `log.service`. For all available fields of `log`, please refer to [the protocol definition](https://github.com/apache/skywalking-data-collect-protocol/blob/master/logging/Logging.proto#L41). All components are executed sequentially in the orders they are declared. ### Global Functions -There are functions globally available that you can use them in all components (i.e. parsers, extractors, and sinks) -when needed. +Globally available functions may be used them in all components (i.e. parsers, extractors, and sinks) where necessary. - `abort` By default, all components declared are executed no matter what flags (`dropped`, `saved`, etc.) have been set. There are cases where you may want the filter chain to stop earlier when specified conditions are met. `abort` function aborts -the remaining filter chain from where it's declared, all the remaining components won't be executed at all. +the remaining filter chain from where it's declared, and all the remaining components won't be executed at all. `abort` function serves as a fast-fail mechanism in LAL. ```groovy @@ -47,8 +46,8 @@ Parsers are responsible for parsing the raw logs into structured data in SkyWalk types of parsers at the moment, namely `json`, `yaml`, and `text`. When a piece of log is parsed, there is a corresponding property available, called `parsed`, injected by LAL. -Property `parsed` is typically a map, containing all the fields parsed from the raw logs, for example, if the parser -is `json` / `yaml`, `parsed` is a map containing all the key-values in the `json` / `yaml`, if the parser is `text` +Property `parsed` is typically a map, containing all the fields parsed from the raw logs. For example, if the parser +is `json` / `yaml`, `parsed` is a map containing all the key-values in the `json` / `yaml`; if the parser is `text` , `parsed` is a map containing all the captured groups and their values (for `regexp` and `grok`). All parsers share the following options: @@ -108,7 +107,7 @@ filter { - `grok` (TODO) -Because grok Java library has performance issue, we need some investigations and benchmark on it. Contributions are +We're aware of certains performance issues in the grok Java library, and so we're currently conducting investigations and benchmarking. Contributions are welcome. ### Extractor @@ -155,8 +154,7 @@ The unit of `timestamp` is millisecond. - `tag` -`tag` extracts the tags from the `parsed` result, and set them into the `LogData`. The form of this extractor is -something like `tag key1: value, key2: value2`, you can use the properties of `parsed` as both keys and values. +`tag` extracts the tags from the `parsed` result, and set them into the `LogData`. The form of this extractor should look something like this: `tag key1: value, key2: value2`. You may use the properties of `parsed` as both keys and values. ```groovy filter { @@ -171,9 +169,9 @@ filter { - `metrics` -`metrics` extracts / generates metrics from the logs, and sends the generated metrics to the meter system, you can +`metrics` extracts / generates metrics from the logs, and sends the generated metrics to the meter system. You may configure [MAL](mal.md) for further analysis of these metrics. The dedicated MAL config files are under -directory `log-mal-rules`, you can set `log-analyzer/default/malFiles` to enable configured files. +directory `log-mal-rules`, and you can set `log-analyzer/default/malFiles` to enable configured files. ```yaml # application.yml @@ -209,7 +207,7 @@ filter { } ``` -The extractor above generates a metrics named `log_count`, with tag key `level` and value `1`, after this, you can +The extractor above generates a metrics named `log_count`, with tag key `level` and value `1`. After that, you can configure MAL rules to calculate the log count grouping by logging level like this: ```yaml @@ -223,7 +221,7 @@ metrics: ``` -The other metrics generated is `http_response_time`, so that you can configure MAL rules to generate more useful metrics +The other metrics generated is `http_response_time`, so you can configure MAL rules to generate more useful metrics like percentiles. ```yaml @@ -237,17 +235,17 @@ metrics: ### Sink Sinks are the persistent layer of the LAL. By default, all the logs of each filter are persisted into the storage. -However, there are some mechanisms that allow you to selectively save some logs, or even drop all the logs after you've +However, some mechanisms allow you to selectively save some logs, or even drop all the logs after you've extracted useful information, such as metrics. #### Sampler -Sampler allows you to save the logs in a sampling manner. Currently, sampling strategy `rateLimit` is supported, welcome -to contribute more sampling strategies. If multiple samplers are specified, the last one determines the final sampling -result, see examples in [Enforcer](#enforcer). +Sampler allows you to save the logs in a sampling manner. Currently, the sampling strategy `rateLimit` is supported. We welcome +contributions on more sampling strategies. If multiple samplers are specified, the last one determines the final sampling +result. See examples in [Enforcer](#enforcer). -`rateLimit` samples `n` logs at most in 1 second. `rateLimit("SamplerID")` requires an ID for the sampler, sampler -declarations with the same ID share the same sampler instance, and thus share the same `qps`, resetting logics. +`rateLimit` samples `n` logs at a maximum rate of 1 second. `rateLimit("SamplerID")` requires an ID for the sampler. Sampler +declarations with the same ID share the same sampler instance, thus sharing the same `qps` and resetting logic. Examples: @@ -273,8 +271,8 @@ filter { #### Dropper -Dropper is a special sink, meaning that all the logs are dropped without any exception. This is useful when you want to -drop debugging logs, +Dropper is a special sink, meaning that all logs are dropped without any exception. This is useful when you want to +drop debugging logs. ```groovy filter { @@ -292,7 +290,7 @@ filter { } ``` -or you have multiple filters, some of which are for extracting metrics, only one of them needs to be persisted. +Or if you have multiple filters, some of which are for extracting metrics, only one of them has to be persisted. ```groovy filter { // filter A: this is for persistence @@ -319,9 +317,9 @@ filter { // filter B: #### Enforcer -Enforcer is another special sink that forcibly samples the log, a typical use case of enforcer is when you have -configured a sampler and want to save some logs forcibly, for example, to save error logs even if the sampling mechanism -is configured. +Enforcer is another special sink that forcibly samples the log. A typical use case of enforcer is when you have +configured a sampler and want to save some logs forcibly, such as to save error logs even if the sampling mechanism +has been configured. ```groovy filter { diff --git a/docs/en/concepts-and-designs/mal.md b/docs/en/concepts-and-designs/mal.md index 7770b6203843..9a478d581b53 100644 --- a/docs/en/concepts-and-designs/mal.md +++ b/docs/en/concepts-and-designs/mal.md @@ -57,6 +57,31 @@ For example, this filters all instance_trace_count samples for values >= 33: ``` instance_trace_count.valueGreaterEqual(33) ``` +### Tag manipulator +MAL provides tag manipulators to change(add/delete/update) tags and their values. + +#### K8s +MAL supports using the metadata of k8s to manipulate the tags and their values. +This feature requires OAP Server to have the authority to access the K8s's `API Server`. + +##### retagByK8sMeta +`retagByK8sMeta(newLabelName, K8sRetagType, existingLabelName, namespaceLabelName)`. Add a new tag to the sample family based on an existing label's value. Provide several internal converting types, including +- K8sRetagType.Pod2Service + +Add a tag to the sample by using `service` as the key, `$serviceName.$namespace` as the value, by the given value of the tag key, which represents the name of a pod. + +For example: +``` +container_cpu_usage_seconds_total{namespace=default, container=my-nginx, cpu=total, pod=my-nginx-5dc4865748-mbczh} 2 +``` +Expression: +``` +container_cpu_usage_seconds_total.retagByK8sMeta('service' , K8sRetagType.Pod2Service , 'pod' , 'namespace') +``` +Output: +``` +container_cpu_usage_seconds_total{namespace=default, container=my-nginx, cpu=total, pod=my-nginx-5dc4865748-mbczh, service='nginx-service.default'} 2 +``` ### Binary operators @@ -186,6 +211,7 @@ Examples: #### time `time()`. returns the number of seconds since January 1, 1970 UTC. + ## Down Sampling Operation MAL should instruct meter-system how to do downsampling for metrics. It doesn't only refer to aggregate raw samples to `minute` level, but also hints data from `minute` to higher levels, for instance, `hour` and `day`. diff --git a/docs/en/guides/Plugin-test.md b/docs/en/guides/Plugin-test.md index e690eb50bcde..fd9def0348de 100644 --- a/docs/en/guides/Plugin-test.md +++ b/docs/en/guides/Plugin-test.md @@ -105,7 +105,6 @@ File Name | Descriptions | entryService | The entrance endpoint(URL) for test case access. Required. (HTTP Method: GET) | healthCheck | The health check endpoint(URL) for test case access. Required. (HTTP Method: HEAD) | startScript | Path of start up script. Required in `type: jvm` only. -| framework | Case name. | runningMode | Running mode whether with the optional plugin, options, `default`(default), `with_optional`, `with_bootstrap` | withPlugins | Plugin selector rule. eg:`apm-spring-annotation-plugin-*.jar`. Required when `runningMode=with_optional` or `runningMode=with_bootstrap`. | environment | Same as `docker-compose#environment`. @@ -131,7 +130,6 @@ type: entryService: healthCheck: startScript: -framework: runningMode: withPlugins: environment: diff --git a/docs/en/setup/backend/grafana-cluster.json b/docs/en/setup/backend/grafana-cluster.json index 3b688bef1f7b..ba99a904cd3d 100644 --- a/docs/en/setup/backend/grafana-cluster.json +++ b/docs/en/setup/backend/grafana-cluster.json @@ -1643,7 +1643,7 @@ "targets": [ { "expr": "increase(mesh_analysis_error_count{job=\"$job\"}[1m]) ", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -1924,7 +1924,7 @@ "targets": [ { "expr": "increase(meter_analysis_error_count{job=\"$job\"}[1m]) ", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -2205,7 +2205,7 @@ "targets": [ { "expr": "increase(log_analysis_error_count{job=\"$job\"}[1m]) ", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -2486,7 +2486,7 @@ "targets": [ { "expr": "increase(event_error_count{job=\"$job\"}[1m]) ", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -2767,7 +2767,7 @@ "targets": [ { "expr": "increase(browser_perf_data_analysis_error_count{job=\"$job\"}[1m]) ", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -3048,7 +3048,7 @@ "targets": [ { "expr": "increase(browser_error_log_analysis_error_count{job=\"$job\"}[1m]) ", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -3329,7 +3329,7 @@ "targets": [ { "expr": "increase(metrics_fetcher_error_count{job=\"$job\"}[1m]) ", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", diff --git a/docs/en/setup/backend/grafana-instance.json b/docs/en/setup/backend/grafana-instance.json index e085d4951ed5..874595a59367 100644 --- a/docs/en/setup/backend/grafana-instance.json +++ b/docs/en/setup/backend/grafana-instance.json @@ -1880,7 +1880,7 @@ "targets": [ { "expr": "increase(trace_in_latency_sum{instance=\"$instance\",job=\"$job\"}[1m])", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -2157,7 +2157,7 @@ "targets": [ { "expr": "increase(mesh_analysis_latency_sum{instance=\"$instance\",job=\"$job\"}[1m])", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -2434,7 +2434,7 @@ "targets": [ { "expr": "increase(meter_in_latency_sum{instance=\"$instance\",job=\"$job\"}[1m])", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -2711,7 +2711,7 @@ "targets": [ { "expr": "increase(log_in_latency_sum{instance=\"$instance\",job=\"$job\"}[1m])", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -2988,7 +2988,7 @@ "targets": [ { "expr": "increase(event_in_latency_sum{instance=\"$instance\",job=\"$job\"}[1m])", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -3265,7 +3265,7 @@ "targets": [ { "expr": "increase(browser_perf_data_in_latency_sum{instance=\"$instance\",job=\"$job\"}[1m])", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -3542,7 +3542,7 @@ "targets": [ { "expr": "increase(browser_error_log_in_latency_sum{instance=\"$instance\",job=\"$job\"}[1m])", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", @@ -3819,7 +3819,7 @@ "targets": [ { "expr": "increase(metrics_fetcher_latency_sum{instance=\"$instance\",job=\"$job\"}[1m])", - "format": "heatmap", + "format": "time_series", "hide": false, "instant": false, "interval": "1m", diff --git a/docs/en/setup/backend/metrics-exporter.md b/docs/en/setup/backend/metrics-exporter.md index b190517864b8..04ca4929bf76 100644 --- a/docs/en/setup/backend/metrics-exporter.md +++ b/docs/en/setup/backend/metrics-exporter.md @@ -31,7 +31,12 @@ message ExportMetricValue { } message SubscriptionsResp { - repeated string metricNames = 1; + repeated SubscriptionMetric metrics = 1; +} + +message SubscriptionMetric { + string metricName = 1; + EventType eventType = 2; } enum ValueType { @@ -40,6 +45,13 @@ enum ValueType { MULTI_LONG = 2; } +enum EventType { + // The metrics aggregated in this bulk, not include the existing persistent data. + INCREMENT = 0; + // Final result of the metrics at this moment. + TOTAL = 1; +} + message SubscriptionReq { } @@ -61,8 +73,8 @@ exporter: ## For target exporter service ### subscription implementation -Return the expected metrics name list, all the names must match the OAL script definition. Return empty list, if you want -to export all metrics. +Return the expected metrics name list with event type(increment or total), all the names must match the OAL/MAL script definition. +Return empty list, if you want to export all metrics in increment event type. ### export implementation Stream service, all subscribed metrics will be sent to here, based on OAP core schedule. Also, if the OAP deployed as cluster, diff --git a/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md b/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md index 1a0f3ef228f1..a3abcfa55869 100644 --- a/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md +++ b/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md @@ -30,6 +30,8 @@ The gRPC report could forward the collected logs to SkyWalking OAP server, or [S ```properties log4j.rootLogger=INFO,CustomAppender log4j.appender.CustomAppender=org.apache.skywalking.apm.toolkit.log.log4j.v1.x.log.GRPCLogClientAppender +log4j.appender.CustomAppender.layout=org.apache.log4j.PatternLayout +log4j.appender.CustomAppender.layout.ConversionPattern=[%t] %-5p %c %x - %m%n ``` * Add config of the plugin or use default diff --git a/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-2.x.md b/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-2.x.md index 30f16b17f40e..5dcc4d326ff0 100644 --- a/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-2.x.md +++ b/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-2.x.md @@ -111,7 +111,9 @@ The gRPC report could forward the collected logs to SkyWalking OAP server, or [S * Add `GRPCLogClientAppender` in log4j2.xml ```xml - + + + ``` * Add config of the plugin or use default diff --git a/docs/en/setup/service-agent/java-agent/Application-toolkit-logback-1.x.md b/docs/en/setup/service-agent/java-agent/Application-toolkit-logback-1.x.md index 3e35113bfcb0..c5d4e14ba786 100644 --- a/docs/en/setup/service-agent/java-agent/Application-toolkit-logback-1.x.md +++ b/docs/en/setup/service-agent/java-agent/Application-toolkit-logback-1.x.md @@ -118,7 +118,13 @@ The gRPC reporter could forward the collected logs to SkyWalking OAP server, or * Add `GRPCLogClientAppender` in logback.xml ```xml - + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n + + + ``` * Add config of the plugin or use default diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md b/docs/en/setup/service-agent/java-agent/Plugin-list.md index b8e7c2bd6dd6..41ba14d95ef0 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -23,7 +23,7 @@ - grpc-1.x - gson-2.8.x - h2-1.x -- hbase-1.x +- hbase-1.x/2.x - httpasyncclient-4.x - httpclient-3.x - httpclient-4.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index dfc01aa05a36..6b9ee71862b8 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -83,7 +83,7 @@ metrics based on the tracing data. * [Cassandra](https://github.com/apache/cassandra) 3.x * [cassandra-java-driver](https://github.com/datastax/java-driver) 3.7.0-3.7.2 * HBase - * [hbase-client](https://github.com/apache/hbase) HTable 1.x + * [hbase-client](https://github.com/apache/hbase) HTable 1.0.0-2.4.2 * Service Discovery * [Netflix Eureka](https://github.com/Netflix/eureka) * Distributed Coordination diff --git a/oap-server/analyzer/meter-analyzer/pom.xml b/oap-server/analyzer/meter-analyzer/pom.xml index 5b990368ad6f..d4723b79fc0d 100644 --- a/oap-server/analyzer/meter-analyzer/pom.xml +++ b/oap-server/analyzer/meter-analyzer/pom.xml @@ -33,7 +33,6 @@ server-core ${project.version} - org.codehaus.groovy groovy @@ -42,6 +41,11 @@ io.vavr vavr + + io.kubernetes + client-java + ${kubernetes.version} +
\ No newline at end of file diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/Analyzer.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/Analyzer.java index 7c39d87ff4ca..4b9975e780a5 100644 --- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/Analyzer.java +++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/Analyzer.java @@ -34,6 +34,7 @@ import org.apache.skywalking.oap.meter.analyzer.dsl.Result; import org.apache.skywalking.oap.meter.analyzer.dsl.Sample; import org.apache.skywalking.oap.meter.analyzer.dsl.SampleFamily; +import org.apache.skywalking.oap.meter.analyzer.k8s.K8sInfoRegistry; import org.apache.skywalking.oap.server.core.analysis.NodeType; import org.apache.skywalking.oap.server.core.analysis.TimeBucket; import org.apache.skywalking.oap.server.core.analysis.manual.endpoint.EndpointTraffic; @@ -219,6 +220,10 @@ private void init(final ExpressionParsingContext ctx) { } } createMetric(ctx.getScopeType(), metricType.literal, ctx.getDownsampling()); + + if (ctx.isRetagByK8sMeta()) { + K8sInfoRegistry.getInstance().start(); + } } private void createMetric(final ScopeType scopeType, diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/DSL.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/DSL.java index 45fa7eeb0c9f..65a93aeb7ff2 100644 --- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/DSL.java +++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/DSL.java @@ -21,7 +21,9 @@ import groovy.lang.Binding; import groovy.lang.GroovyShell; import groovy.util.DelegatingScript; +import org.apache.skywalking.oap.meter.analyzer.dsl.tagOpt.K8sRetagType; import org.codehaus.groovy.control.CompilerConfiguration; +import org.codehaus.groovy.control.customizers.ImportCustomizer; /** * DSL combines methods to parse groovy based DSL expression. @@ -37,6 +39,9 @@ public final class DSL { public static Expression parse(final String expression) { CompilerConfiguration cc = new CompilerConfiguration(); cc.setScriptBaseClass(DelegatingScript.class.getName()); + ImportCustomizer icz = new ImportCustomizer(); + icz.addImport("K8sRetagType", K8sRetagType.class.getName()); + cc.addCompilationCustomizers(icz); GroovyShell sh = new GroovyShell(new Binding(), cc); DelegatingScript script = (DelegatingScript) sh.parse(expression); return new Expression(expression, script); diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/ExpressionParsingContext.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/ExpressionParsingContext.java index 2a421fc406a3..f571ccae39a4 100644 --- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/ExpressionParsingContext.java +++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/ExpressionParsingContext.java @@ -61,7 +61,6 @@ static Optional get() { List samples; boolean isHistogram; - int[] percentiles; Set aggregationLabels; @@ -72,6 +71,11 @@ static Optional get() { ScopeType scopeType; + /** + * Mark whether the retagByK8sMeta func in expressions is active + */ + boolean isRetagByK8sMeta; + /** * Get labels no scope related. * diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/SampleFamily.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/SampleFamily.java index be53356197d0..efe2dca0da0c 100644 --- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/SampleFamily.java +++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/SampleFamily.java @@ -38,6 +38,7 @@ import org.apache.skywalking.oap.meter.analyzer.dsl.EntityDescription.EntityDescription; import org.apache.skywalking.oap.meter.analyzer.dsl.EntityDescription.InstanceEntityDescription; import org.apache.skywalking.oap.meter.analyzer.dsl.EntityDescription.ServiceEntityDescription; +import org.apache.skywalking.oap.meter.analyzer.dsl.tagOpt.K8sRetagType; import org.apache.skywalking.oap.server.core.UnexpectedException; import org.apache.skywalking.oap.server.core.analysis.meter.MeterEntity; import org.apache.skywalking.oap.server.core.analysis.meter.ScopeType; @@ -310,6 +311,19 @@ public SampleFamily tag(Closure cl) { ); } + /* k8s retags*/ + public SampleFamily retagByK8sMeta(String newLabelName, K8sRetagType type, String existingLabelName, String namespaceLabelName) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(newLabelName)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(existingLabelName)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(namespaceLabelName)); + ExpressionParsingContext.get().ifPresent(ctx -> ctx.isRetagByK8sMeta = true); + if (this == EMPTY) { + return EMPTY; + } + + return SampleFamily.build(this.context, type.execute(samples, newLabelName, existingLabelName, namespaceLabelName)); + } + public SampleFamily histogram() { return histogram("le", this.context.defaultHistogramBucketUnit); } diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/tagOpt/K8sRetagType.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/tagOpt/K8sRetagType.java new file mode 100644 index 000000000000..5b179f69ca97 --- /dev/null +++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/tagOpt/K8sRetagType.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.meter.analyzer.dsl.tagOpt; + +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import java.util.Arrays; +import java.util.Map; +import org.apache.skywalking.oap.meter.analyzer.dsl.Sample; +import org.apache.skywalking.oap.meter.analyzer.k8s.K8sInfoRegistry; + +public enum K8sRetagType implements Retag { + + Pod2Service { + @Override + public Sample[] execute(final Sample[] ss, + final String newLabelName, + final String existingLabelName, + final String namespaceLabelName) { + Sample[] samples = Arrays.stream(ss).map(sample -> { + String podName = sample.getLabels().get(existingLabelName); + String namespace = sample.getLabels().get(namespaceLabelName); + if (!Strings.isNullOrEmpty(podName) && !Strings.isNullOrEmpty(namespace)) { + String serviceName = K8sInfoRegistry.getInstance().findServiceName(namespace, podName); + if (!Strings.isNullOrEmpty(serviceName)) { + Map labels = Maps.newHashMap(sample.getLabels()); + labels.put(newLabelName, serviceName); + return sample.toBuilder().labels(ImmutableMap.copyOf(labels)).build(); + } + } + return sample; + }).toArray(Sample[]::new); + return samples; + } + } +} diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/tagOpt/Retag.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/tagOpt/Retag.java new file mode 100644 index 000000000000..e02a9713c0a2 --- /dev/null +++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/tagOpt/Retag.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.meter.analyzer.dsl.tagOpt; + +import org.apache.skywalking.oap.meter.analyzer.dsl.Sample; + +public interface Retag { + Sample[] execute(Sample[] ss, String newLabelName, String existingLabelName, String namespaceLabelName); +} diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/k8s/K8sInfoRegistry.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/k8s/K8sInfoRegistry.java new file mode 100644 index 000000000000..aa49b051eab2 --- /dev/null +++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/k8s/K8sInfoRegistry.java @@ -0,0 +1,230 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.meter.analyzer.k8s; + +import com.google.common.base.Strings; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import io.kubernetes.client.informer.ResourceEventHandler; +import io.kubernetes.client.informer.SharedInformerFactory; +import io.kubernetes.client.openapi.Configuration; +import io.kubernetes.client.openapi.apis.CoreV1Api; +import io.kubernetes.client.openapi.models.V1PodList; +import io.kubernetes.client.openapi.models.V1Service; +import io.kubernetes.client.openapi.models.V1ServiceList; +import io.kubernetes.client.util.Config; +import io.kubernetes.client.openapi.ApiClient; +import io.kubernetes.client.openapi.models.V1Pod; +import java.util.Collection; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; + +import static java.util.Objects.isNull; +import static java.util.Optional.ofNullable; + +@Slf4j +public class K8sInfoRegistry { + + private final static K8sInfoRegistry INSTANCE = new K8sInfoRegistry(); + private final AtomicBoolean isStarted = new AtomicBoolean(false); + private final Map namePodMap = new ConcurrentHashMap<>(); + protected final Map nameServiceMap = new ConcurrentHashMap<>(); + private final Map podServiceMap = new ConcurrentHashMap<>(); + private ExecutorService executor; + private static final String SEPARATOR = "."; + + public static K8sInfoRegistry getInstance() { + return INSTANCE; + } + + private void init() { + executor = Executors.newCachedThreadPool( + new ThreadFactoryBuilder() + .setNameFormat("K8sInfoRegistry-%d") + .setDaemon(true) + .build() + ); + } + + @SneakyThrows + public void start() { + if (isStarted.compareAndSet(false, true)) { + init(); + final ApiClient apiClient = Config.defaultClient(); + apiClient.setHttpClient(apiClient.getHttpClient() + .newBuilder() + .readTimeout(0, TimeUnit.SECONDS) + .build()); + Configuration.setDefaultApiClient(apiClient); + + final CoreV1Api coreV1Api = new CoreV1Api(); + final SharedInformerFactory factory = new SharedInformerFactory(executor); + listenServiceEvents(coreV1Api, factory); + listenPodEvents(coreV1Api, factory); + factory.startAllRegisteredInformers(); + } + } + + private void listenServiceEvents(final CoreV1Api coreV1Api, final SharedInformerFactory factory) { + factory.sharedIndexInformerFor( + params -> coreV1Api.listServiceForAllNamespacesCall( + null, + null, + null, + null, + null, + null, + params.resourceVersion, + 300, + params.watch, + null + ), + V1Service.class, + V1ServiceList.class + ).addEventHandler(new ResourceEventHandler() { + @Override + public void onAdd(final V1Service service) { + addService(service); + } + + @Override + public void onUpdate(final V1Service oldService, final V1Service newService) { + addService(newService); + } + + @Override + public void onDelete(final V1Service service, final boolean deletedFinalStateUnknown) { + removeService(service); + } + }); + } + + private void listenPodEvents(final CoreV1Api coreV1Api, final SharedInformerFactory factory) { + factory.sharedIndexInformerFor( + params -> coreV1Api.listPodForAllNamespacesCall( + null, + null, + null, + null, + null, + null, + params.resourceVersion, + 300, + params.watch, + null + ), + V1Pod.class, + V1PodList.class + ).addEventHandler(new ResourceEventHandler() { + @Override + public void onAdd(final V1Pod pod) { + addPod(pod); + } + + @Override + public void onUpdate(final V1Pod oldPod, final V1Pod newPod) { + addPod(newPod); + } + + @Override + public void onDelete(final V1Pod pod, final boolean deletedFinalStateUnknown) { + removePod(pod); + } + }); + } + + protected void addService(final V1Service service) { + ofNullable(service.getMetadata()).ifPresent( + metadata -> nameServiceMap.put(metadata.getName() + SEPARATOR + metadata.getNamespace(), service) + ); + recompose(); + } + + protected void removeService(final V1Service service) { + ofNullable(service.getMetadata()).ifPresent( + metadata -> nameServiceMap.remove(metadata.getName() + SEPARATOR + metadata.getNamespace()) + ); + recompose(); + } + + protected void addPod(final V1Pod pod) { + ofNullable(pod.getMetadata()).ifPresent( + metadata -> namePodMap.put(metadata.getName() + SEPARATOR + metadata.getNamespace(), pod)); + + recompose(); + } + + protected void removePod(final V1Pod pod) { + ofNullable(pod.getMetadata()).ifPresent( + metadata -> namePodMap.remove(metadata.getName() + SEPARATOR + metadata.getNamespace())); + + ofNullable(pod.getMetadata()).ifPresent( + metadata -> podServiceMap.remove(metadata.getName() + SEPARATOR + metadata.getNamespace())); + } + + private void recompose() { + namePodMap.forEach((podName, pod) -> { + nameServiceMap.forEach((serviceName, service) -> { + if (isNull(pod.getMetadata()) || isNull(service.getMetadata()) || isNull(service.getSpec())) { + return; + } + + Map selector = service.getSpec().getSelector(); + Map labels = pod.getMetadata().getLabels(); + + if (isNull(labels) || isNull(selector)) { + return; + } + + String podNamespace = pod.getMetadata().getNamespace(); + String serviceNamespace = service.getMetadata().getNamespace(); + + if (Strings.isNullOrEmpty(podNamespace) || Strings.isNullOrEmpty( + serviceNamespace) || !podNamespace.equals(serviceNamespace)) { + return; + } + + if (hasIntersection(selector.entrySet(), labels.entrySet())) { + podServiceMap.put(podName, serviceName); + } + }); + }); + } + + public String findServiceName(String namespace, String podName) { + return this.podServiceMap.get(podName + SEPARATOR + namespace); + } + + private boolean hasIntersection(Collection o, Collection c) { + Objects.requireNonNull(o); + Objects.requireNonNull(c); + for (final Object value : o) { + if (c.contains(value)) { + return true; + } + } + return false; + } +} diff --git a/oap-server/analyzer/meter-analyzer/src/test/java/org/apache/skywalking/oap/meter/analyzer/dsl/K8sTagTest.java b/oap-server/analyzer/meter-analyzer/src/test/java/org/apache/skywalking/oap/meter/analyzer/dsl/K8sTagTest.java new file mode 100644 index 000000000000..fbdf1adcc323 --- /dev/null +++ b/oap-server/analyzer/meter-analyzer/src/test/java/org/apache/skywalking/oap/meter/analyzer/dsl/K8sTagTest.java @@ -0,0 +1,280 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.meter.analyzer.dsl; + +import com.google.common.collect.ImmutableMap; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1Pod; +import io.kubernetes.client.openapi.models.V1Service; +import io.kubernetes.client.openapi.models.V1ServiceSpec; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.skywalking.oap.meter.analyzer.k8s.K8sInfoRegistry; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.reflect.Whitebox; + +import static com.google.common.collect.ImmutableMap.of; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.fail; + +@Slf4j +@RunWith(Parameterized.class) +public class K8sTagTest { + + @Parameterized.Parameter + public String name; + + @Parameterized.Parameter(1) + public ImmutableMap input; + + @Parameterized.Parameter(2) + public String expression; + + @Parameterized.Parameter(3) + public Result want; + + @Parameterized.Parameter(4) + public boolean isThrow; + + @Parameterized.Parameters(name = "{index}: {0}") + public static Collection data() { + return Arrays.asList(new Object[][] { + { + "Pod2Service", + of("container_cpu_usage_seconds_total", SampleFamilyBuilder.newBuilder( + Sample.builder() + .labels( + of( + "namespace", "default", "container", "my-nginx", "cpu", "total", "pod", + "my-nginx-5dc4865748-mbczh" + )) + .value(2) + .build(), + Sample.builder() + .labels( + of( + "namespace", "kube-system", "container", "kube-state-metrics", "cpu", "total", "pod", + "kube-state-metrics-6f979fd498-z7xwx" + )) + .value(1) + .build() + ).build()), + "container_cpu_usage_seconds_total.retagByK8sMeta('service' , K8sRetagType.Pod2Service , 'pod' , 'namespace')", + Result.success(SampleFamilyBuilder.newBuilder( + Sample.builder() + .labels( + of( + "namespace", "default", "container", "my-nginx", "cpu", "total", "pod", + "my-nginx-5dc4865748-mbczh", + "service", "nginx-service.default" + )) + .value(2) + .build(), + Sample.builder() + .labels( + of( + "namespace", "kube-system", "container", "kube-state-metrics", "cpu", "total", "pod", + "kube-state-metrics-6f979fd498-z7xwx", + "service", "kube-state-metrics.kube-system" + )) + .value(1) + .build() + ).build()), + false, + }, + { + "Pod2Service_no_pod", + of("container_cpu_usage_seconds_total", SampleFamilyBuilder.newBuilder( + Sample.builder() + .labels( + of( + "namespace", "default", "container", "my-nginx", "cpu", "total", "pod", + "my-nginx-5dc4865748-no-pod" + )) + .value(2) + .build(), + Sample.builder() + .labels( + of( + "namespace", "kube-system", "container", "kube-state-metrics", "cpu", "total", "pod", + "kube-state-metrics-6f979fd498-z7xwx" + )) + .value(1) + .build() + ).build()), + "container_cpu_usage_seconds_total.retagByK8sMeta('service' , K8sRetagType.Pod2Service , 'pod' , 'namespace')", + Result.success(SampleFamilyBuilder.newBuilder( + Sample.builder() + .labels( + of( + "namespace", "default", "container", "my-nginx", "cpu", "total", "pod", + "my-nginx-5dc4865748-no-pod" + )) + .value(2) + .build(), + Sample.builder() + .labels( + of( + "namespace", "kube-system", "container", "kube-state-metrics", "cpu", "total", "pod", + "kube-state-metrics-6f979fd498-z7xwx", + "service", "kube-state-metrics.kube-system" + )) + .value(1) + .build() + ).build()), + false, + }, + { + "Pod2Service_no_service", + of("container_cpu_usage_seconds_total", SampleFamilyBuilder.newBuilder( + Sample.builder() + .labels( + of( + "namespace", "default", "container", "my-nginx", "cpu", "total", "pod", + "my-nginx-5dc4865748-no-service" + )) + .value(2) + .build(), + Sample.builder() + .labels( + of( + "namespace", "kube-system", "container", "kube-state-metrics", "cpu", "total", "pod", + "kube-state-metrics-6f979fd498-z7xwx" + )) + .value(1) + .build() + ).build()), + "container_cpu_usage_seconds_total.retagByK8sMeta('service' , K8sRetagType.Pod2Service , 'pod' , 'namespace')", + Result.success(SampleFamilyBuilder.newBuilder( + Sample.builder() + .labels( + of( + "namespace", "default", "container", "my-nginx", "cpu", "total", "pod", + "my-nginx-5dc4865748-no-service" + )) + .value(2) + .build(), + Sample.builder() + .labels( + of( + "namespace", "kube-system", "container", "kube-state-metrics", "cpu", "total", "pod", + "kube-state-metrics-6f979fd498-z7xwx", + "service", "kube-state-metrics.kube-system" + )) + .value(1) + .build() + ).build()), + false, + }, + }); + } + + @SneakyThrows + @Before + public void setup() { + Whitebox.setInternalState(K8sInfoRegistry.class, "INSTANCE", + Mockito.spy(K8sInfoRegistry.getInstance()) + ); + + PowerMockito.when( + K8sInfoRegistry.getInstance(), "addService", mockService("nginx-service", "default", of("run", "nginx"))) + .thenCallRealMethod(); + PowerMockito.when( + K8sInfoRegistry.getInstance(), "addService", + mockService("kube-state-metrics", "kube-system", of("run", "kube-state-metrics")) + ).thenCallRealMethod(); + PowerMockito.when( + K8sInfoRegistry.getInstance(), "addPod", + mockPod("my-nginx-5dc4865748-mbczh", "default", of("run", "nginx")) + ).thenCallRealMethod(); + PowerMockito.when( + K8sInfoRegistry.getInstance(), "addPod", + mockPod("kube-state-metrics-6f979fd498-z7xwx", "kube-system", of("run", "kube-state-metrics")) + ).thenCallRealMethod(); + + PowerMockito.when( + K8sInfoRegistry.getInstance(), "removeService", mockService("nginx-service", "default", of("run", "nginx"))) + .thenCallRealMethod(); + PowerMockito.when( + K8sInfoRegistry.getInstance(), "removePod", + mockPod("my-nginx-5dc4865748-mbczh", "default", of("run", "nginx")) + ).thenCallRealMethod(); + PowerMockito.when( + K8sInfoRegistry.getInstance(), "addService", mockService("nginx-service", "default", of("run", "nginx"))) + .thenCallRealMethod(); + PowerMockito.when( + K8sInfoRegistry.getInstance(), "addPod", + mockPod("my-nginx-5dc4865748-mbczh", "default", of("run", "nginx")) + ).thenCallRealMethod(); + + } + + @Test + public void test() { + Expression e = DSL.parse(expression); + Result r = null; + try { + r = e.run(input); + } catch (Throwable t) { + if (isThrow) { + return; + } + log.error("Test failed", t); + fail("Should not throw anything"); + } + if (isThrow) { + fail("Should throw something"); + } + assertThat(r, is(want)); + } + + private V1Service mockService(String name, String namespace, Map selector) { + V1Service service = new V1Service(); + V1ObjectMeta serviceMeta = new V1ObjectMeta(); + V1ServiceSpec v1ServiceSpec = new V1ServiceSpec(); + + serviceMeta.setName(name); + serviceMeta.setNamespace(namespace); + service.setMetadata(serviceMeta); + v1ServiceSpec.setSelector(selector); + service.setSpec(v1ServiceSpec); + + return service; + } + + private V1Pod mockPod(String name, String namespace, Map labels) { + V1Pod v1Pod = new V1Pod(); + V1ObjectMeta podMeta = new V1ObjectMeta(); + podMeta.setName(name); + podMeta.setNamespace(namespace); + podMeta.setLabels(labels); + v1Pod.setMetadata(podMeta); + + return v1Pod; + } +} \ No newline at end of file diff --git a/oap-server/exporter/src/main/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporter.java b/oap-server/exporter/src/main/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporter.java index e14b38ecdb6b..875858421efb 100644 --- a/oap-server/exporter/src/main/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporter.java +++ b/oap-server/exporter/src/main/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporter.java @@ -20,11 +20,12 @@ import io.grpc.ManagedChannel; import io.grpc.stub.StreamObserver; -import java.util.HashSet; +import java.util.ArrayList; import java.util.List; -import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.ReentrantLock; +import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.apm.commons.datacarrier.DataCarrier; import org.apache.skywalking.apm.commons.datacarrier.consumer.IConsumer; import org.apache.skywalking.oap.server.core.analysis.metrics.DoubleValueHolder; @@ -37,26 +38,31 @@ import org.apache.skywalking.oap.server.core.exporter.ExportData; import org.apache.skywalking.oap.server.core.exporter.ExportEvent; import org.apache.skywalking.oap.server.core.exporter.MetricValuesExportService; +import org.apache.skywalking.oap.server.exporter.grpc.EventType; import org.apache.skywalking.oap.server.exporter.grpc.ExportMetricValue; import org.apache.skywalking.oap.server.exporter.grpc.ExportResponse; import org.apache.skywalking.oap.server.exporter.grpc.MetricExportServiceGrpc; +import org.apache.skywalking.oap.server.exporter.grpc.SubscriptionMetric; import org.apache.skywalking.oap.server.exporter.grpc.SubscriptionReq; import org.apache.skywalking.oap.server.exporter.grpc.SubscriptionsResp; import org.apache.skywalking.oap.server.exporter.grpc.ValueType; import org.apache.skywalking.oap.server.exporter.provider.MetricFormatter; import org.apache.skywalking.oap.server.library.client.grpc.GRPCClient; import org.apache.skywalking.oap.server.library.util.GRPCStreamStatus; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +@Slf4j public class GRPCExporter extends MetricFormatter implements MetricValuesExportService, IConsumer { - private static final Logger LOGGER = LoggerFactory.getLogger(GRPCExporter.class); - - private GRPCExporterSetting setting; + /** + * The period of subscription list fetching is hardcoded as 30s. + */ + private static final long FETCH_SUBSCRIPTION_PERIOD = 30_000; + private final GRPCExporterSetting setting; private final MetricExportServiceGrpc.MetricExportServiceStub exportServiceFutureStub; private final MetricExportServiceGrpc.MetricExportServiceBlockingStub blockingStub; private final DataCarrier exportBuffer; - private final Set subscriptionSet; + private final ReentrantLock fetchListLock; + private volatile List subscriptionList; + private volatile long lastFetchTimestamp = 0; public GRPCExporter(GRPCExporterSetting setting) { this.setting = setting; @@ -67,27 +73,51 @@ public GRPCExporter(GRPCExporterSetting setting) { blockingStub = MetricExportServiceGrpc.newBlockingStub(channel); exportBuffer = new DataCarrier(setting.getBufferChannelNum(), setting.getBufferChannelSize()); exportBuffer.consume(this, 1, 200); - subscriptionSet = new HashSet<>(); + subscriptionList = new ArrayList<>(); + fetchListLock = new ReentrantLock(); } @Override public void export(ExportEvent event) { - if (ExportEvent.EventType.TOTAL == event.getType()) { - Metrics metrics = event.getMetrics(); - if (metrics instanceof WithMetadata) { - MetricsMetaInfo meta = ((WithMetadata) metrics).getMeta(); - if (subscriptionSet.size() == 0 || subscriptionSet.contains(meta.getMetricsName())) { - exportBuffer.produce(new ExportData(meta, metrics)); - } + Metrics metrics = event.getMetrics(); + if (metrics instanceof WithMetadata) { + MetricsMetaInfo meta = ((WithMetadata) metrics).getMeta(); + if (subscriptionList.size() == 0 && ExportEvent.EventType.INCREMENT.equals(event.getType())) { + exportBuffer.produce(new ExportData(meta, metrics, event.getType())); + } else { + subscriptionList.forEach(subscriptionMetric -> { + if (subscriptionMetric.getMetricName().equals(meta.getMetricsName()) && + eventTypeMatch(event.getType(), subscriptionMetric.getEventType())) { + exportBuffer.produce(new ExportData(meta, metrics, event.getType())); + } + }); } + + fetchSubscriptionList(); } } - public void initSubscriptionList() { - SubscriptionsResp subscription = blockingStub.withDeadlineAfter(10, TimeUnit.SECONDS) - .subscription(SubscriptionReq.newBuilder().build()); - subscription.getMetricNamesList().forEach(subscriptionSet::add); - LOGGER.debug("Get exporter subscription list, {}", subscriptionSet); + /** + * Read the subscription list. + */ + public void fetchSubscriptionList() { + final long currentTimeMillis = System.currentTimeMillis(); + if (currentTimeMillis - lastFetchTimestamp > FETCH_SUBSCRIPTION_PERIOD) { + try { + fetchListLock.lock(); + if (currentTimeMillis - lastFetchTimestamp > FETCH_SUBSCRIPTION_PERIOD) { + lastFetchTimestamp = currentTimeMillis; + SubscriptionsResp subscription = blockingStub.withDeadlineAfter(10, TimeUnit.SECONDS) + .subscription(SubscriptionReq.newBuilder().build()); + subscriptionList = subscription.getMetricsList(); + log.debug("Get exporter subscription list, {}", subscriptionList); + } + } catch (Throwable e) { + log.error("Getting exporter subscription list fails.", e); + } finally { + fetchListLock.unlock(); + } + } } @Override @@ -97,32 +127,28 @@ public void init() { @Override public void consume(List data) { - if (data.size() == 0) { - return; - } - GRPCStreamStatus status = new GRPCStreamStatus(); - StreamObserver streamObserver = exportServiceFutureStub.withDeadlineAfter( - 10, TimeUnit.SECONDS) - .export( - new StreamObserver() { - @Override - public void onNext( - ExportResponse response) { - - } - - @Override - public void onError( - Throwable throwable) { - status.done(); - } - - @Override - public void onCompleted() { - status.done(); - } - }); + StreamObserver streamObserver = + exportServiceFutureStub.withDeadlineAfter(10, TimeUnit.SECONDS) + .export( + new StreamObserver() { + @Override + public void onNext( + ExportResponse response) { + + } + + @Override + public void onError( + Throwable throwable) { + status.done(); + } + + @Override + public void onCompleted() { + status.done(); + } + }); AtomicInteger exportNum = new AtomicInteger(); data.forEach(row -> { ExportMetricValue.Builder builder = ExportMetricValue.newBuilder(); @@ -152,6 +178,8 @@ public void onCompleted() { MetricsMetaInfo meta = row.getMeta(); builder.setMetricName(meta.getMetricsName()); + builder.setEventType( + EventType.INCREMENT.equals(row.getEventType()) ? EventType.INCREMENT : EventType.TOTAL); String entityName = getEntityName(meta); if (entityName == null) { return; @@ -179,7 +207,7 @@ public void onCompleted() { } if (sleepTime > 2000L) { - LOGGER.warn( + log.warn( "Export {} metrics to {}:{}, wait {} milliseconds.", exportNum.get(), setting.getTargetHost(), setting .getTargetPort(), sleepTime @@ -188,18 +216,26 @@ public void onCompleted() { } } - LOGGER.debug( + log.debug( "Exported {} metrics to {}:{} in {} milliseconds.", exportNum.get(), setting.getTargetHost(), setting .getTargetPort(), sleepTime); + + fetchSubscriptionList(); } @Override public void onError(List data, Throwable t) { - LOGGER.error(t.getMessage(), t); + log.error(t.getMessage(), t); } @Override public void onExit() { } + + private boolean eventTypeMatch(ExportEvent.EventType eventType, + org.apache.skywalking.oap.server.exporter.grpc.EventType subscriptionType) { + return (ExportEvent.EventType.INCREMENT.equals(eventType) && EventType.INCREMENT.equals(subscriptionType)) + || (ExportEvent.EventType.TOTAL.equals(eventType) && EventType.TOTAL.equals(subscriptionType)); + } } diff --git a/oap-server/exporter/src/main/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterProvider.java b/oap-server/exporter/src/main/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterProvider.java index f2d75fb1d3da..c104759c1735 100644 --- a/oap-server/exporter/src/main/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterProvider.java +++ b/oap-server/exporter/src/main/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterProvider.java @@ -60,7 +60,7 @@ public void start() throws ServiceNotProvidedException, ModuleStartException { @Override public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { - exporter.initSubscriptionList(); + exporter.fetchSubscriptionList(); } @Override diff --git a/oap-server/exporter/src/main/proto/metric-exporter.proto b/oap-server/exporter/src/main/proto/metric-exporter.proto index 3ade1e37571e..4013bcc36a55 100644 --- a/oap-server/exporter/src/main/proto/metric-exporter.proto +++ b/oap-server/exporter/src/main/proto/metric-exporter.proto @@ -39,10 +39,16 @@ message ExportMetricValue { int64 longValue = 6; double doubleValue = 7; repeated int64 longValues = 8; + EventType eventType = 9; } message SubscriptionsResp { - repeated string metricNames = 1; + repeated SubscriptionMetric metrics = 1; +} + +message SubscriptionMetric { + string metricName = 1; + EventType eventType = 2; } enum ValueType { @@ -51,6 +57,13 @@ enum ValueType { MULTI_LONG = 2; } +enum EventType { + // The metrics aggregated in this bulk, not include the existing persistent data. + INCREMENT = 0; + // Final result of the metrics at this moment. + TOTAL = 1; +} + message SubscriptionReq { } diff --git a/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/ExporterMockReceiver.java b/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/ExporterMockReceiver.java index 06dce2a23487..0684e09c6dde 100644 --- a/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/ExporterMockReceiver.java +++ b/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/ExporterMockReceiver.java @@ -22,6 +22,7 @@ import org.apache.skywalking.oap.server.exporter.grpc.ExportMetricValue; import org.apache.skywalking.oap.server.exporter.grpc.ExportResponse; import org.apache.skywalking.oap.server.exporter.grpc.MetricExportServiceGrpc; +import org.apache.skywalking.oap.server.exporter.grpc.SubscriptionMetric; import org.apache.skywalking.oap.server.exporter.grpc.SubscriptionReq; import org.apache.skywalking.oap.server.exporter.grpc.SubscriptionsResp; import org.apache.skywalking.oap.server.library.server.ServerException; @@ -63,9 +64,18 @@ public void onCompleted() { @Override public void subscription(SubscriptionReq request, StreamObserver responseObserver) { responseObserver.onNext(SubscriptionsResp.newBuilder() - .addMetricNames("all_p99") - .addMetricNames("service_cpm") - .addMetricNames("endpoint_sla") + .addMetrics( + SubscriptionMetric + .newBuilder() + .setMetricName("all_p99")) + .addMetrics( + SubscriptionMetric + .newBuilder() + .setMetricName("service_cpm")) + .addMetrics( + SubscriptionMetric + .newBuilder() + .setMetricName("endpoint_sla")) .build()); responseObserver.onCompleted(); } diff --git a/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterProviderTest.java b/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterProviderTest.java index a1895d32da4d..658a8ca02f6a 100644 --- a/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterProviderTest.java +++ b/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterProviderTest.java @@ -92,7 +92,7 @@ public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleSta when(manager.find(CoreModule.NAME)).thenReturn(providerHolder); when(providerHolder.provider()).thenReturn(serviceHolder); - doNothing().when(exporter).initSubscriptionList(); + doNothing().when(exporter).fetchSubscriptionList(); grpcExporterProvider.setManager(manager); Whitebox.setInternalState(grpcExporterProvider, "exporter", exporter); diff --git a/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterTest.java b/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterTest.java index 467d1e9fd315..de42ce790863 100644 --- a/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterTest.java +++ b/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/GRPCExporterTest.java @@ -33,6 +33,8 @@ import org.junit.Test; import org.powermock.reflect.Whitebox; +import static org.apache.skywalking.oap.server.core.exporter.ExportEvent.EventType.INCREMENT; + public class GRPCExporterTest { private GRPCExporter exporter; @@ -40,7 +42,7 @@ public class GRPCExporterTest { @Rule public final GrpcServerRule grpcServerRule = new GrpcServerRule().directExecutor(); - private MetricExportServiceGrpc.MetricExportServiceImplBase server = new MockMetricExportServiceImpl(); + private MetricExportServiceGrpc.MetricExportServiceImplBase service = new MockMetricExportServiceImpl(); private MetricsMetaInfo metaInfo = new MetricsMetaInfo("mock-metrics", DefaultScopeDefine.ALL); private MetricExportServiceGrpc.MetricExportServiceBlockingStub stub; @@ -51,8 +53,9 @@ public void setUp() throws Exception { setting.setTargetHost("localhost"); setting.setTargetPort(9870); exporter = new GRPCExporter(setting); - grpcServerRule.getServiceRegistry().addService(server); + grpcServerRule.getServiceRegistry().addService(service); stub = MetricExportServiceGrpc.newBlockingStub(grpcServerRule.getChannel()); + Whitebox.setInternalState(exporter, "blockingStub", stub); } @Test @@ -70,8 +73,7 @@ public MetricsMetaInfo getMeta() { @Test public void initSubscriptionList() { - Whitebox.setInternalState(exporter, "blockingStub", stub); - exporter.initSubscriptionList(); + exporter.fetchSubscriptionList(); } @Test @@ -100,10 +102,10 @@ public void onExit() { private List dataList() { List dataList = new LinkedList<>(); - dataList.add(new ExportData(metaInfo, new MockMetrics())); - dataList.add(new ExportData(metaInfo, new MockIntValueMetrics())); - dataList.add(new ExportData(metaInfo, new MockLongValueMetrics())); - dataList.add(new ExportData(metaInfo, new MockDoubleValueMetrics())); + dataList.add(new ExportData(metaInfo, new MockMetrics(), INCREMENT)); + dataList.add(new ExportData(metaInfo, new MockIntValueMetrics(), INCREMENT)); + dataList.add(new ExportData(metaInfo, new MockLongValueMetrics(), INCREMENT)); + dataList.add(new ExportData(metaInfo, new MockDoubleValueMetrics(), INCREMENT)); return dataList; } } \ No newline at end of file diff --git a/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/MockMetricExportServiceImpl.java b/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/MockMetricExportServiceImpl.java index 6cad2cf88a55..72b3ec4d221d 100644 --- a/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/MockMetricExportServiceImpl.java +++ b/oap-server/exporter/src/test/java/org/apache/skywalking/oap/server/exporter/provider/grpc/MockMetricExportServiceImpl.java @@ -19,7 +19,9 @@ package org.apache.skywalking.oap.server.exporter.provider.grpc; import io.grpc.stub.StreamObserver; +import org.apache.skywalking.oap.server.exporter.grpc.EventType; import org.apache.skywalking.oap.server.exporter.grpc.MetricExportServiceGrpc; +import org.apache.skywalking.oap.server.exporter.grpc.SubscriptionMetric; import org.apache.skywalking.oap.server.exporter.grpc.SubscriptionReq; import org.apache.skywalking.oap.server.exporter.grpc.SubscriptionsResp; @@ -27,8 +29,16 @@ public class MockMetricExportServiceImpl extends MetricExportServiceGrpc.MetricE @Override public void subscription(SubscriptionReq request, StreamObserver responseObserver) { SubscriptionsResp resp = SubscriptionsResp.newBuilder() - .addMetricNames("first") - .addMetricNames("second") + .addMetrics( + SubscriptionMetric + .newBuilder() + .setMetricName("first") + .setEventType(EventType.INCREMENT)) + .addMetrics( + SubscriptionMetric + .newBuilder() + .setMetricName("second") + .setEventType(EventType.INCREMENT)) .build(); responseObserver.onNext(resp); responseObserver.onCompleted(); diff --git a/oap-server/server-bootstrap/src/main/resources/application.yml b/oap-server/server-bootstrap/src/main/resources/application.yml index 91ea490bd78d..75947a171dda 100755 --- a/oap-server/server-bootstrap/src/main/resources/application.yml +++ b/oap-server/server-bootstrap/src/main/resources/application.yml @@ -240,6 +240,13 @@ storage: oapAnalyzer: ${SW_STORAGE_ES_OAP_ANALYZER:"{\"analyzer\":{\"oap_analyzer\":{\"type\":\"stop\"}}}"} # the oap analyzer. oapLogAnalyzer: ${SW_STORAGE_ES_OAP_LOG_ANALYZER:"{\"analyzer\":{\"oap_log_analyzer\":{\"type\":\"standard\"}}}"} # the oap log analyzer. It could be customized by the ES analyzer configuration to support more language log formats, such as Chinese log, Japanese log and etc. advanced: ${SW_STORAGE_ES_ADVANCED:""} + iotdb: + # IoTDB configuration + url: ${SW_STORAGE_IOTDB_URL:localhost:6667} + user: ${SW_STORAGE_IOTDB_USER:root} + password: ${SW_STORAGE_IOTDB_PASSWORD:root} + storageGroupPrefix: ${SW_STORAGE_IOTDB_DATABASE:root.skywalking} + enableCompression: ${SW_STORAGE_IOTDB_ACTIONS:false} agent-analyzer: selector: ${SW_AGENT_ANALYZER:default} diff --git a/oap-server/server-bootstrap/src/main/resources/component-libraries.yml b/oap-server/server-bootstrap/src/main/resources/component-libraries.yml index 02bf8d4fcb09..61fc318bc4f6 100755 --- a/oap-server/server-bootstrap/src/main/resources/component-libraries.yml +++ b/oap-server/server-bootstrap/src/main/resources/component-libraries.yml @@ -419,6 +419,9 @@ Koa: Axios: id: 4005 languages: Node.js +Mongoose: + id: 4006 + languages: Node.js # Golang components # [5000, 6000) for Golang agent diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/exporter/ExportData.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/exporter/ExportData.java index a638f97e60a8..faefa565a466 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/exporter/ExportData.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/exporter/ExportData.java @@ -19,16 +19,14 @@ package org.apache.skywalking.oap.server.core.exporter; import lombok.Getter; +import lombok.RequiredArgsConstructor; import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics; import org.apache.skywalking.oap.server.core.analysis.metrics.MetricsMetaInfo; @Getter +@RequiredArgsConstructor public class ExportData { - private MetricsMetaInfo meta; - private Metrics metrics; - - public ExportData(MetricsMetaInfo meta, Metrics metrics) { - this.meta = meta; - this.metrics = metrics; - } + private final MetricsMetaInfo meta; + private final Metrics metrics; + private final ExportEvent.EventType eventType; } \ No newline at end of file diff --git a/oap-server/server-storage-plugin/pom.xml b/oap-server/server-storage-plugin/pom.xml index 38a813cedd7f..187effe82945 100644 --- a/oap-server/server-storage-plugin/pom.xml +++ b/oap-server/server-storage-plugin/pom.xml @@ -34,6 +34,7 @@ storage-zipkin-elasticsearch7-plugin storage-influxdb-plugin storage-tidb-plugin + storage-iotdb-plugin \ No newline at end of file diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/pom.xml b/oap-server/server-storage-plugin/storage-iotdb-plugin/pom.xml new file mode 100644 index 000000000000..feb4c8d51f60 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/pom.xml @@ -0,0 +1,53 @@ + + + + + + server-storage-plugin + org.apache.skywalking + 8.5.0-SNAPSHOT + + 4.0.0 + + storage-iotdb-plugin + jar + + + + org.apache.skywalking + server-core + ${project.version} + + + org.apache.skywalking + library-client + ${project.version} + + + org.apache.iotdb + iotdb-jdbc + 0.12.0-SNAPSHOT + + + org.apache.iotdb + iotdb-session + 0.12.0-SNAPSHOT + + + diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBClient.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBClient.java new file mode 100644 index 000000000000..691f7239f23a --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBClient.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb; + +import org.apache.skywalking.oap.server.library.client.Client; +import org.apache.skywalking.oap.server.library.client.healthcheck.DelegatedHealthChecker; +import org.apache.skywalking.oap.server.library.client.healthcheck.HealthCheckable; +import org.apache.skywalking.oap.server.library.util.HealthChecker; + +import org.apache.iotdb.session.Session; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; + +import java.io.IOException; +import java.util.List; + +public class IoTDBClient implements Client, HealthCheckable { + private final DelegatedHealthChecker healthChecker = new DelegatedHealthChecker(); + private Session iotdbSession; + private final IoTDBStorageConfig config; + private final String storageGroupPrefix; + + public IoTDBClient(IoTDBStorageConfig config) { + this.config = config; + this.storageGroupPrefix = config.getStorageGroupPrefix(); + } + + @Override + public void connect() throws IOException { + String fullURL = config.getUrl(); + int delimIdx = fullURL.indexOf(":"); + try { + iotdbSession = + new Session(fullURL.substring(0, delimIdx), fullURL.substring(delimIdx + 1), config.getUser(), config.getPassword()); + iotdbSession.open(config.isEnableCompression()); + healthChecker.health(); + } catch (Exception e) { + healthChecker.unHealth(e); + throw new IOException(e); + } + } + + @Override + public void shutdown() throws IOException { + try { + this.iotdbSession.close(); + } catch (Exception e) { + throw new IOException(e); + } + } + + public Session getIotdbConnection() { + return iotdbSession; + } + + public void setStorageGroup(String modelName) { + try { + iotdbSession.setStorageGroup(storageGroupPrefix + "." + modelName); + this.healthChecker.health(); + } catch (Throwable e) { + healthChecker.unHealth(e); + } + } + + public void insertRecord( + String deviceId, + long time, + List measurements, + List types, + List values) { + + try { + iotdbSession.insertRecord(deviceId, time, measurements, types, values); + this.healthChecker.health(); + } catch (Throwable e) { + healthChecker.unHealth(e); + } + } + + public void insertRecords( + List deviceIds, + List times, + List> measurementsList, + List> typesList, + List> valuesList) { + + try { + iotdbSession.insertRecords(deviceIds, times, measurementsList, typesList, valuesList); + this.healthChecker.health(); + } catch (Throwable e) { + healthChecker.unHealth(e); + } + } + + @Override + public void registerChecker(HealthChecker healthChecker) { + this.healthChecker.register(healthChecker); + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBInsertRequest.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBInsertRequest.java new file mode 100644 index 000000000000..9793d76eabac --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBInsertRequest.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb; + +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; + +import java.util.ArrayList; +import java.util.List; +import org.apache.skywalking.oap.server.core.storage.StorageData; +import org.apache.skywalking.oap.server.core.storage.StorageHashMapBuilder; +import org.apache.skywalking.oap.server.core.storage.model.Model; +import org.apache.skywalking.oap.server.core.storage.model.ModelColumn; +import org.apache.skywalking.oap.server.library.client.request.InsertRequest; +import org.apache.skywalking.oap.server.library.client.request.UpdateRequest; + +import java.util.Map; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class IoTDBInsertRequest implements InsertRequest, UpdateRequest { + private String deviceId; + private long time; + private List measurements = new ArrayList<>(); + private List dataTypes = new ArrayList<>(); + private List values = new ArrayList<>(); + + public IoTDBInsertRequest(long timestamp, String deviceId, + Model model, T storageData, StorageHashMapBuilder storageBuilder) { + this.time = timestamp; + this.deviceId = "root." + model.getName() + "." + deviceId; + final Map objectMap = storageBuilder.entity2Storage(storageData); + for (ModelColumn column : model.getColumns()) { + measurements.add(column.getColumnName().getName()); + values.add(objectMap.get(column.getColumnName().getName())); + if (column.getType().equals(String.class)) { + dataTypes.add(TSDataType.TEXT); + } else if (column.getType().equals(int.class)) { + dataTypes.add(TSDataType.INT32); + } else if (column.getType().equals(long.class)) { + dataTypes.add(TSDataType.INT64); + } else if (column.getType().equals(float.class)) { + dataTypes.add(TSDataType.FLOAT); + } else if (column.getType().equals(double.class)) { + dataTypes.add(TSDataType.DOUBLE); + } else { + dataTypes.add(TSDataType.TEXT); + } + } + } + + public IoTDBInsertRequest(long timestamp, + Model model, T storageData, StorageHashMapBuilder storageBuilder) { + time = timestamp; + final Map objectMap = storageBuilder.entity2Storage(storageData); + String entityID = ""; + String serviceID = ""; + deviceId = "root." + model.getName(); + for (ModelColumn column : model.getColumns()) { + if (column.getColumnName().getName().equals("entity_id")) { + entityID = objectMap.get(column.getColumnName().getName()).toString(); + } else if (column.getColumnName().getName().equals("service_id")) { + serviceID = objectMap.get(column.getColumnName().getName()).toString(); + } else { + measurements.add(column.getColumnName().getName()); + values.add(objectMap.get(column.getColumnName().getName())); + if (column.getType().equals(String.class)) { + dataTypes.add(TSDataType.TEXT); + } else if (column.getType().equals(int.class)) { + dataTypes.add(TSDataType.INT32); + } else if (column.getType().equals(long.class)) { + dataTypes.add(TSDataType.INT64); + } else if (column.getType().equals(float.class)) { + dataTypes.add(TSDataType.FLOAT); + } else if (column.getType().equals(double.class)) { + dataTypes.add(TSDataType.DOUBLE); + } else { + dataTypes.add(TSDataType.TEXT); + } + } + } + + if (serviceID.equals("")) { + deviceId += ".\"" + entityID + "\""; + } else if (entityID.equals("")) { + deviceId += ".\"" + serviceID + "\""; + } else { + deviceId += ".\"" + serviceID + "\".\"" + entityID + "\""; + } + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBStorageConfig.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBStorageConfig.java new file mode 100644 index 000000000000..1cc4fec29757 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBStorageConfig.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb; + +import org.apache.skywalking.oap.server.library.module.ModuleConfig; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class IoTDBStorageConfig extends ModuleConfig { + private String url; + private String user; + private String password; + private String storageGroupPrefix; + private boolean enableCompression; + +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBStorageProvider.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBStorageProvider.java new file mode 100644 index 000000000000..a913cc3ed297 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBStorageProvider.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb; + +import org.apache.skywalking.oap.server.core.CoreModule; +import org.apache.skywalking.oap.server.core.storage.IBatchDAO; +import org.apache.skywalking.oap.server.core.storage.IHistoryDeleteDAO; +import org.apache.skywalking.oap.server.core.storage.StorageBuilderFactory; +import org.apache.skywalking.oap.server.core.storage.StorageDAO; +import org.apache.skywalking.oap.server.core.storage.StorageModule; +import org.apache.skywalking.oap.server.core.storage.cache.INetworkAddressAliasDAO; +import org.apache.skywalking.oap.server.core.storage.management.UITemplateManagementDAO; +import org.apache.skywalking.oap.server.core.storage.model.ModelCreator; +import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO; +import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO; +import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO; +import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO; +import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO; +import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO; +import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO; +import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO; +import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO; +import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO; +import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO; +import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO; +import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO; +import org.apache.skywalking.oap.server.library.module.ModuleConfig; +import org.apache.skywalking.oap.server.library.module.ModuleDefine; +import org.apache.skywalking.oap.server.library.module.ModuleProvider; +import org.apache.skywalking.oap.server.library.module.ModuleStartException; +import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.base.BatchDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.base.HistoryDeleteDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.base.IoTDBStorageDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.AggregationQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.AlarmQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.BrowserLogQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.EventQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.LogQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.MetadataQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.MetricsQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.NetworkAddressAliasDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.ProfileTaskLogQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.ProfileTaskQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.ProfileThreadSnapshotQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.TopNRecordsQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.TopologyQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.TraceQueryDAO; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.query.UITemplateManagementDAOImpl; +import org.apache.skywalking.oap.server.telemetry.TelemetryModule; +import org.apache.skywalking.oap.server.telemetry.api.HealthCheckMetrics; +import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator; +import org.apache.skywalking.oap.server.telemetry.api.MetricsTag; + +public class IoTDBStorageProvider extends ModuleProvider { + private final IoTDBStorageConfig config; + private IoTDBClient client; + + public IoTDBStorageProvider() { + config = new IoTDBStorageConfig(); + } + + @Override + public String name() { + return "iotdb"; + } + + @Override + public Class module() { + return StorageModule.class; + } + + @Override + public ModuleConfig createConfigBeanIfAbsent() { + return config; + } + + @Override + public void prepare() throws ServiceNotProvidedException { + this.registerServiceImplementation(StorageBuilderFactory.class, new StorageBuilderFactory.Default()); + client = new IoTDBClient(config); + + this.registerServiceImplementation(IBatchDAO.class, new BatchDAO(client)); + this.registerServiceImplementation(StorageDAO.class, new IoTDBStorageDAO(client)); + this.registerServiceImplementation(INetworkAddressAliasDAO.class, new NetworkAddressAliasDAO()); + this.registerServiceImplementation(IMetadataQueryDAO.class, new MetadataQueryDAO()); + + this.registerServiceImplementation(ITopologyQueryDAO.class, new TopologyQueryDAO()); + this.registerServiceImplementation(IMetricsQueryDAO.class, new MetricsQueryDAO()); + this.registerServiceImplementation(ITraceQueryDAO.class, new TraceQueryDAO()); + this.registerServiceImplementation(IBrowserLogQueryDAO.class, new BrowserLogQueryDAO()); + this.registerServiceImplementation(IAggregationQueryDAO.class, new AggregationQueryDAO()); + this.registerServiceImplementation(IAlarmQueryDAO.class, new AlarmQueryDAO()); + this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new TopNRecordsQueryDAO()); + this.registerServiceImplementation(ILogQueryDAO.class, new LogQueryDAO()); + + this.registerServiceImplementation(IProfileTaskQueryDAO.class, new ProfileTaskQueryDAO()); + this.registerServiceImplementation( + IProfileThreadSnapshotQueryDAO.class, new ProfileThreadSnapshotQueryDAO()); + this.registerServiceImplementation( + IProfileTaskLogQueryDAO.class, new ProfileTaskLogQueryDAO()); + + this.registerServiceImplementation( + IHistoryDeleteDAO.class, new HistoryDeleteDAO()); + this.registerServiceImplementation(UITemplateManagementDAO.class, new UITemplateManagementDAOImpl()); + this.registerServiceImplementation(IEventQueryDAO.class, new EventQueryDAO()); + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { + MetricsCreator metricCreator = + getManager().find(TelemetryModule.NAME).provider().getService(MetricsCreator.class); + HealthCheckMetrics healthChecker = + metricCreator.createHealthCheckerGauge( + "storage_iotdb", MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE); + client.registerChecker(healthChecker); + + try { + client.connect(); + + IoTDBTableInstaller installer = new IoTDBTableInstaller(client, getManager()); + getManager() + .find(CoreModule.NAME) + .provider() + .getService(ModelCreator.class) + .addModelListener(installer); + } catch (Exception e) { + throw new ModuleStartException(e.getMessage(), e); + } + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + } + + @Override + public String[] requiredModules() { + return new String[] {CoreModule.NAME}; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBTableInstaller.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBTableInstaller.java new file mode 100644 index 000000000000..9f23e1c01252 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/IoTDBTableInstaller.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb; + +import org.apache.skywalking.oap.server.core.storage.StorageException; +import org.apache.skywalking.oap.server.core.storage.model.Model; +import org.apache.skywalking.oap.server.core.storage.model.ModelInstaller; +import org.apache.skywalking.oap.server.library.client.Client; +import org.apache.skywalking.oap.server.library.module.ModuleManager; + +public class IoTDBTableInstaller extends ModelInstaller { + public IoTDBTableInstaller(Client client, ModuleManager moduleManager) { + super(client, moduleManager); + } + + @Override + protected boolean isExists(Model model) throws StorageException { + return false; + } + + @Override + protected void createTable(Model model) throws StorageException { + String name = model.getName(); + try { + ((IoTDBClient) client).setStorageGroup(name); + } catch (Exception e) { + throw new StorageException(e.getMessage()); + } + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/BatchDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/BatchDAO.java new file mode 100644 index 000000000000..e64d99c77939 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/BatchDAO.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.base; + +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; + +import org.apache.skywalking.oap.server.core.storage.IBatchDAO; +import org.apache.skywalking.oap.server.library.client.request.InsertRequest; +import org.apache.skywalking.oap.server.library.client.request.PrepareRequest; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.IoTDBClient; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.IoTDBInsertRequest; + +import java.util.ArrayList; +import java.util.List; + +public class BatchDAO implements IBatchDAO { + private final IoTDBClient client; + + public BatchDAO(IoTDBClient client) { + this.client = client; + } + + @Override + public void asynchronous(InsertRequest insertRequest) { + } + + @Override + public void synchronous(List prepareRequests) { + List deviceIds = new ArrayList<>(); + List> measurementsList = new ArrayList<>(); + List> valuesList = new ArrayList<>(); + List timestamps = new ArrayList<>(); + List> typesList = new ArrayList<>(); + for (PrepareRequest request : prepareRequests) { + deviceIds.add(((IoTDBInsertRequest) request).getDeviceId()); + timestamps.add(((IoTDBInsertRequest) request).getTime()); + measurementsList.add(((IoTDBInsertRequest) request).getMeasurements()); + typesList.add(((IoTDBInsertRequest) request).getDataTypes()); + valuesList.add(((IoTDBInsertRequest) request).getValues()); + } + client.insertRecords(deviceIds, timestamps, measurementsList, typesList, valuesList); + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/HistoryDeleteDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/HistoryDeleteDAO.java new file mode 100644 index 000000000000..bd96ddd7405b --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/HistoryDeleteDAO.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.base; + +import org.apache.skywalking.oap.server.core.storage.IHistoryDeleteDAO; +import org.apache.skywalking.oap.server.core.storage.model.Model; + +import java.io.IOException; + +public class HistoryDeleteDAO implements IHistoryDeleteDAO { + @Override + public void deleteHistory(Model model, String timeBucketColumnName, int ttl) throws IOException { + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/IoTDBStorageDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/IoTDBStorageDAO.java new file mode 100644 index 000000000000..e6d5d0d304b3 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/IoTDBStorageDAO.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.base; + +import org.apache.skywalking.oap.server.core.analysis.config.NoneStream; +import org.apache.skywalking.oap.server.core.analysis.management.ManagementData; +import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics; +import org.apache.skywalking.oap.server.core.analysis.record.Record; +import org.apache.skywalking.oap.server.core.storage.IManagementDAO; +import org.apache.skywalking.oap.server.core.storage.IMetricsDAO; +import org.apache.skywalking.oap.server.core.storage.INoneStreamDAO; +import org.apache.skywalking.oap.server.core.storage.IRecordDAO; +import org.apache.skywalking.oap.server.core.storage.StorageDAO; +import org.apache.skywalking.oap.server.core.storage.StorageHashMapBuilder; +import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.IoTDBClient; + +public class IoTDBStorageDAO implements StorageDAO { + private final IoTDBClient iotdbClient; + + public IoTDBStorageDAO(IoTDBClient iotdbClient) { + this.iotdbClient = iotdbClient; + } + + @Override + public IMetricsDAO newMetricsDao(StorageBuilder storageBuilder) { + return new MetricsDAO(iotdbClient, (StorageHashMapBuilder) storageBuilder); + } + + @Override + public IRecordDAO newRecordDao(StorageBuilder storageBuilder) { + return new RecordDAO((StorageHashMapBuilder) storageBuilder); + } + + @Override + public INoneStreamDAO newNoneStreamDao(StorageBuilder storageBuilder) { + return new NoneStreamDAO(iotdbClient, (StorageHashMapBuilder) storageBuilder); + } + + @Override + public IManagementDAO newManagementDao(StorageBuilder storageBuilder) { + return new ManagementDAO(iotdbClient, (StorageHashMapBuilder) storageBuilder); + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/ManagementDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/ManagementDAO.java new file mode 100644 index 000000000000..2c2f683cc28c --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/ManagementDAO.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.base; + +import org.apache.skywalking.oap.server.core.analysis.management.ManagementData; +import org.apache.skywalking.oap.server.core.management.ui.template.UITemplate; +import org.apache.skywalking.oap.server.core.storage.IManagementDAO; +import org.apache.skywalking.oap.server.core.storage.StorageHashMapBuilder; +import org.apache.skywalking.oap.server.core.storage.model.Model; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.IoTDBClient; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.IoTDBInsertRequest; + +import java.io.IOException; + +public class ManagementDAO implements IManagementDAO { + private final IoTDBClient client; + private final StorageHashMapBuilder storageBuilder; + + public ManagementDAO(IoTDBClient client, StorageHashMapBuilder storageBuilder) { + this.client = client; + this.storageBuilder = storageBuilder; + } + + @Override + public void insert(Model model, ManagementData storageData) throws IOException { + String storageGroup = UITemplate.INDEX_NAME; + client.setStorageGroup(storageGroup); + IoTDBInsertRequest request = new IoTDBInsertRequest(1L, storageData.id(), model, storageData, storageBuilder); + client.insertRecord(request.getDeviceId(), request.getTime(), request.getMeasurements(), request.getDataTypes(), request.getValues()); + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/MetricsDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/MetricsDAO.java new file mode 100644 index 000000000000..54dbcaddac48 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/MetricsDAO.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.base; + +import org.apache.skywalking.oap.server.core.analysis.TimeBucket; +import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics; +import org.apache.skywalking.oap.server.core.storage.IMetricsDAO; +import org.apache.skywalking.oap.server.core.storage.StorageHashMapBuilder; +import org.apache.skywalking.oap.server.core.storage.model.Model; +import org.apache.skywalking.oap.server.library.client.request.InsertRequest; +import org.apache.skywalking.oap.server.library.client.request.UpdateRequest; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.IoTDBClient; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.IoTDBInsertRequest; + +import java.util.List; + +public class MetricsDAO implements IMetricsDAO { + private final StorageHashMapBuilder storageBuilder; + private final IoTDBClient client; + + public MetricsDAO(IoTDBClient client, StorageHashMapBuilder storageBuilder) { + this.client = client; + this.storageBuilder = storageBuilder; + } + + @Override + public List multiGet(Model model, List metrics) { + // TODO:study what this method does and implement it + return metrics; + } + + @Override + public InsertRequest prepareBatchInsert(Model model, Metrics metrics) { + final long timestamp = + TimeBucket.getTimestamp(metrics.getTimeBucket(), model.getDownsampling()); + + return new IoTDBInsertRequest(timestamp, model, metrics, storageBuilder); + } + + @Override + public UpdateRequest prepareBatchUpdate(Model model, Metrics metrics) { + return (UpdateRequest) this.prepareBatchInsert(model, metrics); + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/NoneStreamDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/NoneStreamDAO.java new file mode 100644 index 000000000000..d93f9eee26f0 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/NoneStreamDAO.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.base; + +import org.apache.skywalking.apm.commons.datacarrier.common.AtomicRangeInteger; +import org.apache.skywalking.oap.server.core.analysis.TimeBucket; +import org.apache.skywalking.oap.server.core.analysis.config.NoneStream; +import org.apache.skywalking.oap.server.core.storage.INoneStreamDAO; +import org.apache.skywalking.oap.server.core.storage.StorageHashMapBuilder; +import org.apache.skywalking.oap.server.core.storage.model.Model; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.IoTDBClient; +import org.apache.skywalking.oap.server.storage.plugin.iotdb.IoTDBInsertRequest; + +import java.io.IOException; + +public class NoneStreamDAO implements INoneStreamDAO { + private static final int PADDING_SIZE = 1_000_000; + private static final AtomicRangeInteger SUFFIX = new AtomicRangeInteger(0, PADDING_SIZE); + private final IoTDBClient client; + private final StorageHashMapBuilder storageBuilder; + + public NoneStreamDAO(IoTDBClient client, StorageHashMapBuilder storageBuilder) { + this.client = client; + this.storageBuilder = storageBuilder; + } + + @Override + public void insert(Model model, NoneStream noneStream) throws IOException { + long timestamp = TimeBucket.getTimestamp(noneStream.getTimeBucket(), model.getDownsampling()) + * PADDING_SIZE + SUFFIX.getAndIncrement(); + + IoTDBInsertRequest request = new IoTDBInsertRequest(timestamp, model, noneStream, storageBuilder); + client.insertRecord(request.getDeviceId(), request.getTime(), request.getMeasurements(), request.getDataTypes(), request.getValues()); + } + +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/RecordDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/RecordDAO.java new file mode 100644 index 000000000000..0f647d77c0c2 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/base/RecordDAO.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.base; + +import org.apache.skywalking.oap.server.core.analysis.record.Record; +import org.apache.skywalking.oap.server.core.storage.IRecordDAO; +import org.apache.skywalking.oap.server.core.storage.StorageHashMapBuilder; +import org.apache.skywalking.oap.server.core.storage.model.Model; +import org.apache.skywalking.oap.server.library.client.request.InsertRequest; + +import java.io.IOException; + +public class RecordDAO implements IRecordDAO { + private final StorageHashMapBuilder storageBuilder; + + public RecordDAO(StorageHashMapBuilder storageBuilder) { + this.storageBuilder = storageBuilder; + } + + @Override + public InsertRequest prepareBatchInsert(Model model, Record record) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/AggregationQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/AggregationQueryDAO.java new file mode 100644 index 000000000000..b14e39e71a45 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/AggregationQueryDAO.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.query.input.Duration; +import org.apache.skywalking.oap.server.core.query.input.TopNCondition; +import org.apache.skywalking.oap.server.core.query.type.KeyValue; +import org.apache.skywalking.oap.server.core.query.type.SelectedRecord; +import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO; + +import java.io.IOException; +import java.util.List; + +public class AggregationQueryDAO implements IAggregationQueryDAO { + @Override + public List sortMetrics(TopNCondition condition, String valueColumnName, Duration duration, List additionalConditions) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/AlarmQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/AlarmQueryDAO.java new file mode 100644 index 000000000000..b52f0008a72c --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/AlarmQueryDAO.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.query.type.Alarms; +import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO; + +import java.io.IOException; + +public class AlarmQueryDAO implements IAlarmQueryDAO { + @Override + public Alarms getAlarm(Integer scopeId, String keyword, int limit, int from, long startTB, long endTB) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/BrowserLogQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/BrowserLogQueryDAO.java new file mode 100644 index 000000000000..bf833c4ca0b9 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/BrowserLogQueryDAO.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory; +import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLogs; +import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO; + +import java.io.IOException; + +public class BrowserLogQueryDAO implements IBrowserLogQueryDAO { + @Override + public BrowserErrorLogs queryBrowserErrorLogs(String serviceId, String serviceVersionId, String pagePathId, String pagePath, BrowserErrorCategory category, long startSecondTB, long endSecondTB, int limit, int from) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/EventQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/EventQueryDAO.java new file mode 100644 index 000000000000..49c924d8c1a7 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/EventQueryDAO.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.query.type.event.EventQueryCondition; +import org.apache.skywalking.oap.server.core.query.type.event.Events; +import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO; + +public class EventQueryDAO implements IEventQueryDAO { + @Override + public Events queryEvents(EventQueryCondition condition) throws Exception { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/LogQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/LogQueryDAO.java new file mode 100644 index 000000000000..ed54dfe5fbb0 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/LogQueryDAO.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag; +import org.apache.skywalking.oap.server.core.query.enumeration.Order; +import org.apache.skywalking.oap.server.core.query.input.TraceScopeCondition; +import org.apache.skywalking.oap.server.core.query.type.Logs; +import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO; + +import java.io.IOException; +import java.util.List; + +public class LogQueryDAO implements ILogQueryDAO { + @Override + public Logs queryLogs(String serviceId, String serviceInstanceId, String endpointId, String endpointName, TraceScopeCondition relatedTrace, Order queryOrder, int from, int limit, long startTB, long endTB, List tags, List keywordsOfContent, List excludingKeywordsOfContent) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/MetadataQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/MetadataQueryDAO.java new file mode 100644 index 000000000000..1194e5e883f4 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/MetadataQueryDAO.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.query.type.Database; +import org.apache.skywalking.oap.server.core.query.type.Endpoint; +import org.apache.skywalking.oap.server.core.query.type.Service; +import org.apache.skywalking.oap.server.core.query.type.ServiceInstance; +import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO; + +import java.io.IOException; +import java.util.List; + +public class MetadataQueryDAO implements IMetadataQueryDAO { + @Override + public List getAllServices(String group) throws IOException { + return null; + } + + @Override + public List getAllBrowserServices() throws IOException { + return null; + } + + @Override + public List getAllDatabases() throws IOException { + return null; + } + + @Override + public List searchServices(String keyword) throws IOException { + return null; + } + + @Override + public Service searchService(String serviceCode) throws IOException { + return null; + } + + @Override + public List searchEndpoint(String keyword, String serviceId, int limit) throws IOException { + return null; + } + + @Override + public List getServiceInstances(long startTimestamp, long endTimestamp, String serviceId) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/MetricsQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/MetricsQueryDAO.java new file mode 100644 index 000000000000..c4cdeaa8b888 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/MetricsQueryDAO.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.query.input.Duration; +import org.apache.skywalking.oap.server.core.query.input.MetricsCondition; +import org.apache.skywalking.oap.server.core.query.type.HeatMap; +import org.apache.skywalking.oap.server.core.query.type.MetricsValues; +import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO; + +import java.io.IOException; +import java.util.List; + +public class MetricsQueryDAO implements IMetricsQueryDAO { + @Override + public long readMetricsValue(MetricsCondition condition, String valueColumnName, Duration duration) throws IOException { + return 0; + } + + @Override + public MetricsValues readMetricsValues(MetricsCondition condition, String valueColumnName, Duration duration) throws IOException { + return null; + } + + @Override + public List readLabeledMetricsValues(MetricsCondition condition, String valueColumnName, List labels, Duration duration) throws IOException { + return null; + } + + @Override + public HeatMap readHeatMap(MetricsCondition condition, String valueColumnName, Duration duration) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/NetworkAddressAliasDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/NetworkAddressAliasDAO.java new file mode 100644 index 000000000000..43ff52543def --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/NetworkAddressAliasDAO.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.analysis.manual.networkalias.NetworkAddressAlias; +import org.apache.skywalking.oap.server.core.storage.cache.INetworkAddressAliasDAO; + +import java.util.List; + +public class NetworkAddressAliasDAO implements INetworkAddressAliasDAO { + @Override + public List loadLastUpdate(long timeBucket) { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/ProfileTaskLogQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/ProfileTaskLogQueryDAO.java new file mode 100644 index 000000000000..22bb8a273293 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/ProfileTaskLogQueryDAO.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLog; +import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO; + +import java.io.IOException; +import java.util.List; + +public class ProfileTaskLogQueryDAO implements IProfileTaskLogQueryDAO { + @Override + public List getTaskLogList() throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/ProfileTaskQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/ProfileTaskQueryDAO.java new file mode 100644 index 000000000000..1224eac98847 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/ProfileTaskQueryDAO.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.query.type.ProfileTask; +import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO; + +import java.io.IOException; +import java.util.List; + +public class ProfileTaskQueryDAO implements IProfileTaskQueryDAO { + @Override + public List getTaskList(String serviceId, String endpointName, Long startTimeBucket, Long endTimeBucket, Integer limit) throws IOException { + return null; + } + + @Override + public ProfileTask getById(String id) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/ProfileThreadSnapshotQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/ProfileThreadSnapshotQueryDAO.java new file mode 100644 index 000000000000..bb47aa9deab8 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/ProfileThreadSnapshotQueryDAO.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord; +import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord; +import org.apache.skywalking.oap.server.core.query.type.BasicTrace; +import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO; + +import java.io.IOException; +import java.util.List; + +public class ProfileThreadSnapshotQueryDAO implements IProfileThreadSnapshotQueryDAO { + @Override + public List queryProfiledSegments(String taskId) throws IOException { + return null; + } + + @Override + public int queryMinSequence(String segmentId, long start, long end) throws IOException { + return 0; + } + + @Override + public int queryMaxSequence(String segmentId, long start, long end) throws IOException { + return 0; + } + + @Override + public List queryRecords(String segmentId, int minSequence, int maxSequence) throws IOException { + return null; + } + + @Override + public SegmentRecord getProfiledSegment(String segmentId) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/TopNRecordsQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/TopNRecordsQueryDAO.java new file mode 100644 index 000000000000..881900785cbc --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/TopNRecordsQueryDAO.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.query.input.Duration; +import org.apache.skywalking.oap.server.core.query.input.TopNCondition; +import org.apache.skywalking.oap.server.core.query.type.SelectedRecord; +import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO; + +import java.io.IOException; +import java.util.List; + +public class TopNRecordsQueryDAO implements ITopNRecordsQueryDAO { + @Override + public List readSampledRecords(TopNCondition condition, String valueColumnName, Duration duration) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/TopologyQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/TopologyQueryDAO.java new file mode 100644 index 000000000000..47ff2bdc30cb --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/TopologyQueryDAO.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.query.type.Call.CallDetail; +import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO; + +import java.io.IOException; +import java.util.List; + +public class TopologyQueryDAO implements ITopologyQueryDAO { + @Override + public List loadServiceRelationsDetectedAtServerSide(long startTB, long endTB, List serviceIds) throws IOException { + return null; + } + + @Override + public List loadServiceRelationDetectedAtClientSide(long startTB, long endTB, List serviceIds) throws IOException { + return null; + } + + @Override + public List loadServiceRelationsDetectedAtServerSide(long startTB, long endTB) throws IOException { + return null; + } + + @Override + public List loadServiceRelationDetectedAtClientSide(long startTB, long endTB) throws IOException { + return null; + } + + @Override + public List loadInstanceRelationDetectedAtServerSide(String clientServiceId, String serverServiceId, long startTB, long endTB) throws IOException { + return null; + } + + @Override + public List loadInstanceRelationDetectedAtClientSide(String clientServiceId, String serverServiceId, long startTB, long endTB) throws IOException { + return null; + } + + @Override + public List loadEndpointRelation(long startTB, long endTB, String destEndpointId) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/TraceQueryDAO.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/TraceQueryDAO.java new file mode 100644 index 000000000000..b962993faaa0 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/TraceQueryDAO.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag; +import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord; +import org.apache.skywalking.oap.server.core.query.type.QueryOrder; +import org.apache.skywalking.oap.server.core.query.type.Span; +import org.apache.skywalking.oap.server.core.query.type.TraceBrief; +import org.apache.skywalking.oap.server.core.query.type.TraceState; +import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO; + +import java.io.IOException; +import java.util.List; + +public class TraceQueryDAO implements ITraceQueryDAO { + @Override + public TraceBrief queryBasicTraces(long startSecondTB, long endSecondTB, long minDuration, long maxDuration, String endpointName, String serviceId, String serviceInstanceId, String endpointId, String traceId, int limit, int from, TraceState traceState, QueryOrder queryOrder, List tags) throws IOException { + return null; + } + + @Override + public List queryByTraceId(String traceId) throws IOException { + return null; + } + + @Override + public List doFlexibleTraceQuery(String traceId) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/UITemplateManagementDAOImpl.java b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/UITemplateManagementDAOImpl.java new file mode 100644 index 000000000000..12c731aadc37 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/iotdb/query/UITemplateManagementDAOImpl.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.storage.plugin.iotdb.query; + +import org.apache.skywalking.oap.server.core.query.input.DashboardSetting; +import org.apache.skywalking.oap.server.core.query.type.DashboardConfiguration; +import org.apache.skywalking.oap.server.core.query.type.TemplateChangeStatus; +import org.apache.skywalking.oap.server.core.storage.management.UITemplateManagementDAO; + +import java.io.IOException; +import java.util.List; + +public class UITemplateManagementDAOImpl implements UITemplateManagementDAO { + @Override + public List getAllTemplates(Boolean includingDisabled) throws IOException { + return null; + } + + @Override + public TemplateChangeStatus addTemplate(DashboardSetting setting) throws IOException { + return null; + } + + @Override + public TemplateChangeStatus changeTemplate(DashboardSetting setting) throws IOException { + return null; + } + + @Override + public TemplateChangeStatus disableTemplate(String name) throws IOException { + return null; + } +} diff --git a/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider new file mode 100644 index 000000000000..3cdccc3901df --- /dev/null +++ b/oap-server/server-storage-plugin/storage-iotdb-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +org.apache.skywalking.oap.server.storage.plugin.iotdb.IoTDBStorageProvider \ No newline at end of file diff --git a/skywalking-ui b/skywalking-ui index b71cb8d8f901..b94022221a89 160000 --- a/skywalking-ui +++ b/skywalking-ui @@ -1 +1 @@ -Subproject commit b71cb8d8f9010ddd84b02d590a64f3d750233dab +Subproject commit b94022221a896c29d9eb9112eb47df3c5eeca686 diff --git a/test/e2e/e2e-test/pom.xml b/test/e2e/e2e-test/pom.xml index d0d79da45c89..ec28918b49da 100755 --- a/test/e2e/e2e-test/pom.xml +++ b/test/e2e/e2e-test/pom.xml @@ -74,4 +74,30 @@ + + + + org.apache.maven.plugins + maven-antrun-plugin + ${maven-antrun-plugin.version} + + + download-jars + compile + + run + + + + + + + + + + + + + + diff --git a/test/e2e/pom.xml b/test/e2e/pom.xml index e39599840e27..7245949bb207 100644 --- a/test/e2e/pom.xml +++ b/test/e2e/pom.xml @@ -67,10 +67,12 @@ 8.0.13 1.18.16 2.4.1 + 0.8.6 2.22.0 3.8.0 3.1.0 + 3.0.0 1.15.1 diff --git a/test/jacoco/jacocoagent.jar b/test/jacoco/jacocoagent.jar deleted file mode 100644 index 3d840bc5466d..000000000000 Binary files a/test/jacoco/jacocoagent.jar and /dev/null differ diff --git a/test/jacoco/jacococli.jar b/test/jacoco/jacococli.jar deleted file mode 100644 index 20ba9741026f..000000000000 Binary files a/test/jacoco/jacococli.jar and /dev/null differ diff --git a/test/plugin/run.sh b/test/plugin/run.sh index ba4462034883..5c221089bece 100755 --- a/test/plugin/run.sh +++ b/test/plugin/run.sh @@ -31,6 +31,7 @@ scenarios_home="${home}/scenarios" num_of_testcases= image_version="jdk8-1.0.0" +jacoco_version="${JACOCO_VERSION:-0.8.6}" print_help() { echo "Usage: run.sh [OPTION] SCENARIO_NAME" @@ -181,6 +182,10 @@ if [[ -n "${running_mode}" ]]; then agent_home_selector ${running_mode} ${with_plugins} fi +mkdir -p "${jacoco_home}" +ls "${jacoco_home}"/jacocoagent.jar || curl -Lso "${jacoco_home}"/jacocoagent.jar https://repo1.maven.org/maven2/org/jacoco/org.jacoco.agent/${jacoco_version}/org.jacoco.agent-${jacoco_version}-runtime.jar +ls "${jacoco_home}"/jacocoacli.jar || curl -Lso "${jacoco_home}"/jacococli.jar https://repo1.maven.org/maven2/org/jacoco/org.jacoco.cli/${jacoco_version}/org.jacoco.cli-${jacoco_version}-nodeps.jar + supported_versions=`grep -v -E "^$|^#" ${supported_version_file}` for version in ${supported_versions} do diff --git a/test/plugin/scenarios/hbase-scenario/configuration.yml b/test/plugin/scenarios/hbase-scenario/configuration.yml index 952b5c9b894b..7cbd9239481e 100644 --- a/test/plugin/scenarios/hbase-scenario/configuration.yml +++ b/test/plugin/scenarios/hbase-scenario/configuration.yml @@ -24,7 +24,7 @@ depends_on: - hbase-server dependencies: hbase-server: - image: harisekhon/hbase:1.4 + image: harisekhon/hbase:2.1 hostname: hbase-server expose: - "2181" diff --git a/test/plugin/scenarios/hbase-scenario/support-version.list b/test/plugin/scenarios/hbase-scenario/support-version.list index 6e0034bc110b..230dce131c03 100644 --- a/test/plugin/scenarios/hbase-scenario/support-version.list +++ b/test/plugin/scenarios/hbase-scenario/support-version.list @@ -16,4 +16,6 @@ 1.2.6 1.3.1 -1.4.9 \ No newline at end of file +1.4.9 +2.1.10 +2.4.2 \ No newline at end of file diff --git a/test/plugin/scenarios/spring-4.3.x-scenario/support-version.list b/test/plugin/scenarios/spring-4.3.x-scenario/support-version.list index 02096a62531b..48d635b044ff 100644 --- a/test/plugin/scenarios/spring-4.3.x-scenario/support-version.list +++ b/test/plugin/scenarios/spring-4.3.x-scenario/support-version.list @@ -14,6 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +4.3.16.RELEASE +4.3.24.RELEASE 4.3.25.RELEASE 5.0.15.RELEASE 5.1.10.RELEASE