1818import io .opentelemetry .instrumentation .elasticsearch .rest .common .v5_0 .internal .RestResponseListener ;
1919import io .opentelemetry .javaagent .extension .instrumentation .TypeInstrumentation ;
2020import io .opentelemetry .javaagent .extension .instrumentation .TypeTransformer ;
21+ import javax .annotation .Nullable ;
2122import net .bytebuddy .asm .Advice ;
23+ import net .bytebuddy .asm .Advice .AssignReturned ;
24+ import net .bytebuddy .asm .Advice .AssignReturned .ToArguments .ToArgument ;
2225import net .bytebuddy .description .type .TypeDescription ;
2326import net .bytebuddy .matcher .ElementMatcher ;
2427import org .elasticsearch .client .Request ;
@@ -44,44 +47,56 @@ public void transform(TypeTransformer transformer) {
4447 @ SuppressWarnings ("unused" )
4548 public static class PerformRequestAsyncAdvice {
4649
50+ public static class AdviceScope {
51+ private final ElasticsearchRestRequest request ;
52+ private final Context context ;
53+ private final Scope scope ;
54+
55+ public AdviceScope (ElasticsearchRestRequest request , Context context , Scope scope ) {
56+ this .request = request ;
57+ this .context = context ;
58+ this .scope = scope ;
59+ }
60+
61+ public void end (@ Nullable Throwable throwable ) {
62+ scope .close ();
63+ if (throwable != null ) {
64+ instrumenter ().end (context , request , null , throwable );
65+ }
66+ // span ended in RestResponseListener
67+ }
68+ }
69+
70+ @ AssignReturned .ToArguments (@ ToArgument (value = 1 , index = 1 ))
4771 @ Advice .OnMethodEnter (suppress = Throwable .class )
48- public static void onEnter (
72+ public static Object [] onEnter (
4973 @ Advice .Argument (0 ) Request request ,
50- @ Advice .Argument (value = 1 , readOnly = false ) ResponseListener responseListener ,
51- @ Advice .Local ("otelRequest" ) ElasticsearchRestRequest otelRequest ,
52- @ Advice .Local ("otelContext" ) Context context ,
53- @ Advice .Local ("otelScope" ) Scope scope ) {
74+ @ Advice .Argument (1 ) ResponseListener originalResponseListener ) {
75+
76+ ResponseListener responseListener = originalResponseListener ;
5477
5578 Context parentContext = currentContext ();
56- otelRequest = ElasticsearchRestRequest .create (request .getMethod (), request .getEndpoint ());
79+ ElasticsearchRestRequest otelRequest =
80+ ElasticsearchRestRequest .create (request .getMethod (), request .getEndpoint ());
5781 if (!instrumenter ().shouldStart (parentContext , otelRequest )) {
58- return ;
82+ return new Object [] { null , responseListener } ;
5983 }
60-
61- context = instrumenter ().start (parentContext , otelRequest );
62- scope = context .makeCurrent ();
84+ Context context = instrumenter ().start (parentContext , otelRequest );
85+ AdviceScope adviceScope = new AdviceScope (otelRequest , context , context .makeCurrent ());
6386
6487 responseListener =
6588 new RestResponseListener (
6689 responseListener , parentContext , instrumenter (), context , otelRequest );
90+ return new Object [] {adviceScope , responseListener };
6791 }
6892
6993 @ Advice .OnMethodExit (onThrowable = Throwable .class , suppress = Throwable .class )
7094 public static void stopSpan (
71- @ Advice .Thrown Throwable throwable ,
72- @ Advice .Local ("otelRequest" ) ElasticsearchRestRequest otelRequest ,
73- @ Advice .Local ("otelContext" ) Context context ,
74- @ Advice .Local ("otelScope" ) Scope scope ) {
75-
76- if (scope == null ) {
77- return ;
78- }
79- scope .close ();
80-
81- if (throwable != null ) {
82- instrumenter ().end (context , otelRequest , null , throwable );
95+ @ Advice .Thrown @ Nullable Throwable throwable , @ Advice .Enter Object [] enterResult ) {
96+ AdviceScope adviceScope = (AdviceScope ) enterResult [0 ];
97+ if (adviceScope != null ) {
98+ adviceScope .end (throwable );
8399 }
84- // span ended in RestResponseListener
85100 }
86101 }
87102}
0 commit comments