Skip to content

Commit 2e4b962

Browse files
jaydelucalaurit
andauthored
Update play mvc to use AdviceScope (#13140)
Co-authored-by: Lauri Tulmin <[email protected]>
1 parent d93fc76 commit 2e4b962

File tree

2 files changed

+97
-55
lines changed

2 files changed

+97
-55
lines changed

instrumentation/play/play-mvc/play-mvc-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/ActionInstrumentation.java

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.opentelemetry.context.Scope;
1919
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2020
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
21+
import javax.annotation.Nullable;
2122
import net.bytebuddy.asm.Advice;
2223
import net.bytebuddy.description.type.TypeDescription;
2324
import net.bytebuddy.matcher.ElementMatcher;
@@ -49,41 +50,60 @@ public void transform(TypeTransformer transformer) {
4950
@SuppressWarnings("unused")
5051
public static class ApplyAdvice {
5152

52-
@Advice.OnMethodEnter(suppress = Throwable.class)
53-
public static void onEnter(
54-
@Advice.Argument(0) Request<?> req,
55-
@Advice.Local("otelContext") Context context,
56-
@Advice.Local("otelScope") Scope scope) {
57-
Context parentContext = currentContext();
58-
if (!instrumenter().shouldStart(parentContext, null)) {
59-
return;
53+
public static class AdviceScope {
54+
private final Context context;
55+
private final Scope scope;
56+
57+
public AdviceScope(Context context, Scope scope) {
58+
this.context = context;
59+
this.scope = scope;
60+
}
61+
62+
@Nullable
63+
public static AdviceScope start(Context parentContext) {
64+
if (!instrumenter().shouldStart(parentContext, null)) {
65+
return null;
66+
}
67+
68+
Context context = instrumenter().start(parentContext, null);
69+
return new AdviceScope(context, context.makeCurrent());
6070
}
6171

62-
context = instrumenter().start(parentContext, null);
63-
scope = context.makeCurrent();
72+
public void end(
73+
@Nullable Throwable throwable,
74+
Future<Result> responseFuture,
75+
Action<?> thisAction,
76+
Request<?> req) {
77+
scope.close();
78+
updateSpan(context, req);
79+
80+
if (throwable == null) {
81+
// span finished in RequestCompleteCallback
82+
responseFuture.onComplete(
83+
new RequestCompleteCallback(context), thisAction.executionContext());
84+
} else {
85+
instrumenter().end(context, null, null, throwable);
86+
}
87+
}
88+
}
89+
90+
@Advice.OnMethodEnter(suppress = Throwable.class)
91+
public static AdviceScope onEnter(@Advice.Argument(0) Request<?> req) {
92+
return AdviceScope.start(currentContext());
6493
}
6594

6695
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
6796
public static void stopTraceOnResponse(
68-
@Advice.This Object thisAction,
97+
@Advice.This Action<?> thisAction,
6998
@Advice.Thrown Throwable throwable,
7099
@Advice.Argument(0) Request<?> req,
71-
@Advice.Return(readOnly = false) Future<Result> responseFuture,
72-
@Advice.Local("otelContext") Context context,
73-
@Advice.Local("otelScope") Scope scope) {
74-
if (scope == null) {
100+
@Advice.Return Future<Result> responseFuture,
101+
@Advice.Enter @Nullable AdviceScope actionScope) {
102+
if (actionScope == null) {
75103
return;
76104
}
77-
scope.close();
78-
79-
updateSpan(context, req);
80-
// span finished in RequestCompleteCallback
81-
if (throwable == null) {
82-
responseFuture.onComplete(
83-
new RequestCompleteCallback(context), ((Action<?>) thisAction).executionContext());
84-
} else {
85-
instrumenter().end(context, null, null, throwable);
86-
}
105+
106+
actionScope.end(throwable, responseFuture, thisAction, req);
87107
}
88108
}
89109
}

instrumentation/play/play-mvc/play-mvc-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/ActionInstrumentation.java

Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.opentelemetry.context.Scope;
1919
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2020
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
21+
import javax.annotation.Nullable;
2122
import net.bytebuddy.asm.Advice;
2223
import net.bytebuddy.description.type.TypeDescription;
2324
import net.bytebuddy.matcher.ElementMatcher;
@@ -49,44 +50,65 @@ public void transform(TypeTransformer transformer) {
4950
@SuppressWarnings("unused")
5051
public static class ApplyAdvice {
5152

52-
@Advice.OnMethodEnter(suppress = Throwable.class)
53-
public static void onEnter(
54-
@Advice.Argument(0) Request<?> req,
55-
@Advice.Local("otelContext") Context context,
56-
@Advice.Local("otelScope") Scope scope) {
57-
Context parentContext = currentContext();
58-
if (!instrumenter().shouldStart(parentContext, null)) {
59-
return;
53+
public static class AdviceScope {
54+
private final Context context;
55+
private final Scope scope;
56+
57+
public AdviceScope(Context context, Scope scope) {
58+
this.context = context;
59+
this.scope = scope;
60+
}
61+
62+
@Nullable
63+
public static AdviceScope start(Context parentContext) {
64+
if (!instrumenter().shouldStart(parentContext, null)) {
65+
return null;
66+
}
67+
68+
Context context = instrumenter().start(parentContext, null);
69+
return new AdviceScope(context, context.makeCurrent());
70+
}
71+
72+
public Future<Result> end(
73+
@Nullable Throwable throwable,
74+
Future<Result> responseFuture,
75+
Action<?> thisAction,
76+
Request<?> req) {
77+
scope.close();
78+
updateSpan(context, req);
79+
80+
if (throwable == null) {
81+
// span is finished when future completes
82+
// not using responseFuture.onComplete() because that doesn't guarantee this handler span
83+
// will be completed before the server span completes
84+
responseFuture =
85+
ResponseFutureWrapper.wrap(responseFuture, context, thisAction.executionContext());
86+
} else {
87+
instrumenter().end(context, null, null, throwable);
88+
}
89+
90+
return responseFuture;
6091
}
92+
}
6193

62-
context = instrumenter().start(parentContext, null);
63-
scope = context.makeCurrent();
94+
@Advice.OnMethodEnter(suppress = Throwable.class)
95+
public static AdviceScope onEnter(@Advice.Argument(0) Request<?> req) {
96+
return AdviceScope.start(currentContext());
6497
}
6598

6699
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
67-
public static void stopTraceOnResponse(
68-
@Advice.This Object thisAction,
100+
@Advice.AssignReturned.ToReturned
101+
public static Future<Result> stopTraceOnResponse(
102+
@Advice.This Action<?> thisAction,
69103
@Advice.Thrown Throwable throwable,
70104
@Advice.Argument(0) Request<?> req,
71-
@Advice.Return(readOnly = false) Future<Result> responseFuture,
72-
@Advice.Local("otelContext") Context context,
73-
@Advice.Local("otelScope") Scope scope) {
74-
if (scope == null) {
75-
return;
76-
}
77-
scope.close();
78-
79-
updateSpan(context, req);
80-
if (throwable == null) {
81-
// span is finished when future completes
82-
// not using responseFuture.onComplete() because that doesn't guarantee this handler span
83-
// will be completed before the server span completes
84-
responseFuture =
85-
ResponseFutureWrapper.wrap(
86-
responseFuture, context, ((Action<?>) thisAction).executionContext());
87-
} else {
88-
instrumenter().end(context, null, null, throwable);
105+
@Advice.Return Future<Result> responseFuture,
106+
@Advice.Enter @Nullable AdviceScope actionScope) {
107+
if (actionScope == null) {
108+
return responseFuture;
89109
}
110+
111+
return actionScope.end(throwable, responseFuture, thisAction, req);
90112
}
91113
}
92114
}

0 commit comments

Comments
 (0)