From ba21072ca1d00276e11a97d5e5cb5312424babef Mon Sep 17 00:00:00 2001 From: daming Date: Wed, 3 Jul 2019 21:31:18 +0800 Subject: [PATCH 1/2] new branch for solr-plugin --- .../trace/component/ComponentsDefine.java | 3 + .../apm/agent/core/conf/Config.java | 12 ++ apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../apm-sdk-plugin/solr-7.x-plugin/pom.xml | 56 +++++++++ .../RequestHandlerBaseInstrumentation.java | 64 ++++++++++ .../solr/RequestHandlerBaseInterceptor.java | 111 ++++++++++++++++++ .../apm/plugin/solr/commons/Constants.java | 41 +++++++ .../apm/plugin/solr/commons/NamesMap.java | 68 +++++++++++ .../HttpShardHandlerInstrumentation.java | 64 ++++++++++ .../search/HttpShardHandlerInterceptor.java | 68 +++++++++++ .../QueryStageTracerInstrumentation.java | 64 ++++++++++ .../search/QueryStageTracerInterceptor.java | 70 +++++++++++ .../solr/shard/ShardConnectorInterceptor.java | 58 +++++++++ .../solr/shard/ShardRequestInterceptor.java | 110 +++++++++++++++++ .../solr/shard/SolrClientInstrumentation.java | 97 +++++++++++++++ ...urrentUpdateSolrClientInstrumentation.java | 80 +++++++++++++ ...ConcurrentUpdateSolrClientInterceptor.java | 78 ++++++++++++ .../UpdateShardHandlerInstrumentation.java | 64 ++++++++++ .../update/UpdateShardHandlerInterceptor.java | 45 +++++++ .../wrappers/CloaseableHttpClientWrapper.java | 77 ++++++++++++ .../solr/wrappers/ModSolrParamsWrapper.java | 45 +++++++ .../src/main/resources/skywalking-plugin.def | 22 ++++ 22 files changed, 1298 insertions(+) create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/RequestHandlerBaseInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/RequestHandlerBaseInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/commons/Constants.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/commons/NamesMap.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/HttpShardHandlerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/HttpShardHandlerInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/QueryStageTracerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/QueryStageTracerInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/ShardConnectorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/ShardRequestInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/SolrClientInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/ConcurrentUpdateSolrClientInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/ConcurrentUpdateSolrClientInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/UpdateShardHandlerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/UpdateShardHandlerInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/wrappers/CloaseableHttpClientWrapper.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/wrappers/ModSolrParamsWrapper.java create mode 100644 apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/resources/skywalking-plugin.def diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java index e02e8b22e2a4..88dda710c5f2 100644 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -124,6 +124,8 @@ public class ComponentsDefine { public static final OfficialComponent SOLRJ = new OfficialComponent(63, "solrj"); + public static final OfficialComponent SOLR = new OfficialComponent(64, "solr"); + public static final OfficialComponent SPRING_ASYNC = new OfficialComponent(65, "SpringAsync"); private static ComponentsDefine INSTANCE = new ComponentsDefine(); @@ -184,6 +186,7 @@ public ComponentsDefine() { addComponent(SPRING_CLOUD_GATEWAY); addComponent(RESTEASY); addComponent(SOLRJ); + addComponent(SOLR); } private void addComponent(OfficialComponent component) { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java index 9efab982bf5b..19dfb5fea991 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java @@ -226,5 +226,17 @@ public static class SolrJ { public static boolean TRACE_OPS_PARAMS = false; } + public static class Solr { + + /** + * If true, the Trace_ID will be put into MDC. Default is false. + */ + public static boolean PRINT_TRACE_ID_ON_LOG = false; + + /** + * If true, not trace admin request, include /admin/ping, /admin/metrics etc. Default is true. + */ + public static boolean SKIP_ADMIN_REQUEST = true; + } } } diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 87e9266f54c4..e2d5e7e42a07 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -74,6 +74,7 @@ vertx-plugins resteasy-plugin solrj-7.x-plugin + solr-7.x-plugin pom diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/pom.xml new file mode 100644 index 000000000000..1a0dd52ae3e7 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/pom.xml @@ -0,0 +1,56 @@ + + + + + apm-sdk-plugin + org.apache.skywalking + 6.3.0-SNAPSHOT + + 4.0.0 + + apm-solr-7.x-plugin + jar + + solr-7.x-plugin + http://maven.apache.org + + + UTF-8 + 7.5.0 + 7.5.0 + + + + + org.apache.solr + solr-core + ${solr-core.version} + provided + + + + org.apache.solr + solr-solrj + ${solr-solrj.version} + provided + + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/RequestHandlerBaseInstrumentation.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/RequestHandlerBaseInstrumentation.java new file mode 100644 index 000000000000..34ff960ab1fb --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/RequestHandlerBaseInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.solr; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; +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.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; + +public class RequestHandlerBaseInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + }; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public boolean isOverrideArgs() { + return false; + } + + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named("handleRequest"); + } + + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.solr.RequestHandlerBaseInterceptor"; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName("org.apache.solr.handler.RequestHandlerBase"); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/RequestHandlerBaseInterceptor.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/RequestHandlerBaseInterceptor.java new file mode 100644 index 000000000000..0edd14b50f53 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/RequestHandlerBaseInterceptor.java @@ -0,0 +1,111 @@ +/* + * 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.solr; + +import org.apache.skywalking.apm.agent.core.conf.Config; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +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.solr.common.params.ShardParams; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.response.SolrQueryResponse; +import org.apache.solr.update.processor.DistributingUpdateProcessorFactory; +import org.slf4j.MDC; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Method; + +import static org.apache.skywalking.apm.plugin.solr.commons.Constants.*; + +public class RequestHandlerBaseInterceptor implements InstanceMethodsAroundInterceptor { + private static final ILog LOG = LogManager.getLogger(RequestHandlerBaseInterceptor.class); + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + final SolrQueryRequest request = (SolrQueryRequest) allArguments[0]; + if (Config.Plugin.Solr.SKIP_ADMIN_REQUEST && request.getPath().startsWith(SKIP_ADMIN_PREF)) { + return; + } + + HttpServletRequest req = request.getHttpSolrCall().getReq(); + ContextCarrier carrier = new ContextCarrier(); + CarrierItem items = carrier.items(); + while (items.hasNext()) { + items = items.next(); + items.setHeadValue(req.getHeader(items.getHeadKey())); + } + + SolrParams params = request.getParams(); + String operationPref = OPER_SOLR_PREF; + + if ((params.getBool(ShardParams.IS_SHARD, false) && params.getInt(ShardParams.SHARDS_PURPOSE, 0) != 0) + || params.get(DistributingUpdateProcessorFactory.DISTRIB_UPDATE_PARAM) != null) { + operationPref = OPER_SHARD_PREF; + } + + createSpan(operationPref + req.getServletPath(), carrier); + if (Config.Plugin.Solr.PRINT_TRACE_ID_ON_LOG) { + MDC.put(MDC_KEY_TRACE_ID, TRACE_ID_PREF + ContextManager.getGlobalTraceId()); + } + } + + private final AbstractSpan createSpan(String operation, ContextCarrier carrier) { + AbstractSpan span = ContextManager.createEntrySpan(operation, carrier); + span.setComponent(ComponentsDefine.SOLR) + .setLayer(SpanLayer.HTTP); + return span; + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + final SolrQueryRequest request = (SolrQueryRequest) allArguments[0]; + if (Config.Plugin.Solr.SKIP_ADMIN_REQUEST && request.getPath().startsWith(SKIP_ADMIN_PREF)) { + return ret; + } + + if (ContextManager.isActive()) { + SolrQueryResponse response = (SolrQueryResponse) allArguments[1]; + Exception exp = response.getException(); + if (exp != null) { + ContextManager.activeSpan().errorOccurred().log(exp); + } + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + if (ContextManager.isActive()) { + ContextManager.activeSpan().errorOccurred().log(t); + } + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/commons/Constants.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/commons/Constants.java new file mode 100644 index 000000000000..ab33a8335fa8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/commons/Constants.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.solr.commons; + +public interface Constants { + String SW_ENHANCE_FLAG = "_sw_enhance_flag_"; + + String OPER_SHARD_PREF = "Solr/shard"; + + String OPER_SHARD_PREF_SLASH = "Solr/shard/"; + + String OPER_STAGE_PREF = "Solr/stage/"; + + String OPER_SOLR_PREF = "Solr"; + + String SKIP_ADMIN_PREF = "/admin/"; + + String TRACE_ID_PREF = "t:"; + + String MDC_KEY_CORE = "core"; + + String MDC_KEY_NODE_NAME = "node_name"; + + String MDC_KEY_TRACE_ID = "traceId"; +} diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/commons/NamesMap.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/commons/NamesMap.java new file mode 100644 index 000000000000..d262524b8e95 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/commons/NamesMap.java @@ -0,0 +1,68 @@ +/* + * 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.solr.commons; + +import org.apache.solr.handler.component.ShardRequest; + +public class NamesMap { + private static final String[] PURPOSENAMES = { + "/PRIVATE", + "/GET_TERM_DFS", + "/GET_TOP_IDS", + "/REFINE_TOP_IDS", + "/GET_FACETS", + "/REFINE_FACETS", + "/GET_FIELDS", + "/GET_HIGHLIGHTS", + "/GET_DEBUG", + "/GET_STATS", + "/GET_TERMS", + "/GET_TOP_GROUPS", + "/GET_MLT_RESULTS", + "/REFINE_PIVOT_FACETS", + "/SET_TERM_STATS", + "/GET_TERM_STATS" + }; + + public static String getStagName(int stage) { + switch (stage) { + case 0: + return "START"; + case 1000: + return "PARSE_QUERY"; + case 1500: + return "TOP_GROUPS"; + case 2000: + return "EXECUTE_QUERY"; + case 3000: + return "GET_FIELDS"; + case Integer.MAX_VALUE: + return "DONE"; + default: + return "UNKNOWN"; + } + } + + public static String gePurposeName(int purpose) { + if (purpose < ShardRequest.PURPOSE_PRIVATE || purpose > ShardRequest.PURPOSE_GET_TERM_STATS) + return "/PENDING"; + return PURPOSENAMES[Integer.numberOfTrailingZeros(purpose)]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/HttpShardHandlerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/HttpShardHandlerInstrumentation.java new file mode 100644 index 000000000000..b597aa244906 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/HttpShardHandlerInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.solr.search; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; +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.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; + +public class HttpShardHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + }; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public boolean isOverrideArgs() { + return true; + } + + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named("submit"); + } + + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.solr.search.HttpShardHandlerInterceptor"; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName("org.apache.solr.handler.component.HttpShardHandler"); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/HttpShardHandlerInterceptor.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/HttpShardHandlerInterceptor.java new file mode 100644 index 000000000000..74a434e91e44 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/HttpShardHandlerInterceptor.java @@ -0,0 +1,68 @@ +/* + * 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. + * + */ + /* + * 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.solr.search; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +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.plugin.solr.wrappers.ModSolrParamsWrapper; +import org.apache.solr.common.params.SolrParams; + +import java.lang.reflect.Method; + +public class HttpShardHandlerInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + if (ContextManager.isActive()) { + ModSolrParamsWrapper paramsWrapper = new ModSolrParamsWrapper((SolrParams) allArguments[2]); + paramsWrapper.setSkyWalkingDynamicField(ContextManager.capture()); + allArguments[2] = paramsWrapper; + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/QueryStageTracerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/QueryStageTracerInstrumentation.java new file mode 100644 index 000000000000..81a233b45aff --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/QueryStageTracerInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.solr.search; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; +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.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; + +public class QueryStageTracerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + }; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public boolean isOverrideArgs() { + return false; + } + + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named("distributedProcess").or(ElementMatchers.named("finishStage")); + } + + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.solr.search.QueryStageTracerInterceptor"; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName("org.apache.solr.handler.component.QueryComponent"); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/QueryStageTracerInterceptor.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/QueryStageTracerInterceptor.java new file mode 100644 index 000000000000..04451443966d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/search/QueryStageTracerInterceptor.java @@ -0,0 +1,70 @@ +/* + * 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.solr.search; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +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.solr.commons.NamesMap; +import org.apache.solr.handler.component.ResponseBuilder; + +import java.lang.reflect.Method; + +import static org.apache.skywalking.apm.plugin.solr.commons.Constants.OPER_STAGE_PREF; + +public class QueryStageTracerInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + if (method.getName().equals("distributedProcess")) { + ContextSnapshot snapshot = null; + if (ContextManager.isActive()) { + snapshot = ContextManager.capture(); + } + + ResponseBuilder rb = (ResponseBuilder) allArguments[0]; + AbstractSpan span = ContextManager.createLocalSpan(OPER_STAGE_PREF + NamesMap.getStagName(rb.stage)); + span.setComponent(ComponentsDefine.SOLR); + + if (snapshot != null) { + ContextManager.continued(snapshot); + } + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + if (method.getName().equals("finishStage")) { + if (ContextManager.isActive()) + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/ShardConnectorInterceptor.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/ShardConnectorInterceptor.java new file mode 100644 index 000000000000..3a4b04774a5c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/ShardConnectorInterceptor.java @@ -0,0 +1,58 @@ +/* + * 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.solr.shard; + +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +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 java.lang.reflect.Method; + +public class ShardConnectorInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + if (!ContextManager.isActive()) + return; + + HttpRequestBase request = (HttpRequestBase) allArguments[0]; + ContextCarrier carrier = new ContextCarrier(); + ContextManager.inject(carrier); + CarrierItem items = carrier.items(); + while (items.hasNext()) { + items = items.next(); + request.setHeader(items.getHeadKey(), items.getHeadValue()); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/ShardRequestInterceptor.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/ShardRequestInterceptor.java new file mode 100644 index 000000000000..0ce26b45f820 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/ShardRequestInterceptor.java @@ -0,0 +1,110 @@ +/* + * 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.solr.shard; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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.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.solr.commons.NamesMap; +import org.apache.skywalking.apm.plugin.solr.wrappers.ModSolrParamsWrapper; +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.apache.solr.common.params.ModifiableSolrParams; +import org.apache.solr.common.params.ShardParams; +import org.apache.solr.common.params.SolrParams; + +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; + +import static org.apache.skywalking.apm.plugin.solr.commons.Constants.*; + +public class ShardRequestInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + HttpSolrClient client = (HttpSolrClient) objInst; + String peer = "", core = ""; + try { + URL url = new URL(client.getBaseURL()); + peer = url.getHost() + ":" + url.getPort(); + int idx = url.getPath().lastIndexOf('/'); + if (idx > 0) { + core = url.getPath().substring(idx); + } + } catch (MalformedURLException ignore) { + } + objInst.setSkyWalkingDynamicField(new String[]{peer, core}); + } + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + SolrRequest request = (SolrRequest) allArguments[0]; + if (request.getPath().startsWith(SKIP_ADMIN_PREF)) + return; + + String[] info = (String[]) objInst.getSkyWalkingDynamicField(); + SolrParams params = request.getParams(); + + ContextSnapshot snapshot = null; + String operationName = OPER_SHARD_PREF + info[1] + request.getPath(); + if (params.getBool(SW_ENHANCE_FLAG, false)) { + if (params instanceof ModSolrParamsWrapper) { + EnhancedInstance instance = (EnhancedInstance) request.getParams(); + snapshot = (ContextSnapshot) instance.getSkyWalkingDynamicField(); + } + ((ModifiableSolrParams) params).remove(SW_ENHANCE_FLAG); + final int purpose = params.getInt(ShardParams.SHARDS_PURPOSE, 0); + operationName = operationName + NamesMap.gePurposeName(purpose); + } + + AbstractSpan span = ContextManager.createExitSpan(operationName, info[0]); + span.setComponent(ComponentsDefine.SOLR); + span.setLayer(SpanLayer.HTTP); + + if (snapshot != null) { + ContextManager.continued(snapshot); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + SolrRequest request = (SolrRequest) allArguments[0]; + if (!request.getPath().startsWith(SKIP_ADMIN_PREF) && ContextManager.isActive()) { + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + if (ContextManager.isActive()) { + ContextManager.activeSpan().errorOccurred().log(t); + } + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/SolrClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/SolrClientInstrumentation.java new file mode 100644 index 000000000000..932307ab9f18 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/shard/SolrClientInstrumentation.java @@ -0,0 +1,97 @@ +/* + * 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.solr.shard; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; +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.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; + +public class SolrClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + + @Override + public ElementMatcher getConstructorMatcher() { + return ElementMatchers.any(); + } + + @Override + public String getConstructorInterceptor() { + return "org.apache.skywalking.apm.plugin.solr.shard.ShardRequestInterceptor"; + } + } + }; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public boolean isOverrideArgs() { + return false; + } + + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named("executeMethod"); + } + + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.solr.shard.ShardConnectorInterceptor"; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public boolean isOverrideArgs() { + return false; + } + + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named("request").and(ElementMatchers.takesArguments(3)); + } + + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.solr.shard.ShardRequestInterceptor"; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName("org.apache.solr.client.solrj.impl.HttpSolrClient"); + } + + @Override + protected String[] witnessClasses() { + return new String[] {"org.apache.solr.servlet.BaseSolrServlet"}; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/ConcurrentUpdateSolrClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/ConcurrentUpdateSolrClientInstrumentation.java new file mode 100644 index 000000000000..e9a47e7b373a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/ConcurrentUpdateSolrClientInstrumentation.java @@ -0,0 +1,80 @@ +/* + * 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.solr.update; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; +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.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; + +public class ConcurrentUpdateSolrClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public String getConstructorInterceptor() { + return "org.apache.skywalking.apm.plugin.solr.update.ConcurrentUpdateSolrClientInterceptor"; + } + + @Override + public ElementMatcher getConstructorMatcher() { + return ElementMatchers.any(); + } + } + }; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public boolean isOverrideArgs() { + return false; + } + + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named("sendUpdateStream"); + } + + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.solr.update.ConcurrentUpdateSolrClientInterceptor"; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName("org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient$Runner"); + } + + @Override + protected String[] witnessClasses() { + return new String[] {"org.apache.solr.servlet.BaseSolrServlet"}; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/ConcurrentUpdateSolrClientInterceptor.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/ConcurrentUpdateSolrClientInterceptor.java new file mode 100644 index 000000000000..03c57ac395ef --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/ConcurrentUpdateSolrClientInterceptor.java @@ -0,0 +1,78 @@ +/* + * 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.solr.update; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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.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.slf4j.MDC; + +import java.lang.reflect.Method; + +import static org.apache.skywalking.apm.plugin.solr.commons.Constants.*; + +public class ConcurrentUpdateSolrClientInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + String coreName = MDC.get(MDC_KEY_CORE).substring(2); + if (ContextManager.isActive()) { + objInst.setSkyWalkingDynamicField(new Object[] {ContextManager.capture(), coreName}); + } + } + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + Object[] params = (Object[]) objInst.getSkyWalkingDynamicField(); + ContextSnapshot snapshot = (ContextSnapshot) params[0]; + + String nodeName = MDC.get(MDC_KEY_NODE_NAME); + final String peer = nodeName.substring(2, nodeName.length() - 5); + + AbstractSpan span = ContextManager.createExitSpan(OPER_SHARD_PREF_SLASH + params[1] + "/update", peer); + span.setComponent(ComponentsDefine.SOLR).setLayer(SpanLayer.HTTP); + + if (snapshot != null) { + ContextManager.continued(snapshot); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + if (ContextManager.isActive()) { + ContextManager.activeSpan().errorOccurred().log(t); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/UpdateShardHandlerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/UpdateShardHandlerInstrumentation.java new file mode 100644 index 000000000000..7be0ac4a5bb2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/UpdateShardHandlerInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.solr.update; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; +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.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; + +public class UpdateShardHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + }; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public boolean isOverrideArgs() { + return false; + } + + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named("getUpdateOnlyHttpClient"); + } + + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.solr.update.UpdateShardHandlerInterceptor"; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName("org.apache.solr.update.UpdateShardHandler"); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/UpdateShardHandlerInterceptor.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/UpdateShardHandlerInterceptor.java new file mode 100644 index 000000000000..8fa18215b15d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/update/UpdateShardHandlerInterceptor.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.solr.update; + +import org.apache.http.impl.client.CloseableHttpClient; +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.plugin.solr.wrappers.CloaseableHttpClientWrapper; + +import java.lang.reflect.Method; + +public class UpdateShardHandlerInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + return new CloaseableHttpClientWrapper((CloseableHttpClient) ret); + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/wrappers/CloaseableHttpClientWrapper.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/wrappers/CloaseableHttpClientWrapper.java new file mode 100644 index 000000000000..e0adfb94bd76 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/wrappers/CloaseableHttpClientWrapper.java @@ -0,0 +1,77 @@ +/* + * 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.solr.wrappers; + +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.params.HttpParams; +import org.apache.http.protocol.HttpContext; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; + +import java.io.IOException; + +public class CloaseableHttpClientWrapper extends CloseableHttpClient { + private static final ILog LOG = LogManager.getLogger(CloaseableHttpClientWrapper.class); + private final CloseableHttpClient client; + + public CloaseableHttpClientWrapper(CloseableHttpClient client) { + this.client = client; + } + + @Override + public HttpParams getParams() { + return client.getParams(); + } + + @Override + public ClientConnectionManager getConnectionManager() { + return client.getConnectionManager(); + } + + @Override + public void close() throws IOException { + client.close(); + } + + @Override + protected CloseableHttpResponse doExecute(HttpHost target, HttpRequest request, HttpContext context) + throws IOException, ClientProtocolException { + try { + ContextCarrier carrier = new ContextCarrier(); + ContextManager.inject(carrier); + CarrierItem items = carrier.items(); + while (items.hasNext()) { + items = items.next(); + request.addHeader(items.getHeadKey(), items.getHeadValue()); + } + } catch (Throwable throwable) { + LOG.error("", throwable); + } + return client.execute(target, request, context); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/wrappers/ModSolrParamsWrapper.java b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/wrappers/ModSolrParamsWrapper.java new file mode 100644 index 000000000000..ebb6e262fc59 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solr/wrappers/ModSolrParamsWrapper.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.solr.wrappers; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.plugin.solr.commons.Constants; +import org.apache.solr.common.params.ModifiableSolrParams; +import org.apache.solr.common.params.SolrParams; + +public class ModSolrParamsWrapper extends ModifiableSolrParams implements EnhancedInstance { + private static final long serialVersionUID = 9015331918376176370L; + private Object dynamic = null; + + public ModSolrParamsWrapper(SolrParams params) { + super(params); + set(Constants.SW_ENHANCE_FLAG, true); + } + + @Override + public Object getSkyWalkingDynamicField() { + return dynamic; + } + + @Override + public void setSkyWalkingDynamicField(Object object) { + this.dynamic = object; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 000000000000..c3601217fdca --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solr-7.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,22 @@ +# 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. + +solr-7.x=org.apache.skywalking.apm.plugin.solr.RequestHandlerBaseInstrumentation +solr-7.x=org.apache.skywalking.apm.plugin.solr.shard.SolrClientInstrumentation +solr-7.x=org.apache.skywalking.apm.plugin.solr.search.QueryStageTracerInstrumentation +solr-7.x=org.apache.skywalking.apm.plugin.solr.search.HttpShardHandlerInstrumentation +solr-7.x=org.apache.skywalking.apm.plugin.solr.update.ConcurrentUpdateSolrClientInstrumentation +solr-7.x=org.apache.skywalking.apm.plugin.solr.update.UpdateShardHandlerInstrumentation \ No newline at end of file From fe5b1014898b076aab472a35f90161c5919b034f Mon Sep 17 00:00:00 2001 From: dmsolr Date: Thu, 4 Jul 2019 15:22:59 +0800 Subject: [PATCH 2/2] update supported-list --- docs/en/setup/service-agent/java-agent/Supported-list.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 1f52dffdddaa..96d0c2c8aeba 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -53,7 +53,8 @@ * [Xmemcached](https://github.com/killme2008/xmemcached) 2.x * [Elasticsearch](https://github.com/elastic/elasticsearch) * [transport-client](https://github.com/elastic/elasticsearch/tree/master/client/transport) 5.2.x-5.6.x - * [Solr](https://github.com/apache/lucene-solr/) + * Solr + * [Solr](https://github.com/apache/lucene-solr/) 7.x * [SolrJ](https://github.com/apache/lucene-solr/tree/master/solr/solrj) 7.x * Service Discovery