Skip to content

Commit

Permalink
Enhance optional plugin docs for Spring Gateway.
Browse files Browse the repository at this point in the history
  • Loading branch information
wu-sheng committed Dec 16, 2024
1 parent be3d092 commit 394ddc2
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 44 deletions.
10 changes: 8 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,20 @@ Release Notes.
* Add agent self-observability.
* Fix intermittent ClassCircularityError by preloading ThreadLocalRandom since ByteBuddy 1.12.11
* Add witness class/method for resteasy-server plugin(v3/v4/v6)
* Add async-profiler feature for performance analysis
* Add async-profiler feature for performance analysis
* Support db.instance tag,db.collection tag and AggregateOperation span for mongodb plugin(3.x/4.x)
* Improve CustomizeConfiguration by avoiding repeatedly resolve file config
* Add empty judgment for constructorInterceptPoint
* Bump up gRPC to 1.68.1
* Bump up netty to 4.1.115.Final
* Fix the `CreateAopProxyInterceptor` in the Spring core-patch to prevent it from changing the implementation of the Spring AOP proxy
* Fix the `CreateAopProxyInterceptor` in the Spring core-patch to prevent it from changing the implementation of the
Spring AOP proxy
* Support Tracing for GlobalFilter and GatewayFilter in Spring Gateway
* [doc] Enhance Custom Trace Ignoring Plugin document about conflicts with the plugin of **sampler plugin with CPU
policy**
* [doc] Add Spring Gateway Plugin document
* [doc] Add 4 menu items guiding users to find important notices for Spring Annotation Plugin, Custom Trace Ignoring
Plugin, Kotlin Coroutine Plugin, and Spring Gateway Plugin

All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@

package org.apache.skywalking.apm.plugin.spring.patch;

import java.lang.reflect.Method;
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.aop.SpringProxy;
import org.springframework.aop.framework.AdvisedSupport;

import java.lang.reflect.Method;

/**
* <code>CreateAopProxyInterceptor</code> check that the bean has been implement {@link EnhancedInstance}.
* if yes, true will be returned.
Expand All @@ -34,45 +32,25 @@ public class CreateAopProxyInterceptor implements InstanceMethodsAroundIntercept

@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
MethodInterceptResult result) throws Throwable {

}

@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
Object ret) throws Throwable {
AdvisedSupport advisedSupport = (AdvisedSupport) allArguments[0];

if (maybeHasUserSuppliedProxyInterfaces(ret)) {
Class targetClass = advisedSupport.getTargetClass();
if (targetClass != null) {
if (onlyImplementsEnhancedInstance(advisedSupport) || onlyImplementsEnhancedInstanceAndSpringProxy(advisedSupport)) {
return true;
}
}
Class targetClass = advisedSupport.getTargetClass();
if (targetClass != null && EnhancedInstance.class.isAssignableFrom(targetClass)) {
return true;
}
return ret;
}

private boolean maybeHasUserSuppliedProxyInterfaces(Object ret) {
return !(Boolean) ret;
}

private boolean onlyImplementsEnhancedInstanceAndSpringProxy(AdvisedSupport advisedSupport) {
Class<?>[] ifcs = advisedSupport.getProxiedInterfaces();
Class targetClass = advisedSupport.getTargetClass();
return ifcs.length == 2 && EnhancedInstance.class.isAssignableFrom(targetClass) && SpringProxy.class.isAssignableFrom(targetClass);
}

private boolean onlyImplementsEnhancedInstance(AdvisedSupport advisedSupport) {
Class<?>[] ifcs = advisedSupport.getProxiedInterfaces();
Class targetClass = advisedSupport.getTargetClass();
return ifcs.length == 1 && EnhancedInstance.class.isAssignableFrom(targetClass);
}

@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
Class<?>[] argumentsTypes, Throwable t) {

}
}
14 changes: 10 additions & 4 deletions docs/en/setup/service-agent/java-agent/Optional-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ Now, we have the following known 2 kinds of optional plugins.
These plugins affect the performance or must be used under some conditions, from experiences.
So only released in `/optional-plugins` or `/bootstrap-plugins`, copy to `/plugins` in order to make them work.

* [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)
* Plugin of [tracing Spring annotation beans](agent-optional-plugins/Spring-annotation-plugin.md)
* [Filter traces through specified endpoint name patterns](agent-optional-plugins/trace-ignore-plugin.md)
* Plugin of Gson serialization lib in optional plugin folder.
* 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.x and 3.x and 4.x in optional plugin folder. Please only activate this plugin when you install agent in Spring Gateway.
* Plugin of [Spring Cloud Gateway 2.x and 3.x and 4.x](agent-optional-plugins/spring-gateway.md) in optional plugin folder. Please only activate this plugin when you install agent in Spring Gateway.
* Plugin of Spring Transaction in optional plugin folder. The reason of being optional plugin is, many local span are generated, which also spend more CPU, memory and network.
* [Plugin of Kotlin coroutine](agent-optional-plugins/Kotlin-Coroutine-plugin.md) provides the tracing across coroutines automatically. As it will add local spans to all across routines scenarios, Please assess the performance impact.
* Plugin of quartz-scheduler-2.x in the optional plugin folder. The reason for being an optional plugin is, many task scheduling systems are based on quartz-scheduler, this will cause duplicate tracing and link different sub-tasks as they share the same quartz level trigger, such as ElasticJob.
Expand All @@ -26,11 +25,18 @@ So only released in `/optional-plugins` or `/bootstrap-plugins`, copy to `/plugi
* Plugin of fastjson serialization lib in optional plugin folder.
* Plugin of jackson serialization lib in optional plugin folder.
* Plugin of Apache ShenYu(incubating) Gateway 2.4.x in optional plugin folder. Please only activate this plugin when you install agent in Apache ShenYu Gateway.
* Plugin of trace sampler CPU policy in the optional plugin folder. Please only activate this plugin when you need to disable trace collecting when the agent process CPU usage is too high(over threshold).
* Plugin of sampler plugin with CPU policy in the optional plugin folder. Please only activate this plugin when you need to disable trace collecting when the agent process CPU usage is too high(over threshold).
* Plugin for Spring 6.x and RestTemplate 6.x are in the optional plugin folder. Spring 6 requires Java 17 but SkyWalking is still compatible with Java 8. So, we put it in the optional plugin folder.
* Plugin of nacos-client 2.x lib in optional plugin folder. The reason is many business irrelevant traces are generated, which cause extra payload to agents and backends, also spend more CPU, memory and network.
* Plugin of netty-http 4.1.x lib in optional plugin folder. The reason is some frameworks use Netty HTTP as kernel, which could double the unnecessary spans and create incorrect RPC relative metrics.

### Notice due to Licence Restrictions
These plugins can't be provided in Apache release because of Oracle and Resin Licenses.
If you want to know details, please read [Apache license legal document](https://www.apache.org/legal/resolved.html)

Due to license incompatibilities/restrictions these plugins are hosted and released in 3rd part repository,
go to [OpenSkywalking java plugin extension repository](https://github.com/OpenSkywalking/java-plugin-extensions) to get these.

## Optional Level 3 Plugins. Expired Plugins
These plugins are not tested in the CI/CD pipeline, as the previous added tests are not able to run according to the latest
CI/CD infrastructure limitations, lack of maintenance, or dependencies/images not available(e.g. removed from DockerHub).
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Spring annotation plugin
# Spring annotation plugin
This plugin allows to trace all methods of beans in Spring context, which are annotated with
`@Bean`, `@Service`, `@Component` and `@Repository`.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Spring Gateway Plugin

Spring Gateway Plugin only support Spring Gateway 2.x, 3.x and 4.x. It has capabilities to create entry spans for
incoming calls, continue tracing context propagation in Spring Gateway and create exit spans for outgoing calls.

About the filter extension of Gateway, it provides automatically support as much as possible, including GlobalFilter and GatewayFilter
support. However, the filter extension by using `chain.filter(exchange).then(...)` is not able to transparently.

## Supported Auto-Instrument Filters

```java
@Component
public class Filter1 implements GlobalFilter, Ordered {

private static final Logger log = LoggerFactory.getLogger(Filter1.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// Available trace context
// For log framework integration(trace context log output) and manual trace context usage.
String traceId = TraceContext.traceId();
log.info("available traceId: {}", traceId);

String segmentId = TraceContext.segmentId();
log.info("available segmentId: {}", segmentId);

int spanId = TraceContext.spanId();
log.info("available spanId: {}", spanId);

return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100;
}
}
```
```java
@Component
public class GatewayFilter1 implements GatewayFilter {

private static final Logger log = LoggerFactory.getLogger(GatewayFilter1.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// Available trace context
log.info("gatewayFilter1 running");
return chain.filter(exchange);
}
}
```

## Unsupported Auto-Instrument Filters
Typically, in the following case, you need to read via [Webflux Tracing Assistant APIs](../Application-toolkit-webflux.md) to get the trace context.

```java
@Component
public class UnsupportedFilter implements GlobalFilter, Ordered {
private static final Logger log = LoggerFactory.getLogger(UnsupportedFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String traceId = TraceContext.traceId();
// Trace ID is available as it's in the GlobalFilter.
log.info("available traceId: {}", traceId);

String segmentId = TraceContext.segmentId();
// Segment ID is available as it's in the GlobalFilter.
log.info("available segmentId: {}", segmentId);

int spanId = TraceContext.spanId();
// Span ID is available as it's in the GlobalFilter.
log.info("available spanId: {}", spanId);

return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// Trace ID/context is not available, N/A in the all following logs.
// The trace context is not available in the then-closure.
// Only webflux assistant API can get the trace context.
String traceId2 = WebFluxSkyWalkingTraceContext.traceId(exchange);
// Trace ID is not available, N/A in the logs.
log.info("unavailable in then-closure, available traceId: {} through webflux assistant API", traceId2);

String segmentId2 = WebFluxSkyWalkingTraceContext.segmentId(exchange);
// Segment ID is not available, N/A in the logs.
log.info("unavailable in then-closure, available segmentId: {} through webflux assistant API", segmentId2);

int spanId2 = WebFluxSkyWalkingTraceContext.spanId(exchange);
// Span ID is not available, N/A in the logs.
log.info("unavailable in then-closure, available spanId: {} through webflux assistant API", spanId2);
}));
}

@Override
public int getOrder() {
return 10;
}
}

```
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Support custom trace ignore
# Support Custom Trace Ignoring
Here is an optional plugin `apm-trace-ignore-plugin`

**Notice:**
Expand All @@ -18,3 +18,5 @@ There are two ways to configure ignore patterns. Settings through system env has
trace.ignore_path=/your/path/1/**,/your/path/2/**
```

## Conflicts Notice
Due to the mechanism sharing, this plugin has conflicts with the plugin of **sampler plugin with CPU policy**(`trace-sampler-cpu-policy-plugin-*.jar`) in the optional plugin folder.
12 changes: 11 additions & 1 deletion docs/menu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,17 @@ catalog:
- name: "Supported middleware, framework and library"
path: "/en/setup/service-agent/java-agent/Supported-list"
- name: "Optional Plugins"
path: "/en/setup/service-agent/java-agent/Optional-plugins"
catalog:
- name: "Plugin Manifest"
path: "/en/setup/service-agent/java-agent/Optional-plugins"
- name: "Spring Annotation Plugin"
path: "/en/setup/service-agent/java-agent/agent-optional-plugins/Spring-annotation-plugin"
- name: "Spring Gateway"
path: "/en/setup/service-agent/java-agent/agent-optional-plugins/spring-gateway"
- name: "Custom Trace Ignoring"
path: "/en/setup/service-agent/java-agent/agent-optional-plugins/trace-ignore-plugin"
- name: "Kotlin Coroutine"
path: "/en/setup/service-agent/java-agent/agent-optional-plugins/Kotlin-Coroutine-plugin"
- name: "Bootstrap/JVM class plugin"
path: "/en/setup/service-agent/java-agent/Bootstrap-plugins"
- name: "Agent Configuration Properties"
Expand Down

0 comments on commit 394ddc2

Please sign in to comment.