2121import java .net .URL ;
2222import java .util .function .BiConsumer ;
2323import java .util .function .Function ;
24+
2425import org .apache .skywalking .apm .agent .core .context .CarrierItem ;
2526import org .apache .skywalking .apm .agent .core .context .ContextCarrier ;
2627import org .apache .skywalking .apm .agent .core .context .ContextManager ;
2728import org .apache .skywalking .apm .agent .core .context .tag .Tags ;
2829import org .apache .skywalking .apm .agent .core .context .trace .AbstractSpan ;
2930import org .apache .skywalking .apm .agent .core .context .trace .SpanLayer ;
3031import org .apache .skywalking .apm .agent .core .plugin .interceptor .enhance .EnhancedInstance ;
31- import org .apache .skywalking .apm .agent .core .plugin .interceptor .enhance .InstanceMethodsAroundInterceptor ;
32- import org .apache .skywalking .apm .agent .core .plugin .interceptor .enhance .MethodInterceptResult ;
32+ import org .apache .skywalking .apm .agent .core .plugin .interceptor .enhance .v2 . InstanceMethodsAroundInterceptorV2 ;
33+ import org .apache .skywalking .apm .agent .core .plugin .interceptor .enhance .v2 . MethodInvocationContext ;
3334import org .apache .skywalking .apm .plugin .spring .cloud .gateway .v20x .define .EnhanceCacheObject ;
3435import org .reactivestreams .Publisher ;
3536import reactor .core .publisher .Mono ;
3839
3940import static org .apache .skywalking .apm .network .trace .component .ComponentsDefine .SPRING_CLOUD_GATEWAY ;
4041
41- public class HttpClientRequestInterceptor implements InstanceMethodsAroundInterceptor {
42+ public class HttpClientRequestInterceptor implements InstanceMethodsAroundInterceptorV2 {
43+
4244 @ Override
4345 public void beforeMethod (final EnhancedInstance objInst ,
4446 final Method method ,
4547 final Object [] allArguments ,
4648 final Class <?>[] argumentsTypes ,
47- final MethodInterceptResult result ) throws Throwable {
49+ final MethodInvocationContext context ) throws Throwable {
4850
4951 /*
5052 In this plug-in, the HttpClientFinalizerSendInterceptor depends on the NettyRoutingFilterInterceptor
@@ -54,13 +56,13 @@ public void beforeMethod(final EnhancedInstance objInst,
5456 if (!ContextManager .isActive ()) {
5557 return ;
5658 }
57-
59+
5860 AbstractSpan span = ContextManager .activeSpan ();
5961
6062 URL url = new URL ((String ) allArguments [1 ]);
6163 ContextCarrier contextCarrier = new ContextCarrier ();
6264 AbstractSpan abstractSpan = ContextManager .createExitSpan (
63- "SpringCloudGateway/sendRequest" , contextCarrier , getPeer (url ));
65+ "SpringCloudGateway/sendRequest" , contextCarrier , getPeer (url ));
6466 abstractSpan .prepareForAsync ();
6567 Tags .URL .set (abstractSpan , String .valueOf (allArguments [1 ]));
6668 abstractSpan .setLayer (SpanLayer .HTTP );
@@ -80,36 +82,53 @@ public Publisher<Void> apply(final HttpClientRequest httpClientRequest) {
8082 }
8183 };
8284
83- objInst . setSkyWalkingDynamicField (new EnhanceCacheObject (span , abstractSpan ));
85+ context . setContext (new EnhanceCacheObject (span , abstractSpan ));
8486 }
8587
8688 @ Override
8789 public Object afterMethod (final EnhancedInstance objInst ,
8890 final Method method ,
8991 final Object [] allArguments ,
9092 final Class <?>[] argumentsTypes ,
91- final Object ret ) {
92- EnhanceCacheObject enhanceCacheObject = (EnhanceCacheObject ) objInst .getSkyWalkingDynamicField ();
93+ final Object ret ,
94+ MethodInvocationContext context ) {
95+ EnhanceCacheObject enhanceCacheObject = (EnhanceCacheObject ) context .getContext ();
9396 Mono <HttpClientResponse > responseMono = (Mono <HttpClientResponse >) ret ;
9497 return responseMono .doAfterSuccessOrError (new BiConsumer <HttpClientResponse , Throwable >() {
9598 @ Override
9699 public void accept (final HttpClientResponse httpClientResponse , final Throwable throwable ) {
100+ doAfterSuccessOrError (httpClientResponse , throwable , enhanceCacheObject );
101+ }
102+ });
103+ }
97104
98- AbstractSpan abstractSpan = enhanceCacheObject .getSendSpan ();
99- if (abstractSpan != null ) {
100- if (throwable != null ) {
101- abstractSpan .log (throwable );
102- } else if (httpClientResponse .status ().code () > 400 ) {
103- abstractSpan .errorOccurred ();
104- }
105- Tags .HTTP_RESPONSE_STATUS_CODE .set (abstractSpan , httpClientResponse .status ().code ());
106- abstractSpan .asyncFinish ();
107- }
105+ void doAfterSuccessOrError (HttpClientResponse httpClientResponse , Throwable throwable , EnhanceCacheObject enhanceCacheObject ) {
106+ try {
107+ //When executing the beforeMethod method, if the ContextManager is inactive, the enhanceCacheObject will be null.
108+ if (enhanceCacheObject == null ) {
109+ return ;
110+ }
108111
109- objInst .setSkyWalkingDynamicField (null );
110- enhanceCacheObject .getFilterSpan ().asyncFinish ();
112+ //The doAfterSuccessOrError method may be executed multiple times.
113+ if (enhanceCacheObject .isSpanFinish ()) {
114+ return ;
111115 }
112- });
116+
117+ AbstractSpan abstractSpan = enhanceCacheObject .getSendSpan ();
118+ if (throwable != null ) {
119+ abstractSpan .log (throwable );
120+ } else if (httpClientResponse .status ().code () > 400 ) {
121+ abstractSpan .errorOccurred ();
122+ }
123+ Tags .HTTP_RESPONSE_STATUS_CODE .set (abstractSpan , httpClientResponse .status ().code ());
124+
125+ abstractSpan .asyncFinish ();
126+ enhanceCacheObject .getFilterSpan ().asyncFinish ();
127+
128+ enhanceCacheObject .setSpanFinish (true );
129+ } catch (Throwable e ) {
130+ //Catch unknown exceptions to avoid interrupting business processes.
131+ }
113132 }
114133
115134 private String getPeer (URL url ) {
@@ -121,7 +140,8 @@ public void handleMethodException(final EnhancedInstance objInst,
121140 final Method method ,
122141 final Object [] allArguments ,
123142 final Class <?>[] argumentsTypes ,
124- final Throwable t ) {
143+ final Throwable t ,
144+ MethodInvocationContext context ) {
125145
126146 }
127147}
0 commit comments