提交 a0e81677 编写于 作者: 于玉桔 提交者: wu-sheng

Webflux plugin optimization (#3243)

* webflux
上级 7eb5694a
......@@ -127,4 +127,7 @@ public class ComponentsDefine {
public static final OfficialComponent SPRING_ASYNC = new OfficialComponent(65, "SpringAsync");
public static final OfficialComponent JDK_HTTP = new OfficialComponent(66, "JdkHttp");
public static final OfficialComponent SPRING_WEBFLUX = new OfficialComponent(67, "spring-webflux");
}
......@@ -29,10 +29,6 @@
<name>webflux-5.x-plugin</name>
<url>http://maven.apache.org</url>
<properties>
<javax-servlet-api.version>3.0.1</javax-servlet-api.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
......@@ -40,19 +36,5 @@
<version>5.0.0.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax-servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-springmvc-annotation-commons</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
/*
* 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.webflux.v5;
import io.netty.handler.codec.http.HttpRequest;
import java.lang.reflect.Method;
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.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 org.apache.skywalking.apm.plugin.spring.mvc.commons.EnhanceRequireObjectCache;
import org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor.StackDepth;
import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.CONTROLLER_METHOD_STACK_DEPTH;
import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.FORWARD_REQUEST_FLAG;
import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.WEBFLUX_REQUEST_KEY;
/**
* the abstract method interceptor
*/
public abstract class AbstractMethodInterceptor implements InstanceMethodsAroundInterceptor {
public abstract String getRequestURL(Method method);
public abstract String getAcceptedMethodTypes(Method method);
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
Boolean forwardRequestFlag = (Boolean)ContextManager.getRuntimeContext().get(FORWARD_REQUEST_FLAG);
/**
* Spring MVC plugin do nothing if current request is forward request.
* Ref: https://github.com/apache/skywalking/pull/1325
*/
if (forwardRequestFlag != null && forwardRequestFlag) {
return;
}
EnhanceRequireObjectCache pathMappingCache = (EnhanceRequireObjectCache)objInst.getSkyWalkingDynamicField();
String requestURL = pathMappingCache.findPathMapping(method);
if (requestURL == null) {
requestURL = getRequestURL(method);
pathMappingCache.addPathMapping(method, requestURL);
requestURL = getAcceptedMethodTypes(method) + pathMappingCache.findPathMapping(method);
}
HttpRequest request = (HttpRequest)ContextManager.getRuntimeContext().get(WEBFLUX_REQUEST_KEY);
if (request != null) {
StackDepth stackDepth = (StackDepth)ContextManager.getRuntimeContext().get(CONTROLLER_METHOD_STACK_DEPTH);
if (stackDepth == null) {
ContextCarrier contextCarrier = new ContextCarrier();
CarrierItem next = contextCarrier.items();
while (next.hasNext()) {
next = next.next();
next.setHeadValue(request.headers().get(next.getHeadKey()));
}
AbstractSpan span = ContextManager.createEntrySpan(requestURL, contextCarrier);
Tags.URL.set(span, request.uri());
Tags.HTTP.METHOD.set(span, request.method().name());
span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION);
SpanLayer.asHttp(span);
stackDepth = new StackDepth();
} else {
AbstractSpan span = ContextManager.createLocalSpan(objInst.getClass().getName() + "/" + method.getName());
span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION);
}
stackDepth.increment();
}
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
Boolean forwardRequestFlag = (Boolean)ContextManager.getRuntimeContext().get(FORWARD_REQUEST_FLAG);
/**
* Spring MVC plugin do nothing if current request is forward request.
* Ref: https://github.com/apache/skywalking/pull/1325
*/
if (forwardRequestFlag != null && forwardRequestFlag) {
return ret;
}
HttpRequest request = (HttpRequest)ContextManager.getRuntimeContext().get(WEBFLUX_REQUEST_KEY);
if (request != null) {
ContextManager.stopSpan();
}
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
}
}
......@@ -6,46 +6,68 @@
* (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
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.plugin.spring.webflux.v5;
import io.netty.handler.codec.http.HttpRequest;
import java.lang.reflect.Method;
/**
* @author zhaoyuguang
*/
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import java.lang.reflect.Method;
public class BodyInserterResponseMethodInterceptor implements InstanceMethodsAroundInterceptor {
import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.WEBFLUX_REQUEST_KEY;
/**
* The error reason
* see more details org.springframework.boot.web.reactive.error.DefaultErrorAttributes#storeErrorInformation
*/
private final static String ERROR_ATTRIBUTE = "org.springframework.boot.web.reactive.error.DefaultErrorAttributes.ERROR";
public class OnOutboundErrorInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
Throwable exception = (Throwable)allArguments[0];
HttpRequest request = (HttpRequest)ContextManager.getRuntimeContext().get(WEBFLUX_REQUEST_KEY);
if (request != null) {
ContextManager.activeSpan().errorOccurred().log(exception);
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
EnhancedInstance instance = (EnhancedInstance) allArguments[0];
AbstractSpan span = (AbstractSpan) instance.getSkyWalkingDynamicField();
if (span == null) {
return;
}
ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
HttpStatus status = exchange.getResponse().getStatusCode();
if (status != null && status.value() >= 400) {
span.errorOccurred();
if (exchange.getAttribute(ERROR_ATTRIBUTE) != null) {
span.log((Throwable) exchange.getAttribute(ERROR_ATTRIBUTE));
}
Tags.STATUS_CODE.set(span, Integer.toString(status.value()));
}
ContextManager.stopSpan(span);
((EnhancedInstance) allArguments[0]).setSkyWalkingDynamicField(null);
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
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) {
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
}
}
/*
* 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.webflux.v5;
import io.netty.handler.codec.http.HttpRequest;
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;
import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.WEBFLUX_REQUEST_KEY;
public class ConstructorWithHttpRequestInterceptor implements InstanceConstructorInterceptor {
@Override
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
HttpRequest httpRequest = (HttpRequest)allArguments[4];
ContextManager.getRuntimeContext().put(WEBFLUX_REQUEST_KEY, httpRequest);
}
}
/*
* 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.webflux.v5;
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.plugin.spring.mvc.commons.EnhanceRequireObjectCache;
import org.apache.skywalking.apm.plugin.spring.mvc.commons.PathMappingCache;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* The <code>ControllerConstructorInterceptor</code> intercepts the Controller's constructor, in order to acquire the
* mapping annotation, if exist.
*
* But, you can see we only use the first mapping value, <B>Why?</B>
*
* Right now, we intercept the controller by annotation as you known, so we CAN'T know which uri patten is actually
* matched. Even we know, that costs a lot.
*
* If we want to resolve that, we must intercept the Spring MVC core codes, that is not a good choice for now.
*
* Comment by @wu-sheng
*/
public class ControllerConstructorInterceptor implements InstanceConstructorInterceptor {
@Override
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
String basePath = "";
RequestMapping basePathRequestMapping = objInst.getClass().getAnnotation(RequestMapping.class);
if (basePathRequestMapping != null) {
if (basePathRequestMapping.value().length > 0) {
basePath = basePathRequestMapping.value()[0];
} else if (basePathRequestMapping.path().length > 0) {
basePath = basePathRequestMapping.path()[0];
}
}
EnhanceRequireObjectCache enhanceRequireObjectCache = new EnhanceRequireObjectCache();
enhanceRequireObjectCache.setPathMappingCache(new PathMappingCache(basePath));
objInst.setSkyWalkingDynamicField(enhanceRequireObjectCache);
}
}
......@@ -6,28 +6,27 @@
* (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
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.plugin.spring.webflux.v5;
import io.netty.handler.codec.http.HttpRequest;
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;
import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.WEBFLUX_REQUEST_KEY;
public class ConstructorInterceptor implements InstanceConstructorInterceptor {
/**
*
* @author zhaoyuguang
*/
public class DefaultServerWebExchangeConstructorInterceptor implements InstanceConstructorInterceptor {
@Override
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
HttpRequest httpRequest = (HttpRequest)allArguments[3];
ContextManager.getRuntimeContext().put(WEBFLUX_REQUEST_KEY, httpRequest);
}
}
\ No newline at end of file
}
......@@ -6,19 +6,22 @@
* (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
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.plugin.spring.webflux.v5;
import io.netty.handler.codec.http.HttpRequest;
import java.lang.reflect.Method;
/**
* @author zhaoyuguang
*/
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;
......@@ -29,49 +32,46 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedI
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.springframework.http.HttpHeaders;
import org.springframework.web.server.ServerWebExchange;
import java.lang.reflect.Method;
import java.util.List;
public class DispatcherHandlerHandleMethodInterceptor implements InstanceMethodsAroundInterceptor {
import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.WEBFLUX_REQUEST_KEY;
private static final String WIP_OPERATION_NAME = "WEBFLUX.handle";
public class OnInboundNextInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
HttpRequest request = (HttpRequest)ContextManager.getRuntimeContext().get(WEBFLUX_REQUEST_KEY);
if (request != null) {
ContextCarrier contextCarrier = new ContextCarrier();
CarrierItem next = contextCarrier.items();
while (next.hasNext()) {
next = next.next();
next.setHeadValue(request.headers().get(next.getHeadKey()));
}
if (allArguments[1] instanceof HttpRequest) {
AbstractSpan span = ContextManager.createEntrySpan(toPath(request.uri()), contextCarrier);
Tags.URL.set(span, request.uri());
Tags.HTTP.METHOD.set(span, request.method().name());
span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION);
SpanLayer.asHttp(span);
MethodInterceptResult result) throws Throwable {
ContextCarrier contextCarrier = new ContextCarrier();
CarrierItem next = contextCarrier.items();
ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
EnhancedInstance instance = (EnhancedInstance) allArguments[0];
HttpHeaders headers = exchange.getRequest().getHeaders();
while (next.hasNext()) {
next = next.next();
List<String> header = headers.get(next.getHeadKey());
if (header != null && header.size() > 0) {
next.setHeadValue(header.get(0));
}
}
AbstractSpan span = ContextManager.createEntrySpan(WIP_OPERATION_NAME, contextCarrier);
span.setComponent(ComponentsDefine.SPRING_WEBFLUX);
SpanLayer.asHttp(span);
Tags.URL.set(span, exchange.getRequest().getURI().toString());
instance.setSkyWalkingDynamicField(span);
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
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;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
}
}
......@@ -6,46 +6,51 @@
* (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
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.plugin.spring.webflux.v5;
import io.netty.handler.codec.http.HttpResponseStatus;
/**
* @author zhaoyuguang
*/
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import java.lang.reflect.Method;
public class StatusInterceptor implements InstanceMethodsAroundInterceptor {
public class DispatcherHandlerHandleResultMethodInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
HttpResponseStatus status = (HttpResponseStatus)allArguments[0];
if (status.code() >= 400) {
ContextManager.activeSpan().errorOccurred();
Tags.STATUS_CODE.set(ContextManager.activeSpan(), String.valueOf(status.code()));
}
MethodInterceptResult result) throws Throwable {
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
Object ret) throws Throwable {
EnhancedInstance instance = (EnhancedInstance) allArguments[0];
AbstractSpan span = (AbstractSpan) instance.getSkyWalkingDynamicField();
if (span != null) {
ContextManager.stopSpan(span);
instance.setSkyWalkingDynamicField(null);
}
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
Class<?>[] argumentsTypes, Throwable t) {
}
}
......@@ -6,45 +6,76 @@
* (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
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.plugin.spring.webflux.v5;
import io.netty.handler.codec.http.HttpRequest;
import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
/**
* @author zhaoyuguang
*/
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.web.method.HandlerMethod;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class DispatcherHandlerInvokeHandlerMethodInterceptor implements InstanceMethodsAroundInterceptor {
private static final String ROUTER_SEARCH = "$$Lambda";
private static final String ROUTER_FIELD = "arg$1";
private static final String DOT = ".";
import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.WEBFLUX_REQUEST_KEY;
public class OnOutboundCompleteInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
MethodInterceptResult result) throws Throwable {
EnhancedInstance instance = (EnhancedInstance) allArguments[0];
AbstractSpan span = (AbstractSpan) instance.getSkyWalkingDynamicField();
if (span == null) {
return;
}
String handleClassName = allArguments[1].getClass().getSimpleName();
int index = handleClassName.indexOf(ROUTER_SEARCH);
if (index != -1) {
String operationName = handleClassName.substring(0, index);
try {
Field field = allArguments[1].getClass().getDeclaredField(ROUTER_FIELD);
field.setAccessible(true);
operationName = operationName + DOT + field.get(allArguments[1]).getClass().getName();
} catch (NoSuchFieldException ignore) {
}
span.setOperationName(operationName);
} else if (allArguments[1] instanceof HandlerMethod) {
HandlerMethod handler = (HandlerMethod) allArguments[1];
span.setOperationName(getHandlerMethodOperationName(handler));
}
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
HttpRequest request = (HttpRequest)ContextManager.getRuntimeContext().get(WEBFLUX_REQUEST_KEY);
if (request != null) {
ContextManager.stopSpan();
ContextManager.getRuntimeContext().remove(WEBFLUX_REQUEST_KEY);
}
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);
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
}
private String getHandlerMethodOperationName(HandlerMethod handler) {
Method method = handler.getMethod();
return method.getDeclaringClass().getName() + DOT + method.getName();
}
}
/*
* 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.webflux.v5;
import java.lang.reflect.Method;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* The <code>RequestMappingMethodInterceptor</code> only use the first mapping value. it will interceptor with
* <code>@RequestMapping</code>
*
* @author clevertension
*/
public class RequestMappingMethodInterceptor extends AbstractMethodInterceptor {
@Override
public String getRequestURL(Method method) {
String requestURL = "";
RequestMapping methodRequestMapping = method.getAnnotation(RequestMapping.class);
if (methodRequestMapping.value().length > 0) {
requestURL = methodRequestMapping.value()[0];
} else if (methodRequestMapping.path().length > 0) {
requestURL = methodRequestMapping.path()[0];
}
return requestURL;
}
@Override
public String getAcceptedMethodTypes(Method method) {
RequestMapping methodRequestMapping = method.getAnnotation(RequestMapping.class);
StringBuilder methodTypes = new StringBuilder();
if (methodRequestMapping.method().length > 0) {
methodTypes.append("{");
for (int i = 0; i < methodRequestMapping.method().length; i++) {
methodTypes.append(methodRequestMapping.method()[i].toString());
if (methodRequestMapping.method().length > (i + 1)) {
methodTypes.append(",");
}
}
methodTypes.append("}");
}
return methodTypes.toString();
}
}
/*
* 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.webflux.v5;
import java.lang.reflect.Method;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
/**
* The <code>RestMappingMethodInterceptor</code> only use the first mapping value. it will inteceptor with
* <code>@GetMapping</code>, <code>@PostMapping</code>, <code>@PutMapping</code>
* <code>@DeleteMapping</code>, <code>@PatchMapping</code>
*
* @author clevertension
*/
public class RestMappingMethodInterceptor extends AbstractMethodInterceptor {
@Override
public String getRequestURL(Method method) {
String requestURL = "";
GetMapping getMapping = method.getAnnotation(GetMapping.class);
PostMapping postMapping = method.getAnnotation(PostMapping.class);
PutMapping putMapping = method.getAnnotation(PutMapping.class);
DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
if (getMapping != null) {
if (getMapping.value().length > 0) {
requestURL = getMapping.value()[0];
} else if (getMapping.path().length > 0) {
requestURL = getMapping.path()[0];
}
} else if (postMapping != null) {
if (postMapping.value().length > 0) {
requestURL = postMapping.value()[0];
} else if (postMapping.path().length > 0) {
requestURL = postMapping.path()[0];
}
} else if (putMapping != null) {
if (putMapping.value().length > 0) {
requestURL = putMapping.value()[0];
} else if (putMapping.path().length > 0) {
requestURL = putMapping.path()[0];
}
} else if (deleteMapping != null) {
if (deleteMapping.value().length > 0) {
requestURL = deleteMapping.value()[0];
} else if (deleteMapping.path().length > 0) {
requestURL = deleteMapping.path()[0];
}
} else if (patchMapping != null) {
if (patchMapping.value().length > 0) {
requestURL = patchMapping.value()[0];
} else if (patchMapping.path().length > 0) {
requestURL = patchMapping.path()[0];
}
}
return requestURL;
}
@Override
public String getAcceptedMethodTypes(Method method) {
return "";
}
}
......@@ -6,13 +6,14 @@
* (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
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.plugin.spring.webflux.v5.define;
......@@ -25,72 +26,35 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInst
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;
public class HttpServerOperations21xInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[] {
new ConstructorInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getConstructorMatcher() {
return takesArgumentWithType(3, "io.netty.handler.codec.http.HttpRequest");
}
import static org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch.byMultiClassMatch;
@Override public String getConstructorInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.ConstructorInterceptor";
}
}
};
}
@Override public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("status").and(takesArgumentWithType(0, "io.netty.handler.codec.http.HttpResponseStatus"));
}
@Override public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.StatusInterceptor";
}
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("onInboundNext");
}
/**
* @author zhaoyuguang
*/
@Override public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.OnInboundNextInterceptor";
}
public class BodyInserterResponseInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("onOutboundComplete");
}
@Override
protected ClassMatch enhanceClass() {
return byMultiClassMatch("org.springframework.web.reactive.function.server.DefaultServerResponseBuilder$BodyInserterResponse",
"org.springframework.web.reactive.function.server.DefaultServerResponseBuilder$BodyInserterServerResponse");
}
@Override public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.OnOutboundCompleteInterceptor";
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override public boolean isOverrideArgs() {
return false;
}
},
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("onOutboundError");
return named("writeToInternal");
}
@Override public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.OnOutboundErrorInterceptor";
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.BodyInserterResponseMethodInterceptor";
}
@Override public boolean isOverrideArgs() {
......@@ -99,8 +63,4 @@ public class HttpServerOperations21xInstrumentation extends ClassInstanceMethods
}
};
}
@Override protected ClassMatch enhanceClass() {
return byName("reactor.netty.http.server.HttpServerOperations");
}
}
/*
* 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.webflux.v5.define;
public class ControllerInstrumentation extends AbstractControllerInstrumentation {
public static final String ENHANCE_ANNOTATION = "org.springframework.stereotype.Controller";
@Override protected String[] getEnhanceAnnotations() {
return new String[] {ENHANCE_ANNOTATION};
}
}
......@@ -6,25 +6,57 @@
* (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
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.plugin.spring.webflux.v5.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.any;
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
public abstract class AbstractSpringWebflux5Instrumentation extends ClassInstanceMethodsEnhancePluginDefine {
public static final String WITHNESS_CLASSES = "org.springframework.web.reactive.BindingContext";
/**
* @author zhaoyuguang
*/
public class DefaultServerWebExchangeInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[]{
new ConstructorInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getConstructorMatcher() {
return any();
}
@Override
public String getConstructorInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.DefaultServerWebExchangeConstructorInterceptor";
}
}
};
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[0];
}
@Override
protected final String[] witnessClasses() {
return new String[] {WITHNESS_CLASSES};
protected ClassMatch enhanceClass() {
return byName("org.springframework.web.server.adapter.DefaultServerWebExchange");
}
}
......@@ -6,13 +6,14 @@
* (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
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.plugin.spring.webflux.v5.define;
......@@ -20,80 +21,65 @@ package org.apache.skywalking.apm.plugin.spring.webflux.v5.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.DeclaredInstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch;
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.any;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
/**
* {@link ControllerInstrumentation} enhance all constructor and method annotated with
* <code>org.springframework.web.bind.annotation.RequestMapping</code> that class has
* <code>org.springframework.stereotype.Controller</code> annotation.
*
* <code>ControllerConstructorInterceptor</code> set the controller base path to
* dynamic field before execute constructor.
*
* <code>org.apache.skywalking.apm.plugin.spring.mvc.v4.RequestMappingMethodInterceptor</code> get the request path
* from dynamic field first, if not found, <code>RequestMappingMethodInterceptor</code> generate request path that
* combine the path value of current annotation on current method and the base path and set the new path to the dynamic
* filed
*
* @author zhangxin
* @author zhaoyuguang
*/
public abstract class AbstractControllerInstrumentation extends AbstractSpringWebflux5Instrumentation {
public class DispatcherHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[] {
new ConstructorInterceptPoint() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getConstructorMatcher() {
return any();
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("handle");
}
@Override
public String getConstructorInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.ControllerConstructorInterceptor";
public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.DispatcherHandlerHandleMethodInterceptor";
}
}
};
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new DeclaredInstanceMethodsInterceptPoint() {
@Override
public boolean isOverrideArgs() {
return false;
}
}, new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return isAnnotatedWith(named("org.springframework.web.bind.annotation.RequestMapping"));
return named("invokeHandler");
}
@Override
public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.RequestMappingMethodInterceptor";
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.DispatcherHandlerInvokeHandlerMethodInterceptor";
}
@Override
public boolean isOverrideArgs() {
return false;
}
},
new DeclaredInstanceMethodsInterceptPoint() {
}, new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return isAnnotatedWith(named("org.springframework.web.bind.annotation.GetMapping"))
.or(isAnnotatedWith(named("org.springframework.web.bind.annotation.PostMapping")))
.or(isAnnotatedWith(named("org.springframework.web.bind.annotation.PutMapping")))
.or(isAnnotatedWith(named("org.springframework.web.bind.annotation.DeleteMapping")))
.or(isAnnotatedWith(named("org.springframework.web.bind.annotation.PatchMapping")));
return named("handleResult");
}
@Override
public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.RestMappingMethodInterceptor";
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.DispatcherHandlerHandleResultMethodInterceptor";
}
@Override
......@@ -106,9 +92,6 @@ public abstract class AbstractControllerInstrumentation extends AbstractSpringWe
@Override
protected ClassMatch enhanceClass() {
return ClassAnnotationMatch.byClassAnnotationMatch(getEnhanceAnnotations());
return byName("org.springframework.web.reactive.DispatcherHandler");
}
protected abstract String[] getEnhanceAnnotations();
}
/*
* 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.webflux.v5.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;
public class HttpServerOperations20xInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[] {
new ConstructorInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getConstructorMatcher() {
return takesArgumentWithType(4, "io.netty.handler.codec.http.HttpRequest");
}
@Override public String getConstructorInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.ConstructorWithHttpRequestInterceptor";
}
}
};
}
@Override public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("status").and(takesArgumentWithType(0, "io.netty.handler.codec.http.HttpResponseStatus"));
}
@Override public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.StatusInterceptor";
}
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("onInboundNext");
}
@Override public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.OnInboundNextInterceptor";
}
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("onOutboundComplete");
}
@Override public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.OnOutboundCompleteInterceptor";
}
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("onOutboundError");
}
@Override public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.spring.webflux.v5.OnOutboundErrorInterceptor";
}
@Override public boolean isOverrideArgs() {
return false;
}
}
};
}
@Override protected ClassMatch enhanceClass() {
return byName("reactor.ipc.netty.http.server.HttpServerOperations");
}
}
/*
* 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.webflux.v5.define;
public class RestControllerInstrumentation extends AbstractControllerInstrumentation {
public static final String ENHANCE_ANNOTATION = "org.springframework.web.bind.annotation.RestController";
@Override protected String[] getEnhanceAnnotations() {
return new String[] {ENHANCE_ANNOTATION};
}
}
......@@ -14,7 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.HttpServerOperations20xInstrumentation
spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.HttpServerOperations21xInstrumentation
spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.ControllerInstrumentation
spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.RestControllerInstrumentation
spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.DispatcherHandlerInstrumentation
spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.DefaultServerWebExchangeInstrumentation
spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.BodyInserterResponseInstrumentation
\ No newline at end of file
......@@ -210,6 +210,9 @@ SpringAsync:
JdkHttp:
id: 66
languages: Java
spring-webflux:
id: 67
languages: Java
# .NET/.NET Core components
# [3000, 4000) for C#/.NET only
......
......@@ -228,6 +228,9 @@ SpringAsync:
JdkHttp:
id: 66
languages: Java
spring-webflux:
id: 67
languages: Java
# .NET/.NET Core components
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册