diff --git a/CHANGES.md b/CHANGES.md index 099fb3e84135eb04bf483e758a390fc13c884344..1239be9fe35e0106257daecd78e5d636916d8435 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ Release Notes. #### Java Agent * Add `trace_segment_ref_limit_per_span` configuration mechanism to avoid OOM. * Improve `GlobalIdGenerator` performance. +* Add an agent plugin to support elasticsearch7. #### OAP-Backend * BugFix: filter invalid Envoy access logs whose socket address is empty. diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/AdapterActionFutureInstrumentation.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/AdapterActionFutureInstrumentation.java index af6c92bf7dec7fd7e3c4017774ba4f3cf4ef9108..2fc72a20b2384d240f6109fe52ecb3cad2c2127c 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/AdapterActionFutureInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/AdapterActionFutureInstrumentation.java @@ -18,8 +18,11 @@ package org.apache.skywalking.apm.plugin.elasticsearch.v6.define; +import java.util.Collections; +import java.util.List; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint; @@ -28,6 +31,8 @@ import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import org.apache.skywalking.apm.plugin.elasticsearch.v6.interceptor.Constants; import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.returns; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; public class AdapterActionFutureInstrumentation extends ClassEnhancePluginDefine { @@ -39,7 +44,7 @@ public class AdapterActionFutureInstrumentation extends ClassEnhancePluginDefine @Override public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[]{ + return new InstanceMethodsInterceptPoint[] { new InstanceMethodsInterceptPoint() { @Override public ElementMatcher getMethodsMatcher() { @@ -71,6 +76,14 @@ public class AdapterActionFutureInstrumentation extends ClassEnhancePluginDefine @Override protected String[] witnessClasses() { - return new String[]{Constants.TASK_TRANSPORT_CHANNEL_WITNESS_CLASSES}; + return new String[] {Constants.TASK_TRANSPORT_CHANNEL_WITNESS_CLASSES}; + } + + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod( + Constants.SEARCH_HITS_WITNESS_CLASSES, + named("getTotalHits").and(takesArguments(0)).and(returns(long.class)) + )); } } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/AdapterActionFutureActionGetMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/AdapterActionFutureActionGetMethodsInterceptor.java index 349bf77f2d130a17600888338d37bead928c8e3b..bee05a636bea861b4bf56d612de8eacbd9b835bf 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/AdapterActionFutureActionGetMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/AdapterActionFutureActionGetMethodsInterceptor.java @@ -18,6 +18,7 @@ package org.apache.skywalking.apm.plugin.elasticsearch.v6.interceptor; +import java.lang.reflect.Method; import org.apache.skywalking.apm.agent.core.context.ContextManager; import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; @@ -34,8 +35,6 @@ import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.update.UpdateResponse; -import java.lang.reflect.Method; - import static org.apache.skywalking.apm.plugin.elasticsearch.v6.ElasticsearchPluginConfig.Plugin.Elasticsearch.ELASTICSEARCH_DSL_LENGTH_THRESHOLD; import static org.apache.skywalking.apm.plugin.elasticsearch.v6.ElasticsearchPluginConfig.Plugin.Elasticsearch.TRACE_DSL; @@ -45,26 +44,22 @@ public class AdapterActionFutureActionGetMethodsInterceptor implements InstanceM public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { - if (!isTrace(objInst)) { - return; + if (isTrace(objInst)) { + AbstractSpan span = ContextManager.createLocalSpan(Constants.DB_TYPE + "/" + Constants.BASE_FUTURE_METHOD); + span.setComponent(ComponentsDefine.TRANSPORT_CLIENT); + Tags.DB_TYPE.set(span, Constants.DB_TYPE); } - - AbstractSpan span = ContextManager.createLocalSpan(Constants.DB_TYPE + "/" + Constants.BASE_FUTURE_METHOD); - span.setComponent(ComponentsDefine.TRANSPORT_CLIENT); - Tags.DB_TYPE.set(span, Constants.DB_TYPE); } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { - if (!isTrace(objInst)) { - return ret; + if (isTrace(objInst)) { + AbstractSpan span = ContextManager.activeSpan(); + parseResponseInfo((ActionResponse) ret, span); + ContextManager.stopSpan(); } - - AbstractSpan span = ContextManager.activeSpan(); - parseResponseInfo((ActionResponse) ret, span); - ContextManager.stopSpan(); return ret; } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/Constants.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/Constants.java index 9a7171cebed4079282546e0ce35cbb50c40d0df5..638b98bbbb8a5727dbc6a763de41c824368c3e90 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/Constants.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/Constants.java @@ -43,6 +43,7 @@ public class Constants { //witnessClasses public static final String TASK_TRANSPORT_CHANNEL_WITNESS_CLASSES = "org.elasticsearch.transport.TaskTransportChannel"; + public static final String SEARCH_HITS_WITNESS_CLASSES = "org.elasticsearch.search.SearchHits"; //es operator name public static final String CREATE_OPERATOR_NAME = "Elasticsearch/CreateRequest"; diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..9a8b4debdca73c48511155def273f1f41eb45cef --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml @@ -0,0 +1,52 @@ + + + + + apm-sdk-plugin + org.apache.skywalking + 8.6.0-SNAPSHOT + + 4.0.0 + + apm-elasticsearch-7.x-plugin + jar + + elasticsearch-7.x-plugin + http://maven.apache.org + + + UTF-8 + 7.2.1 + + + + + org.elasticsearch.client + elasticsearch-rest-high-level-client + ${elasticsearch.rest.high.level.client.version} + provided + + + org.apache.skywalking + apm-elasticsearch-6.x-plugin + ${project.version} + provided + + + diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/define/AdapterActionFutureInstrumentation.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/define/AdapterActionFutureInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..927ec5f3cf8a1a117d06ea81726aeaf40fe3a252 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/define/AdapterActionFutureInstrumentation.java @@ -0,0 +1,89 @@ +/* + * 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.elasticsearch.v7.define; + +import java.util.Collections; +import java.util.List; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.interceptor.Constants; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.returns; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class AdapterActionFutureInstrumentation extends ClassEnhancePluginDefine { + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("actionGet"); + } + + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.elasticsearch.v7.interceptor.AdapterActionFutureActionGetMethodsInterceptor"; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() { + return new StaticMethodsInterceptPoint[0]; + } + + @Override + protected ClassMatch enhanceClass() { + return byName("org.elasticsearch.action.support.AdapterActionFuture"); + } + + @Override + protected String[] witnessClasses() { + return new String[] {Constants.TASK_TRANSPORT_CHANNEL_WITNESS_CLASSES}; + } + + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod( + Constants.SEARCH_HITS_WITNESS_CLASSES, + named("getTotalHits").and(takesArguments(0)).and(returns(named("org.apache.lucene.search.TotalHits"))) + )); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/AdapterActionFutureActionGetMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/AdapterActionFutureActionGetMethodsInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..fb19d34831513f230abd8ade0b19adf6fbccef7e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/AdapterActionFutureActionGetMethodsInterceptor.java @@ -0,0 +1,161 @@ +/* + * 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.elasticsearch.v7.interceptor; + +import java.lang.reflect.Method; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.interceptor.Constants; +import org.apache.skywalking.apm.util.StringUtil; +import org.elasticsearch.action.ActionResponse; +import org.elasticsearch.action.bulk.BulkResponse; +import org.elasticsearch.action.delete.DeleteResponse; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.index.IndexResponse; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.update.UpdateResponse; + +import static org.apache.skywalking.apm.plugin.elasticsearch.v6.ElasticsearchPluginConfig.Plugin.Elasticsearch.ELASTICSEARCH_DSL_LENGTH_THRESHOLD; +import static org.apache.skywalking.apm.plugin.elasticsearch.v6.ElasticsearchPluginConfig.Plugin.Elasticsearch.TRACE_DSL; + +public class AdapterActionFutureActionGetMethodsInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + + if (isTrace(objInst)) { + AbstractSpan span = ContextManager.createLocalSpan(Constants.DB_TYPE + "/" + Constants.BASE_FUTURE_METHOD); + span.setComponent(ComponentsDefine.TRANSPORT_CLIENT); + Tags.DB_TYPE.set(span, Constants.DB_TYPE); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) throws Throwable { + + if (isTrace(objInst)) { + AbstractSpan span = ContextManager.activeSpan(); + parseResponseInfo((ActionResponse) ret, span); + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().log(t); + } + + private boolean isTrace(EnhancedInstance objInst) { + return objInst.getSkyWalkingDynamicField() != null && (boolean) objInst.getSkyWalkingDynamicField(); + } + + private void parseResponseInfo(ActionResponse response, AbstractSpan span) { + // search response + if (response instanceof SearchResponse) { + parseSearchResponse((SearchResponse) response, span); + return; + } + // bulk response + if (response instanceof BulkResponse) { + parseBulkResponse((BulkResponse) response, span); + return; + } + // get response + if (response instanceof GetResponse) { + parseGetResponse((GetResponse) response, span); + return; + } + // index response + if (response instanceof IndexResponse) { + parseIndexResponse((IndexResponse) response, span); + return; + } + // update response + if (response instanceof UpdateResponse) { + parseUpdateResponse((UpdateResponse) response, span); + return; + } + // delete response + if (response instanceof DeleteResponse) { + parseDeleteResponse((DeleteResponse) response, span); + return; + } + } + + private void parseSearchResponse(SearchResponse searchResponse, AbstractSpan span) { + span.tag(Constants.ES_TOOK_MILLIS, Long.toString(searchResponse.getTook().getMillis())); + span.tag(Constants.ES_TOTAL_HITS, Long.toString(searchResponse.getHits().getTotalHits().value)); + if (TRACE_DSL) { + String tagValue = searchResponse.toString(); + tagValue = ELASTICSEARCH_DSL_LENGTH_THRESHOLD > 0 ? StringUtil.cut(tagValue, ELASTICSEARCH_DSL_LENGTH_THRESHOLD) : tagValue; + Tags.DB_STATEMENT.set(span, tagValue); + } + } + + private void parseBulkResponse(BulkResponse bulkResponse, AbstractSpan span) { + span.tag(Constants.ES_TOOK_MILLIS, Long.toString(bulkResponse.getTook().getMillis())); + span.tag(Constants.ES_INGEST_TOOK_MILLIS, Long.toString(bulkResponse.getIngestTookInMillis())); + if (TRACE_DSL) { + String tagValue = bulkResponse.toString(); + tagValue = ELASTICSEARCH_DSL_LENGTH_THRESHOLD > 0 ? StringUtil.cut(tagValue, ELASTICSEARCH_DSL_LENGTH_THRESHOLD) : tagValue; + Tags.DB_STATEMENT.set(span, tagValue); + } + } + + private void parseGetResponse(GetResponse getResponse, AbstractSpan span) { + if (TRACE_DSL) { + String tagValue = getResponse.toString(); + tagValue = ELASTICSEARCH_DSL_LENGTH_THRESHOLD > 0 ? StringUtil.cut(tagValue, ELASTICSEARCH_DSL_LENGTH_THRESHOLD) : tagValue; + Tags.DB_STATEMENT.set(span, tagValue); + } + } + + private void parseIndexResponse(IndexResponse indexResponse, AbstractSpan span) { + if (TRACE_DSL) { + String tagValue = indexResponse.toString(); + tagValue = ELASTICSEARCH_DSL_LENGTH_THRESHOLD > 0 ? StringUtil.cut(tagValue, ELASTICSEARCH_DSL_LENGTH_THRESHOLD) : tagValue; + Tags.DB_STATEMENT.set(span, tagValue); + } + } + + private void parseUpdateResponse(UpdateResponse updateResponse, AbstractSpan span) { + if (TRACE_DSL) { + String tagValue = updateResponse.toString(); + tagValue = ELASTICSEARCH_DSL_LENGTH_THRESHOLD > 0 ? StringUtil.cut(tagValue, ELASTICSEARCH_DSL_LENGTH_THRESHOLD) : tagValue; + Tags.DB_STATEMENT.set(span, tagValue); + } + } + + private void parseDeleteResponse(DeleteResponse deleteResponse, AbstractSpan span) { + if (TRACE_DSL) { + String tagValue = deleteResponse.toString(); + tagValue = ELASTICSEARCH_DSL_LENGTH_THRESHOLD > 0 ? StringUtil.cut(tagValue, ELASTICSEARCH_DSL_LENGTH_THRESHOLD) : tagValue; + Tags.DB_STATEMENT.set(span, tagValue); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000000000000000000000000000000000..23fe26794490bfa6dd7b0629f88c7153f9a3a007 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,17 @@ +# 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. + +elasticsearch-7.x=org.apache.skywalking.apm.plugin.elasticsearch.v7.define.AdapterActionFutureInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 8dbf88d366a5ba4bc373bcfda42e7cdf100708b8..8bbca4a930d6f0f2230b272f6eee0fdc1961cf61 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -72,6 +72,7 @@ activemq-5.x-plugin elasticsearch-5.x-plugin elasticsearch-6.x-plugin + elasticsearch-7.x-plugin undertow-plugins rabbitmq-5.x-plugin dubbo-conflict-patch 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 41ba14d95ef08480af6051de8fe55280d0cf5262..07ee1511e13c234f84001a8373fe59e481c1b41a 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -16,6 +16,7 @@ - elastic-job-3.x - elasticsearch-5.x - elasticsearch-6.x +- elasticsearch-7.x - feign-default-http-9.x - feign-pathvar-9.x - finagle 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 6b9ee71862b855bb08216813b788956d59f92675..1c47b4052011c43907832e1b47681135967e76cc 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -76,6 +76,7 @@ metrics based on the tracing data. * [Elasticsearch](https://github.com/elastic/elasticsearch) * [transport-client](https://github.com/elastic/elasticsearch/tree/v5.2.0/client/transport) 5.2.x-5.6.x * [transport-client](https://github.com/elastic/elasticsearch/tree/v6.7.1/client/transport) 6.7.1-6.8.4 + * [transport-client](https://github.com/elastic/elasticsearch/tree/7.0/client/transport) 7.0.0-7.5.2 * [rest-high-level-client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.7/index.html) 6.7.1-6.8.4 * [rest-high-level-client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.0/java-rest-high.html) 7.0.0-7.5.2 * [Solr](https://github.com/apache/solr/) diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/elasticsearch-7.x-scenario/config/expectedData.yaml index fc3c726f6d4818d8e80d42e823ac31fbe44c6c3b..86e53ae405eb515ace4912ea6dd14041c4771161 100644 --- a/test/plugin/scenarios/elasticsearch-7.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/config/expectedData.yaml @@ -14,161 +14,301 @@ # See the License for the specific language governing permissions and # limitations under the License. segmentItems: -- serviceName: elasticsearch-7.x-scenario - segmentSize: ge 1 - segments: - - segmentId: not null - spans: - - operationName: Elasticsearch/Health - operationId: 0 - parentSpanId: 0 - spanId: 1 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 77 - isError: false - spanType: Exit - peer: not null - tags: - - {key: db.type, value: Elasticsearch} - skipAnalysis: 'false' - - operationName: Elasticsearch/GetSettings - operationId: 0 - parentSpanId: 0 - spanId: 2 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 77 - isError: false - spanType: Exit - peer: not null - tags: - - {key: db.type, value: Elasticsearch} - skipAnalysis: 'false' - - operationName: Elasticsearch/PutSettings - operationId: 0 - parentSpanId: 0 - spanId: 3 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 77 - isError: false - spanType: Exit - peer: not null - tags: - - {key: db.type, value: Elasticsearch} - - {key: db.statement, value: not null} - skipAnalysis: 'false' - - operationName: Elasticsearch/CreateRequest - operationId: 0 - parentSpanId: 0 - spanId: 4 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 77 - isError: false - spanType: Exit - peer: not null - tags: - - {key: db.type, value: Elasticsearch} - - {key: db.instance, value: not null} - - {key: db.statement, value: not null} - skipAnalysis: 'false' - - operationName: Elasticsearch/IndexRequest - operationId: 0 - parentSpanId: 0 - spanId: 5 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 77 - isError: false - spanType: Exit - peer: not null - tags: - - {key: db.type, value: Elasticsearch} - - {key: db.instance, value: not null} - - {key: db.statement, value: not null} - skipAnalysis: 'false' - - operationName: Elasticsearch/GetRequest - operationId: 0 - parentSpanId: 0 - spanId: 6 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 77 - isError: false - spanType: Exit - peer: not null - tags: - - {key: db.type, value: Elasticsearch} - - {key: db.instance, value: not null} - - {key: db.statement, value: not null} - skipAnalysis: 'false' - - operationName: Elasticsearch/SearchRequest - operationId: 0 - parentSpanId: 0 - spanId: 7 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 77 - isError: false - spanType: Exit - peer: not null - tags: - - {key: db.type, value: Elasticsearch} - - {key: db.instance, value: not null} - - {key: db.statement, value: not null} - skipAnalysis: 'false' - - operationName: Elasticsearch/UpdateRequest - operationId: 0 - parentSpanId: 0 - spanId: 8 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 77 - isError: false - spanType: Exit - peer: not null - tags: - - {key: db.type, value: Elasticsearch} - - {key: db.instance, value: not null} - - {key: db.statement, value: not null} - skipAnalysis: 'false' - - operationName: Elasticsearch/DeleteRequest - operationId: 0 - parentSpanId: 0 - spanId: 9 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 77 - isError: false - spanType: Exit - peer: not null - tags: - - {key: db.type, value: Elasticsearch} - - {key: db.instance, value: not null} - skipAnalysis: 'false' - - operationName: /elasticsearch-case/case/elasticsearch - operationId: 0 - parentSpanId: -1 - spanId: 0 - spanLayer: Http - startTime: nq 0 - endTime: nq 0 - componentId: 1 - isError: false - spanType: Entry - peer: '' - tags: - - {key: url, value: 'http://localhost:8080/elasticsearch-case/case/elasticsearch'} - - {key: http.method, value: GET} - skipAnalysis: 'false' + - serviceName: elasticsearch-7.x-scenario + segmentSize: ge 1 + segments: + - segmentId: not null + spans: + - operationName: Elasticsearch/Health + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + skipAnalysis: 'false' + - operationName: Elasticsearch/GetSettings + operationId: 0 + parentSpanId: 0 + spanId: 2 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + skipAnalysis: 'false' + - operationName: Elasticsearch/PutSettings + operationId: 0 + parentSpanId: 0 + spanId: 3 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/CreateRequest + operationId: 0 + parentSpanId: 0 + spanId: 4 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/IndexRequest + operationId: 0 + parentSpanId: 0 + spanId: 5 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/GetRequest + operationId: 0 + parentSpanId: 0 + spanId: 6 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/SearchRequest + operationId: 0 + parentSpanId: 0 + spanId: 7 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/UpdateRequest + operationId: 0 + parentSpanId: 0 + spanId: 8 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/DeleteRequest + operationId: 0 + parentSpanId: 0 + spanId: 9 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/IndexRequest + operationId: 0 + parentSpanId: 0 + spanId: 10 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 48 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + - { key: node.address, value: not null } + - { key: es.indices, value: not null } + - { key: es.types, value: not null } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/actionGet + operationId: 0 + parentSpanId: 0 + spanId: 11 + startTime: nq 0 + endTime: nq 0 + componentId: 48 + isError: false + spanType: Local + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/GetRequest + operationId: 0 + parentSpanId: 0 + spanId: 12 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 48 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + - { key: node.address, value: not null } + - { key: es.indices, value: not null } + - { key: es.types, value: not null } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/SearchRequest + operationId: 0 + parentSpanId: 0 + spanId: 13 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 48 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + - { key: node.address, value: not null } + - { key: es.indices, value: not null } + - { key: es.types, value: not null } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/actionGet + operationId: 0 + parentSpanId: 0 + spanId: 14 + startTime: nq 0 + endTime: nq 0 + componentId: 48 + isError: false + spanType: Local + tags: + - {key: db.type, value: Elasticsearch} + - {key: es.took_millis, value: not null } + - {key: es.total_hits, value: not null } + - {key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/UpdateRequest + operationId: 0 + parentSpanId: 0 + spanId: 15 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 48 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + - { key: node.address, value: not null } + - { key: es.indices, value: not null } + - { key: es.types, value: not null } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/DeleteRequest + operationId: 0 + parentSpanId: 0 + spanId: 16 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 48 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + - { key: node.address, value: not null } + - { key: es.indices, value: not null } + - { key: es.types, value: not null } + - { key: db.statement, value: not null } + skipAnalysis: 'false' + - operationName: Elasticsearch/DeleteIndexRequest + operationId: 0 + parentSpanId: 0 + spanId: 17 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 48 + isError: false + spanType: Exit + peer: not null + tags: + - { key: db.type, value: Elasticsearch } + - { key: db.instance, value: not null } + - { key: node.address, value: not null } + - { key: es.indices, value: not null } + skipAnalysis: 'false' + - operationName: /elasticsearch-case/case/elasticsearch + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + tags: + - { key: url, value: 'http://localhost:8080/elasticsearch-case/case/elasticsearch' } + - { key: http.method, value: GET } + skipAnalysis: 'false' \ No newline at end of file diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/pom.xml b/test/plugin/scenarios/elasticsearch-7.x-scenario/pom.xml index 069a71445cd3b5282843423c3a0090ec9f17a820..6aee670a7437508dc95fdf0f50de5dc1e913203d 100644 --- a/test/plugin/scenarios/elasticsearch-7.x-scenario/pom.xml +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/pom.xml @@ -98,6 +98,18 @@ elasticsearch ${test.framework.version} + + + org.elasticsearch.client + transport + ${test.framework.version} + + + + org.elasticsearch.plugin + transport-netty4-client + ${test.framework.version} + diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/RestHighLevelClientCase.java b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/RestHighLevelClientCase.java new file mode 100644 index 0000000000000000000000000000000000000000..2a3bccfdbcaef303c29bdaa32c59567a1fcc70b3 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/RestHighLevelClientCase.java @@ -0,0 +1,270 @@ +/* + * 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.testcase.elasticsearch; + +import java.io.IOException; +import java.util.Map; +import java.util.UUID; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.skywalking.apm.testcase.elasticsearch.controller.CaseController; +import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest; +import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest; +import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse; +import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; +import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; +import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; +import org.elasticsearch.action.get.GetRequest; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.index.IndexResponse; +import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.support.master.AcknowledgedResponse; +import org.elasticsearch.action.update.UpdateRequest; +import org.elasticsearch.action.update.UpdateResponse; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.client.indices.CreateIndexRequest; +import org.elasticsearch.client.indices.CreateIndexResponse; +import org.elasticsearch.cluster.health.ClusterHealthStatus; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.ByteSizeUnit; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.indices.recovery.RecoverySettings; +import org.elasticsearch.script.Script; +import org.elasticsearch.script.ScriptType; +import org.elasticsearch.search.builder.SearchSourceBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import static java.util.Collections.singletonMap; + +@Component +public class RestHighLevelClientCase { + + private static final Logger LOGGER = LogManager.getLogger(CaseController.class); + + @Autowired + private RestHighLevelClient client; + + public String healthCheck() throws Exception { + ClusterHealthRequest request = new ClusterHealthRequest(); + request.timeout(TimeValue.timeValueSeconds(10)); + request.waitForStatus(ClusterHealthStatus.GREEN); + + ClusterHealthResponse response = client.cluster().health(request, RequestOptions.DEFAULT); + if (response.isTimedOut()) { + String message = "elastic search node start fail!"; + LOGGER.error(message); + throw new RuntimeException(message); + } + return "Success"; + } + + public String elasticsearch() throws Exception { + String indexName = UUID.randomUUID().toString(); + try { + // health + health(); + + // get settings + getSettings(); + + // put settings + putSettings(); + + // create + createIndex(indexName); + + // index + index(indexName); + + client.indices().refresh(new RefreshRequest(indexName), RequestOptions.DEFAULT); + + // get + get(indexName); + + // search + search(indexName); + + // update + update(indexName); + + // delete + delete(indexName); + } finally { + if (null != client) { + client.close(); + } + } + return "Success"; + } + + private void health() throws IOException { + ClusterHealthRequest request = new ClusterHealthRequest(); + ClusterHealthResponse response = client.cluster().health(request, RequestOptions.DEFAULT); + if (response.isTimedOut()) { + String message = "elastic search health fail!"; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + private void putSettings() throws IOException { + ClusterUpdateSettingsRequest request = new ClusterUpdateSettingsRequest(); + String transientSettingKey = + RecoverySettings.INDICES_RECOVERY_MAX_BYTES_PER_SEC_SETTING.getKey(); + int transientSettingValue = 10; + Settings transientSettings = Settings.builder() + .put(transientSettingKey, transientSettingValue, ByteSizeUnit.BYTES) + .build(); + request.transientSettings(transientSettings); + ClusterUpdateSettingsResponse response = client.cluster().putSettings(request, RequestOptions.DEFAULT); + if (response == null) { + String message = "elasticsearch put settings fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + private void getSettings() throws IOException { + ClusterGetSettingsResponse response = client.cluster() + .getSettings( + new ClusterGetSettingsRequest(), + RequestOptions.DEFAULT + ); + if (response == null) { + String message = "elasticsearch get settings fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + private void createIndex(String indexName) throws IOException { + CreateIndexRequest request = new CreateIndexRequest(indexName); + + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.startObject(); + { + builder.startObject("properties"); + { + builder.startObject("author"); + { + builder.field("type", "keyword"); + } + builder.endObject(); + builder.startObject("title"); + { + builder.field("type", "keyword"); + } + builder.endObject(); + } + builder.endObject(); + } + builder.endObject(); + request.mapping(builder); + + request.settings(Settings.builder().put("index.number_of_shards", 1).put("index.number_of_replicas", 0)); + + CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); + if (!createIndexResponse.isAcknowledged()) { + String message = "elasticsearch create index fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + private void index(String indexName) throws IOException { + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.startObject(); + { + builder.field("author", "Marker"); + builder.field("title", "Java programing."); + } + builder.endObject(); + IndexRequest indexRequest = new IndexRequest(indexName).id("1").source(builder); + + IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT); + if (indexResponse.status().getStatus() >= 400) { + String message = "elasticsearch index data fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + private void get(String indexName) throws IOException { + GetRequest getRequest = new GetRequest(indexName, "1"); + GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT); + + if (!getResponse.isExists()) { + String message = "elasticsearch get data fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + private void update(String indexName) throws IOException { + UpdateRequest request = new UpdateRequest(indexName, "1"); + Map parameters = singletonMap("title", "c++ programing."); + Script inline = new Script(ScriptType.INLINE, "painless", "ctx._source.title = params.title", parameters); + request.script(inline); + + UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT); + if (updateResponse.getVersion() != 2) { + String message = "elasticsearch update data fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + private void delete(String indexName) throws IOException { + DeleteIndexRequest request = new DeleteIndexRequest(indexName); + AcknowledgedResponse deleteIndexResponse = client.indices().delete(request, RequestOptions.DEFAULT); + if (!deleteIndexResponse.isAcknowledged()) { + String message = "elasticsearch delete index fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + private void search(String indexName) throws IOException { + SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); + sourceBuilder.query(QueryBuilders.termQuery("author", "Marker")); + sourceBuilder.from(0); + sourceBuilder.size(10); + + SearchRequest searchRequest = new SearchRequest(); + searchRequest.indices(indexName); + searchRequest.source(sourceBuilder); + SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); + + int length = searchResponse.getHits().getHits().length; + if (!(length > 0)) { + String message = "elasticsearch search data fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } +} diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/TransportClientCase.java b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/TransportClientCase.java new file mode 100644 index 0000000000000000000000000000000000000000..7dcf6b4b97ef3d1a1fd78a820e833df3fad5b5d5 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/TransportClientCase.java @@ -0,0 +1,100 @@ +/* + * 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.testcase.elasticsearch; + +import java.io.IOException; +import java.util.UUID; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.elasticsearch.client.Client; +import org.elasticsearch.client.transport.TransportClient; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class TransportClientCase { + + private static final Logger LOGGER = LogManager.getLogger(TransportClientCase.class); + + @Autowired + private TransportClient client; + + public boolean elasticsearch() throws Exception { + String indexName = UUID.randomUUID().toString(); + try { + // create + index(client, indexName); + // get + get(client, indexName); + // search + search(client, indexName); + // update + update(client, indexName); + // delete + delete(client, indexName); + // remove index + client.admin().indices().prepareDelete(indexName).execute(); + } finally { + if (null != client) { + client.close(); + } + } + return true; + } + + private void index(Client client, String indexName) throws IOException { + try { + client.prepareIndex(indexName, "test", "1") + .setSource(XContentFactory.jsonBuilder() + .startObject() + .field("name", "mysql innodb") + .field("price", "0") + .field("language", "chinese") + .endObject()) + .get(); + } catch (IOException e) { + LOGGER.error("index document error.", e); + throw e; + } + } + + private void get(Client client, String indexName) { + client.prepareGet().setIndex(indexName).setId("1").execute(); + } + + private void update(Client client, String indexName) throws IOException { + try { + client.prepareUpdate(indexName, "test", "1") + .setDoc(XContentFactory.jsonBuilder().startObject().field("price", "9.9").endObject()) + .execute(); + } catch (IOException e) { + LOGGER.error("update document error.", e); + throw e; + } + } + + private void delete(Client client, String indexName) { + client.prepareDelete(indexName, "test", "1").execute(); + } + + private void search(Client client, String indexName) { + client.prepareSearch(indexName).setTypes("test").setSize(10).execute().actionGet(); + } +} diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/config/TransportClientConfig.java b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/config/TransportClientConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..7b2fb773e3f7603210efe67ed8b5fa38ed239309 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/config/TransportClientConfig.java @@ -0,0 +1,71 @@ +/* + * 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.testcase.elasticsearch.config; + +import java.net.InetAddress; +import org.elasticsearch.client.transport.TransportClient; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.transport.client.PreBuiltTransportClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class TransportClientConfig { + + @Value("${elasticsearch.server}") + private String elasticsearchHost; + + public final static Integer PORT = 9300; //port + + @Bean + public TransportClient getESClientConnection() + throws Exception { + + TransportClient client = null; + Settings settings = Settings.builder() + .put("cluster.name", "docker-node") + .put("client.transport.sniff", false) + .build(); + + client = new PreBuiltTransportClient(settings); + for (TransportAddress i : parseEsHost()) { + client.addTransportAddress(i); + } + return client; + } + + private TransportAddress[] parseEsHost() + throws Exception { + TransportAddress[] transportAddresses = null; + if (!elasticsearchHost.isEmpty()) { + String[] hostIp = elasticsearchHost.split(","); + transportAddresses = new TransportAddress[hostIp.length]; + + for (int i = 0; i < hostIp.length; ++i) { + String[] hostIpItem = hostIp[i].split(":"); + String ip = hostIpItem[0].trim(); + String port = hostIpItem[1].trim(); + transportAddresses[i] = new TransportAddress(InetAddress.getByName(ip), PORT); + } + } + return transportAddresses; + } +} diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java index c55f83c142b050c5fb49510a4e190938bde00818..be5fdf5393694c429483f053b7db433417e1cc35 100644 --- a/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java @@ -18,254 +18,39 @@ package org.apache.skywalking.apm.testcase.elasticsearch.controller; -import java.io.IOException; -import java.util.Map; -import java.util.UUID; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest; -import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; -import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest; -import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse; -import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; -import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; -import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; -import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; -import org.elasticsearch.action.get.GetRequest; -import org.elasticsearch.action.get.GetResponse; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.action.index.IndexResponse; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.action.support.master.AcknowledgedResponse; -import org.elasticsearch.action.update.UpdateRequest; -import org.elasticsearch.action.update.UpdateResponse; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.client.indices.CreateIndexRequest; -import org.elasticsearch.client.indices.CreateIndexResponse; -import org.elasticsearch.cluster.health.ClusterHealthStatus; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.unit.ByteSizeUnit; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.indices.recovery.RecoverySettings; -import org.elasticsearch.script.Script; -import org.elasticsearch.script.ScriptType; -import org.elasticsearch.search.builder.SearchSourceBuilder; +import org.apache.skywalking.apm.testcase.elasticsearch.RestHighLevelClientCase; +import org.apache.skywalking.apm.testcase.elasticsearch.TransportClientCase; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import static java.util.Collections.singletonMap; - @RestController -@RequestMapping("/case") +@RequestMapping("/elasticsearch-case/case") public class CaseController { private static final Logger LOGGER = LogManager.getLogger(CaseController.class); @Autowired - private RestHighLevelClient client; + private RestHighLevelClientCase restHighLevelClientCase; - @GetMapping("/healthCheck") - public String healthCheck() throws Exception { - ClusterHealthRequest request = new ClusterHealthRequest(); - request.timeout(TimeValue.timeValueSeconds(10)); - request.waitForStatus(ClusterHealthStatus.GREEN); + @Autowired + private TransportClientCase transportClientCase; - ClusterHealthResponse response = client.cluster().health(request, RequestOptions.DEFAULT); - if (response.isTimedOut()) { - String message = "elastic search node start fail!"; - LOGGER.error(message); - throw new RuntimeException(message); - } + @GetMapping("/healthCheck") + public String healthcheck() throws Exception { + restHighLevelClientCase.healthCheck(); return "Success"; } @GetMapping("/elasticsearch") public String elasticsearch() throws Exception { - String indexName = UUID.randomUUID().toString(); - try { - // health - health(); - - // get settings - getSettings(); - - // put settings - putSettings(); - - // create - createIndex(indexName); - - // index - index(indexName); + restHighLevelClientCase.elasticsearch(); + transportClientCase.elasticsearch(); - client.indices().refresh(new RefreshRequest(indexName), RequestOptions.DEFAULT); - - // get - get(indexName); - - // search - search(indexName); - - // update - update(indexName); - - // delete - delete(indexName); - } finally { - if (null != client) { - client.close(); - } - } return "Success"; } - - private void health() throws IOException { - ClusterHealthRequest request = new ClusterHealthRequest(); - ClusterHealthResponse response = client.cluster().health(request, RequestOptions.DEFAULT); - if (response.isTimedOut()) { - String message = "elastic search health fail!"; - LOGGER.error(message); - throw new RuntimeException(message); - } - } - - private void putSettings() throws IOException { - ClusterUpdateSettingsRequest request = new ClusterUpdateSettingsRequest(); - String transientSettingKey = - RecoverySettings.INDICES_RECOVERY_MAX_BYTES_PER_SEC_SETTING.getKey(); - int transientSettingValue = 10; - Settings transientSettings = Settings.builder() - .put(transientSettingKey, transientSettingValue, ByteSizeUnit.BYTES) - .build(); - request.transientSettings(transientSettings); - ClusterUpdateSettingsResponse response = client.cluster().putSettings(request, RequestOptions.DEFAULT); - if (response == null) { - String message = "elasticsearch put settings fail."; - LOGGER.error(message); - throw new RuntimeException(message); - } - } - - private void getSettings() throws IOException { - ClusterGetSettingsResponse response = client.cluster().getSettings(new ClusterGetSettingsRequest(), RequestOptions.DEFAULT); - if (response == null) { - String message = "elasticsearch get settings fail."; - LOGGER.error(message); - throw new RuntimeException(message); - } - } - - private void createIndex(String indexName) throws IOException { - CreateIndexRequest request = new CreateIndexRequest(indexName); - - XContentBuilder builder = XContentFactory.jsonBuilder(); - builder.startObject(); - { - builder.startObject("properties"); - { - builder.startObject("author"); - { - builder.field("type", "keyword"); - } - builder.endObject(); - builder.startObject("title"); - { - builder.field("type", "keyword"); - } - builder.endObject(); - } - builder.endObject(); - } - builder.endObject(); - request.mapping(builder); - - request.settings(Settings.builder().put("index.number_of_shards", 1).put("index.number_of_replicas", 0)); - - CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); - if (!createIndexResponse.isAcknowledged()) { - String message = "elasticsearch create index fail."; - LOGGER.error(message); - throw new RuntimeException(message); - } - } - - private void index(String indexName) throws IOException { - XContentBuilder builder = XContentFactory.jsonBuilder(); - builder.startObject(); - { - builder.field("author", "Marker"); - builder.field("title", "Java programing."); - } - builder.endObject(); - IndexRequest indexRequest = new IndexRequest(indexName).id("1").source(builder); - - IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT); - if (indexResponse.status().getStatus() >= 400) { - String message = "elasticsearch index data fail."; - LOGGER.error(message); - throw new RuntimeException(message); - } - } - - private void get(String indexName) throws IOException { - GetRequest getRequest = new GetRequest(indexName, "1"); - GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT); - - if (!getResponse.isExists()) { - String message = "elasticsearch get data fail."; - LOGGER.error(message); - throw new RuntimeException(message); - } - } - - private void update(String indexName) throws IOException { - UpdateRequest request = new UpdateRequest(indexName, "1"); - Map parameters = singletonMap("title", "c++ programing."); - Script inline = new Script(ScriptType.INLINE, "painless", "ctx._source.title = params.title", parameters); - request.script(inline); - - UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT); - if (updateResponse.getVersion() != 2) { - String message = "elasticsearch update data fail."; - LOGGER.error(message); - throw new RuntimeException(message); - } - } - - private void delete(String indexName) throws IOException { - DeleteIndexRequest request = new DeleteIndexRequest(indexName); - AcknowledgedResponse deleteIndexResponse = client.indices().delete(request, RequestOptions.DEFAULT); - if (!deleteIndexResponse.isAcknowledged()) { - String message = "elasticsearch delete index fail."; - LOGGER.error(message); - throw new RuntimeException(message); - } - } - - private void search(String indexName) throws IOException { - SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); - sourceBuilder.query(QueryBuilders.termQuery("author", "Marker")); - sourceBuilder.from(0); - sourceBuilder.size(10); - - SearchRequest searchRequest = new SearchRequest(); - searchRequest.indices(indexName); - searchRequest.source(sourceBuilder); - SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); - - int length = searchResponse.getHits().getHits().length; - if (!(length > 0)) { - String message = "elasticsearch search data fail."; - LOGGER.error(message); - throw new RuntimeException(message); - } - } } diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/resources/application.yaml index 7cc560285a6a2be35d4b771a2823e5618dd66cd3..ba18cc1c03f19f7c97a26e959924437ad148fa70 100644 --- a/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/resources/application.yaml +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/resources/application.yaml @@ -17,7 +17,5 @@ # server: port: 8080 - servlet: - context-path: /elasticsearch-case logging: - config: classpath:log4j2.xml + config: classpath:log4j2.xml \ No newline at end of file