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 8d6f16851978418cf994caaec52dab6f885ad8c9..c3a10f28f7f728ecb36468b2068b72faffd9946a 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 @@ -118,6 +118,8 @@ public class ComponentsDefine { public static final OfficialComponent SHARDING_SPHERE = new OfficialComponent(60, "ShardingSphere"); + public static final OfficialComponent SPRING_CLOUD_GATEWAY = new OfficialComponent(61, "spring-cloud-gateway"); + private static ComponentsDefine INSTANCE = new ComponentsDefine(); private String[] components; @@ -173,6 +175,7 @@ public class ComponentsDefine { addComponent(LETTUCE); addComponent(ZOOKEEPER); addComponent(VERTX); + addComponent(SPRING_CLOUD_GATEWAY); } private void addComponent(OfficialComponent component) { diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..8489605c8d904a89168b9274e4607f087b71ef86 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/pom.xml @@ -0,0 +1,48 @@ + + + + +4.0.0 + + + org.apache.skywalking + optional-spring-cloud + 6.2.0-SNAPSHOT + + +apm-spring-cloud-gateway-2.x-plugin +jar + +gateway-2.x-plugin +http://maven.apache.org + + + 2.1.1.RELEASE + + + + + org.springframework.cloud + spring-cloud-starter-gateway + ${spring-cloud-starter-gateway.version} + provided + + + + diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/DefaultHttpHeadersInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/DefaultHttpHeadersInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..edc3edadcbcde3cbbbd0f62c00462cbd8df99d13 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/DefaultHttpHeadersInterceptor.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2; + +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.InstanceConstructorInterceptor; + +public class DefaultHttpHeadersInterceptor implements InstanceConstructorInterceptor { + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + if (ContextManager.isActive()) { + objInst.setSkyWalkingDynamicField(ContextManager.capture()); + } + } +} \ No newline at end of file diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/FilteringWebHandlerInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/FilteringWebHandlerInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..77fddde81f974d654dc9fc9d3d14f308871c555d --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/FilteringWebHandlerInterceptor.java @@ -0,0 +1,67 @@ +/* + * 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.spring.cloud.gateway.v2; + +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.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.springframework.cloud.gateway.route.Route; +import org.springframework.web.server.ServerWebExchange; + +import java.lang.reflect.Method; + +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR; + + +/** + * @author zhaoyuguang + */ +public class FilteringWebHandlerInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + ServerWebExchange exchange = (ServerWebExchange) allArguments[0]; + Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR); + + AbstractSpan span = ContextManager.activeSpan(); + if (span != null) { + span.tag("route", route.getId()); + } + } + + @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) { + AbstractSpan span = ContextManager.activeSpan(); + if (span != null) { + span.errorOccurred(); + span.log(t); + } + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/HttpClientOperationsHeadersInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/HttpClientOperationsHeadersInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..79ada67d4b8438c323716b56cb7e769c9f652df6 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/HttpClientOperationsHeadersInterceptor.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2; + +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 java.lang.reflect.Method; + + +/** + * @author zhaoyuguang + */ +public class HttpClientOperationsHeadersInterceptor implements InstanceMethodsAroundInterceptor { + + private static final ILog logger = LogManager.getLogger(HttpClientOperationsHeadersInterceptor.class); + + @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 { + ((EnhancedInstance) ret).setSkyWalkingDynamicField(((EnhancedInstance) allArguments[0]).getSkyWalkingDynamicField()); + return ret; + } + + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/HttpClientOperationsSendInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/HttpClientOperationsSendInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..e7adffe45d616e95e8739df775fc663f95ec50de --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/HttpClientOperationsSendInterceptor.java @@ -0,0 +1,96 @@ +/* + * 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.spring.cloud.gateway.v2; + +import io.netty.handler.codec.http.HttpHeaders; +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.ContextSnapshot; +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.context.trace.SpanLayer; +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 reactor.netty.channel.ChannelOperations; +import reactor.netty.http.client.HttpClientRequest; + +import java.lang.reflect.Method; +import java.net.InetSocketAddress; + + +/** + * @author zhaoyuguang + */ +public class HttpClientOperationsSendInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + HttpClientRequest request = (HttpClientRequest) objInst; + EnhancedInstance instance = (EnhancedInstance) request; + + HttpHeaders header = request.requestHeaders(); + ChannelOperations channelOpt = (ChannelOperations) objInst; + InetSocketAddress remote = (InetSocketAddress) (channelOpt.channel().remoteAddress()); + String peer = remote.getHostName() + ":" + remote.getPort(); + + AbstractSpan span = ContextManager.createExitSpan(toPath(request.uri()), peer); + ContextSnapshot snapshot = (ContextSnapshot) instance.getSkyWalkingDynamicField(); + + ContextManager.continued(snapshot); + ContextCarrier contextCarrier = new ContextCarrier(); + ContextManager.inject(contextCarrier); + + span.setComponent(ComponentsDefine.SPRING_CLOUD_GATEWAY); + Tags.URL.set(span, peer + request.uri()); + Tags.HTTP.METHOD.set(span, request.method().name()); + SpanLayer.asHttp(span); + + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + header.set(next.getHeadKey(), next.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) { + ContextManager.activeSpan().errorOccurred().log(t); + } + + private static String toPath(String uri) { + int index = uri.indexOf("?"); + if (index > -1) { + return uri.substring(0, index); + } else { + return uri; + } + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/HttpClientOperationsStatusInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/HttpClientOperationsStatusInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..65319f8aa9db726a2892965ee109c1ebe1bd73fa --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/HttpClientOperationsStatusInterceptor.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.spring.cloud.gateway.v2; + +import io.netty.handler.codec.http.HttpResponseStatus; +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.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; + + +/** + * @author zhaoyuguang + */ +public class HttpClientOperationsStatusInterceptor 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 { + HttpResponseStatus response = (HttpResponseStatus) ret; + if (response.code() > 400) { + ContextManager.activeSpan().errorOccurred(); + Tags.STATUS_CODE.set(ContextManager.activeSpan(), String.valueOf(response.code())); + } + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/define/DefaultHttpHeadersInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/define/DefaultHttpHeadersInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..7be695e9ca1fd24202416c3abe58f89627503c94 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/define/DefaultHttpHeadersInstrumentation.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +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 static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * @author zhaoyuguang + */ + +public class DefaultHttpHeadersInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override public ElementMatcher getConstructorMatcher() { + return takesArgumentWithType(0, "io.netty.handler.codec.DefaultHeaders"); + } + + @Override public String getConstructorInterceptor() { + return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.DefaultHttpHeadersInterceptor"; + } + } + }; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + + @Override + public ClassMatch enhanceClass() { + return byName("io.netty.handler.codec.http.DefaultHttpHeaders"); + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/define/FilteringWebHandlerInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/define/FilteringWebHandlerInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..b3a81dad9de99f8540bd5f764d978a85ca484a89 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/define/FilteringWebHandlerInstrumentation.java @@ -0,0 +1,72 @@ +/* + * 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.spring.cloud.gateway.v2.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +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 static net.bytebuddy.matcher.ElementMatchers.named; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * @author zhaoyuguang + */ + +public class FilteringWebHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("handle").and(takesArgumentWithType(0, "org.springframework.web.server.ServerWebExchange")); + } + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.FilteringWebHandlerInterceptor"; + } + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + public ClassMatch enhanceClass() { + return byName("org.springframework.cloud.gateway.handler.FilteringWebHandler"); + } + + @Override + protected final String[] witnessClasses() { + return new String[]{"org.springframework.cloud.gateway.handler.FilteringWebHandler", "reactor.netty.http.client.HttpClientOperations"}; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/define/HttpClientOperationsInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/define/HttpClientOperationsInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..51e0d3e0a0f9d64a9205dabc4a7eca8e8444570c --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v2/define/HttpClientOperationsInstrumentation.java @@ -0,0 +1,99 @@ +/* + * 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.spring.cloud.gateway.v2.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +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 static net.bytebuddy.matcher.ElementMatchers.named; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * @author zhaoyuguang + */ + +public class HttpClientOperationsInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("headers").and(takesArgumentWithType(0, "io.netty.handler.codec.http.HttpHeaders")); + } + + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.HttpClientOperationsHeadersInterceptor"; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + },new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("send").and(takesArgumentWithType(0, "org.reactivestreams.Publisher")); + } + + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.HttpClientOperationsSendInterceptor"; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("status"); + } + + @Override + public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.HttpClientOperationsStatusInterceptor"; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + }; + } + + @Override + public ClassMatch enhanceClass() { + return byName("reactor.netty.http.client.HttpClientOperations"); + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000000000000000000000000000000000..9a76bc82cef5afa0aac8e43d70239b5cd4450cbc --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +spring-cloud-gateway-2.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.define.DefaultHttpHeadersInstrumentation +spring-cloud-gateway-2.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.define.FilteringWebHandlerInstrumentation +spring-cloud-gateway-2.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v2.define.HttpClientOperationsInstrumentation \ No newline at end of file diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..975b1b9f5e5ad52fe8f1b60020e83371d4b94ee0 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml @@ -0,0 +1,44 @@ + + + + + 4.0.0 + + + org.apache.skywalking + optional-spring-plugins + 6.2.0-SNAPSHOT + + + optional-spring-cloud + + gateway-2.x-plugin + + pom + + optional-spring-cloud + http://maven.apache.org + + + UTF-8 + /../.. + + + diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml index 49dc230ebb13bd2d239421d2cf0e93ef5e8cafb5..c3c80ccc621efc3af19cee8a71a46c2677a061d2 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml @@ -30,6 +30,7 @@ spring-annotation-plugin + optional-spring-cloud diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md index d79e9bb5ca2b8c8454a7037766ee39cc1b4c3085..a14cd44b786b6f05522eea1a10146e3a25367536 100644 --- a/docs/en/setup/service-agent/java-agent/README.md +++ b/docs/en/setup/service-agent/java-agent/README.md @@ -88,13 +88,14 @@ Java agent plugins are all pluggable. Optional plugins could be provided in `opt For using these plugins, you need to put the target plugin jar file into `/plugins`. Now, we have the following known optional plugins. -* [Trace Spring annotation beans](agent-optional-plugins/Spring-annotation-plugin.md) -* [Trace Oracle and Resin](agent-optional-plugins/Oracle-Resin-plugins.md) +* [Plugin of tracing Spring annotation beans](agent-optional-plugins/Spring-annotation-plugin.md) +* [Plugin of tracing Oracle and Resin](agent-optional-plugins/Oracle-Resin-plugins.md) * [Filter traces through specified endpoint name patterns](agent-optional-plugins/trace-ignore-plugin.md) -* Gson serialization lib in optional plugin folder -* Lettuce 5.x(JRE1.8+) in optional plugin folder -* Zookeeper 3.4.x in optional plugin folder. The reason of being optional plugin is, many business irrelevant traces are generated, which cause extra payload to agents and backends. At the same time, those traces may be just heartbeat(s). +* Plugin of Gson serialization lib in optional plugin folder. +* Plugin of Lettuce 5.x(JRE 8+) in optional plugin folder. Agent is compatible in JDK 1.6+, this plugin could be used in JRE 8+, by matching the lib requirement. +* Plugin of Zookeeper 3.4.x in optional plugin folder. The reason of being optional plugin is, many business irrelevant traces are generated, which cause extra payload to agents and backends. At the same time, those traces may be just heartbeat(s). * [Customize enhance](Customize-enhance-trace.md) Trace methods based on description files, rather than write plugin or change source codes. +* Plugin of Spring Cloud Gateway 2.1.x in optional plugin folder. Please only active this plugin when you install agent in Spring Gateway. ## Advanced Features * Set the settings through system properties for config file override. Read [setting override](Setting-override.md). 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 2376cb79cabe8cb91e996115ec714f96671def27..6b0f8064baa251048d1dd2ab3ebe3500a2174955 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -19,6 +19,8 @@ * [Spring RestTemplete](https://github.com/spring-projects/spring-framework) 4.x * [Jetty Client](http://www.eclipse.org/jetty/) 9 * [Apache httpcomponent AsyncClient](https://hc.apache.org/httpcomponents-asyncclient-dev/) 4.x +* HTTP Gateway + * [Spring Cloud Gateway](https://spring.io/projects/spring-cloud-gateway) 2.1.x.RELEASE (Optional²) * JDBC * Mysql Driver 5.x, 6.x * Oracle Driver (Optional¹) diff --git a/oap-server/server-core/src/test/resources/component-libraries.yml b/oap-server/server-core/src/test/resources/component-libraries.yml index 0d793a0b81f6b5fc02022bbaec04cf454f69b9e6..3b5f49da53b25dbc674fca452fcf4443a79f6ce9 100644 --- a/oap-server/server-core/src/test/resources/component-libraries.yml +++ b/oap-server/server-core/src/test/resources/component-libraries.yml @@ -192,6 +192,9 @@ Vertx: ShardingSphere: id: 60 languages: Java +spring-cloud-gateway: + id: 61 + languages: Java # .NET/.NET Core components # [3000, 4000) for C#/.NET only diff --git a/oap-server/server-starter/src/main/resources/component-libraries.yml b/oap-server/server-starter/src/main/resources/component-libraries.yml index 747bb2592eefb48f05023ac2590ef760afca3f26..7dc8242b64f51787fc4c65e89b9d07a5845427ea 100644 --- a/oap-server/server-starter/src/main/resources/component-libraries.yml +++ b/oap-server/server-starter/src/main/resources/component-libraries.yml @@ -210,6 +210,9 @@ Vertx: ShardingSphere: id: 60 languages: Java +spring-cloud-gateway: + id: 61 + languages: Java # .NET/.NET Core components # [3000, 4000) for C#/.NET only