Skip to content

Commit 95ea343

Browse files
LikeTheSaladlaurit
authored andcommitted
Indy-ready - twilio (open-telemetry#14839)
Co-authored-by: Lauri Tulmin <[email protected]>
1 parent e958747 commit 95ea343

File tree

3 files changed

+99
-62
lines changed

3 files changed

+99
-62
lines changed

instrumentation/twilio-6.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioAsyncInstrumentation.java

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
package io.opentelemetry.javaagent.instrumentation.twilio;
77

8-
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
98
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass;
109
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
1110
import static io.opentelemetry.javaagent.instrumentation.twilio.TwilioSingletons.instrumenter;
@@ -26,6 +25,7 @@
2625
import io.opentelemetry.context.Scope;
2726
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2827
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
28+
import javax.annotation.Nullable;
2929
import net.bytebuddy.asm.Advice;
3030
import net.bytebuddy.description.type.TypeDescription;
3131
import net.bytebuddy.matcher.ElementMatcher;
@@ -71,47 +71,63 @@ we found that there were certain methods declared on the base class (particularl
7171
@SuppressWarnings("unused")
7272
public static class TwilioClientAsyncAdvice {
7373

74-
/** Method entry instrumentation. */
75-
@Advice.OnMethodEnter(suppress = Throwable.class)
76-
public static void methodEnter(
77-
@Advice.This Object that,
78-
@Advice.Origin("#m") String methodName,
79-
@Advice.Local("otelContext") Context context,
80-
@Advice.Local("otelScope") Scope scope,
81-
@Advice.Local("otelSpanName") String spanName) {
82-
Context parentContext = currentContext();
83-
spanName = spanName(that, methodName);
84-
if (!instrumenter().shouldStart(parentContext, spanName)) {
85-
return;
74+
public static class AdviceScope {
75+
private final Context context;
76+
private final Scope scope;
77+
private final String spanName;
78+
79+
private AdviceScope(Context context, Scope scope, String spanName) {
80+
this.context = context;
81+
this.scope = scope;
82+
this.spanName = spanName;
83+
}
84+
85+
@Nullable
86+
public static AdviceScope start(Object target, String methodName) {
87+
Context parentContext = Context.current();
88+
String spanName = spanName(target, methodName);
89+
if (!instrumenter().shouldStart(parentContext, spanName)) {
90+
return null;
91+
}
92+
93+
Context context = instrumenter().start(parentContext, spanName);
94+
context = TwilioAsyncMarker.markAsync(context);
95+
return new AdviceScope(context, context.makeCurrent(), spanName);
96+
}
97+
98+
public void end(Throwable throwable, ListenableFuture<?> response) {
99+
scope.close();
100+
if (throwable != null) {
101+
// There was a synchronous error,
102+
// which means we shouldn't wait for a callback to close the span.
103+
instrumenter().end(context, spanName, null, throwable);
104+
} else {
105+
// We're calling an async operation, we still need to finish the span when it's
106+
// complete and report the results; set an appropriate callback
107+
Futures.addCallback(
108+
response,
109+
new SpanFinishingCallback<>(context, spanName),
110+
Twilio.getExecutorService());
111+
}
86112
}
113+
}
87114

88-
context = instrumenter().start(parentContext, spanName);
89-
context = TwilioAsyncMarker.markAsync(context);
90-
scope = context.makeCurrent();
115+
/** Method entry instrumentation. */
116+
@Nullable
117+
@Advice.OnMethodEnter(suppress = Throwable.class)
118+
public static AdviceScope methodEnter(
119+
@Advice.This Object that, @Advice.Origin("#m") String methodName) {
120+
return AdviceScope.start(that, methodName);
91121
}
92122

93123
/** Method exit instrumentation. */
94124
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
95125
public static void methodExit(
96-
@Advice.Thrown Throwable throwable,
97-
@Advice.Return ListenableFuture<?> response,
98-
@Advice.Local("otelContext") Context context,
99-
@Advice.Local("otelScope") Scope scope,
100-
@Advice.Local("otelSpanName") String spanName) {
101-
if (scope == null) {
102-
return;
103-
}
104-
105-
scope.close();
106-
if (throwable != null) {
107-
// There was an synchronous error,
108-
// which means we shouldn't wait for a callback to close the span.
109-
instrumenter().end(context, spanName, null, throwable);
110-
} else {
111-
// We're calling an async operation, we still need to finish the span when it's
112-
// complete and report the results; set an appropriate callback
113-
Futures.addCallback(
114-
response, new SpanFinishingCallback<>(context, spanName), Twilio.getExecutorService());
126+
@Advice.Thrown @Nullable Throwable throwable,
127+
@Advice.Enter @Nullable AdviceScope adviceScope,
128+
@Advice.Return ListenableFuture<?> response) {
129+
if (adviceScope != null) {
130+
adviceScope.end(throwable, response);
115131
}
116132
}
117133
}

instrumentation/twilio-6.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioInstrumentationModule.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import com.google.auto.service.AutoService;
1111
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1212
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
13+
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
1314
import java.util.List;
1415

1516
@AutoService(InstrumentationModule.class)
16-
public class TwilioInstrumentationModule extends InstrumentationModule {
17+
public class TwilioInstrumentationModule extends InstrumentationModule
18+
implements ExperimentalInstrumentationModule {
1719
public TwilioInstrumentationModule() {
1820
super("twilio", "twilio-6.6");
1921
}
@@ -22,4 +24,9 @@ public TwilioInstrumentationModule() {
2224
public List<TypeInstrumentation> typeInstrumentations() {
2325
return asList(new TwilioAsyncInstrumentation(), new TwilioSyncInstrumentation());
2426
}
27+
28+
@Override
29+
public boolean isIndyReady() {
30+
return true;
31+
}
2532
}

instrumentation/twilio-6.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioSyncInstrumentation.java

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
package io.opentelemetry.javaagent.instrumentation.twilio;
77

8-
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
98
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass;
109
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
1110
import static io.opentelemetry.javaagent.instrumentation.twilio.TwilioSingletons.instrumenter;
@@ -19,6 +18,7 @@
1918
import io.opentelemetry.context.Scope;
2019
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2120
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
21+
import javax.annotation.Nullable;
2222
import net.bytebuddy.asm.Advice;
2323
import net.bytebuddy.description.type.TypeDescription;
2424
import net.bytebuddy.matcher.ElementMatcher;
@@ -63,39 +63,53 @@ we found that there were certain methods declared on the base class (particularl
6363
@SuppressWarnings("unused")
6464
public static class TwilioClientAdvice {
6565

66-
/** Method entry instrumentation. */
67-
@Advice.OnMethodEnter(suppress = Throwable.class)
68-
public static void methodEnter(
69-
@Advice.This Object that,
70-
@Advice.Origin("#m") String methodName,
71-
@Advice.Local("otelContext") Context context,
72-
@Advice.Local("otelScope") Scope scope,
73-
@Advice.Local("otelSpanName") String spanName) {
74-
Context parentContext = currentContext();
75-
spanName = TwilioSingletons.spanName(that, methodName);
76-
if (!instrumenter().shouldStart(parentContext, spanName)
77-
|| TwilioAsyncMarker.isMarkedAsync(parentContext)) {
78-
return;
66+
public static class AdviceScope {
67+
private final Context context;
68+
private final Scope scope;
69+
private final String spanName;
70+
71+
private AdviceScope(Context context, Scope scope, String spanName) {
72+
this.context = context;
73+
this.scope = scope;
74+
this.spanName = spanName;
75+
}
76+
77+
@Nullable
78+
public static AdviceScope start(Object target, String methodName) {
79+
Context parentContext = Context.current();
80+
String spanName = TwilioSingletons.spanName(target, methodName);
81+
if (!instrumenter().shouldStart(parentContext, spanName)
82+
|| TwilioAsyncMarker.isMarkedAsync(parentContext)) {
83+
return null;
84+
}
85+
86+
Context context = instrumenter().start(parentContext, spanName);
87+
return new AdviceScope(context, context.makeCurrent(), spanName);
7988
}
8089

81-
context = instrumenter().start(parentContext, spanName);
82-
scope = context.makeCurrent();
90+
public void end(Throwable throwable, Object response) {
91+
scope.close();
92+
instrumenter().end(context, spanName, response, throwable);
93+
}
94+
}
95+
96+
/** Method entry instrumentation. */
97+
@Nullable
98+
@Advice.OnMethodEnter(suppress = Throwable.class)
99+
public static AdviceScope methodEnter(
100+
@Advice.This Object that, @Advice.Origin("#m") String methodName) {
101+
return AdviceScope.start(that, methodName);
83102
}
84103

85104
/** Method exit instrumentation. */
86105
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
87106
public static void methodExit(
88-
@Advice.Thrown Throwable throwable,
89-
@Advice.Return Object response,
90-
@Advice.Local("otelContext") Context context,
91-
@Advice.Local("otelScope") Scope scope,
92-
@Advice.Local("otelSpanName") String spanName) {
93-
if (scope == null) {
94-
return;
107+
@Advice.Thrown @Nullable Throwable throwable,
108+
@Advice.Enter @Nullable AdviceScope adviceScope,
109+
@Advice.Return Object response) {
110+
if (adviceScope != null) {
111+
adviceScope.end(throwable, response);
95112
}
96-
97-
scope.close();
98-
instrumenter().end(context, spanName, response, throwable);
99113
}
100114
}
101115
}

0 commit comments

Comments
 (0)