|
8 | 8 | import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; |
9 | 9 | import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface; |
10 | 10 | import static io.opentelemetry.javaagent.instrumentation.awslambdaevents.v2_2.AwsLambdaSingletons.flushTimeout; |
| 11 | +import static io.opentelemetry.javaagent.instrumentation.awslambdaevents.v2_2.AwsLambdaSingletons.functionInstrumenter; |
11 | 12 | import static net.bytebuddy.matcher.ElementMatchers.isMethod; |
12 | 13 | import static net.bytebuddy.matcher.ElementMatchers.isPublic; |
13 | 14 | import static net.bytebuddy.matcher.ElementMatchers.named; |
|
25 | 26 | import java.util.Collections; |
26 | 27 | import java.util.Map; |
27 | 28 | import java.util.concurrent.TimeUnit; |
| 29 | +import javax.annotation.Nullable; |
28 | 30 | import net.bytebuddy.asm.Advice; |
29 | 31 | import net.bytebuddy.description.type.TypeDescription; |
30 | 32 | import net.bytebuddy.implementation.bytecode.assign.Assigner.Typing; |
@@ -55,63 +57,90 @@ public void transform(TypeTransformer transformer) { |
55 | 57 | @SuppressWarnings("unused") |
56 | 58 | public static class HandleRequestAdvice { |
57 | 59 |
|
58 | | - @Advice.OnMethodEnter(suppress = Throwable.class) |
59 | | - public static void onEnter( |
60 | | - @Advice.Argument(value = 0, typing = Typing.DYNAMIC) Object arg, |
61 | | - @Advice.Argument(1) Context context, |
62 | | - @Advice.Local("otelInput") AwsLambdaRequest input, |
63 | | - @Advice.Local("otelFunctionContext") io.opentelemetry.context.Context functionContext, |
64 | | - @Advice.Local("otelFunctionScope") Scope functionScope, |
65 | | - @Advice.Local("otelMessageContext") io.opentelemetry.context.Context messageContext, |
66 | | - @Advice.Local("otelMessageScope") Scope messageScope) { |
67 | | - Map<String, String> headers = Collections.emptyMap(); |
68 | | - if (arg instanceof APIGatewayProxyRequestEvent) { |
69 | | - headers = MapUtils.lowercaseMap(((APIGatewayProxyRequestEvent) arg).getHeaders()); |
| 60 | + public static class AdviceScope { |
| 61 | + private final AwsLambdaRequest lambdaRequest; |
| 62 | + private final Scope functionScope; |
| 63 | + private final io.opentelemetry.context.Context functionContext; |
| 64 | + private final Scope messageScope; |
| 65 | + private final io.opentelemetry.context.Context messageContext; |
| 66 | + |
| 67 | + private AdviceScope( |
| 68 | + AwsLambdaRequest lambdaRequest, |
| 69 | + io.opentelemetry.context.Context functionContext, |
| 70 | + Scope functionScope, |
| 71 | + io.opentelemetry.context.Context messageContext, |
| 72 | + Scope messageScope) { |
| 73 | + this.lambdaRequest = lambdaRequest; |
| 74 | + this.functionContext = functionContext; |
| 75 | + this.functionScope = functionScope; |
| 76 | + this.messageContext = messageContext; |
| 77 | + this.messageScope = messageScope; |
70 | 78 | } |
71 | | - input = AwsLambdaRequest.create(context, arg, headers); |
72 | | - io.opentelemetry.context.Context parentContext = |
73 | | - AwsLambdaSingletons.functionInstrumenter().extract(input); |
74 | 79 |
|
75 | | - if (!AwsLambdaSingletons.functionInstrumenter().shouldStart(parentContext, input)) { |
76 | | - return; |
77 | | - } |
| 80 | + @Nullable |
| 81 | + public static AdviceScope start(Object arg, Context context) { |
78 | 82 |
|
79 | | - functionContext = AwsLambdaSingletons.functionInstrumenter().start(parentContext, input); |
80 | | - functionScope = functionContext.makeCurrent(); |
| 83 | + Map<String, String> headers = Collections.emptyMap(); |
| 84 | + if (arg instanceof APIGatewayProxyRequestEvent) { |
| 85 | + headers = MapUtils.lowercaseMap(((APIGatewayProxyRequestEvent) arg).getHeaders()); |
| 86 | + } |
| 87 | + AwsLambdaRequest lambdaRequest = AwsLambdaRequest.create(context, arg, headers); |
| 88 | + io.opentelemetry.context.Context parentContext = |
| 89 | + functionInstrumenter().extract(lambdaRequest); |
81 | 90 |
|
82 | | - if (arg instanceof SQSEvent) { |
83 | | - if (AwsLambdaSingletons.messageInstrumenter() |
84 | | - .shouldStart(functionContext, (SQSEvent) arg)) { |
85 | | - messageContext = |
86 | | - AwsLambdaSingletons.messageInstrumenter().start(functionContext, (SQSEvent) arg); |
87 | | - messageScope = messageContext.makeCurrent(); |
| 91 | + if (!functionInstrumenter().shouldStart(parentContext, lambdaRequest)) { |
| 92 | + return null; |
88 | 93 | } |
| 94 | + |
| 95 | + io.opentelemetry.context.Context functionContext = |
| 96 | + functionInstrumenter().start(parentContext, lambdaRequest); |
| 97 | + Scope functionScope = functionContext.makeCurrent(); |
| 98 | + |
| 99 | + io.opentelemetry.context.Context messageContext = null; |
| 100 | + Scope messageScope = null; |
| 101 | + if (arg instanceof SQSEvent) { |
| 102 | + if (AwsLambdaSingletons.messageInstrumenter() |
| 103 | + .shouldStart(functionContext, (SQSEvent) arg)) { |
| 104 | + messageContext = |
| 105 | + AwsLambdaSingletons.messageInstrumenter().start(functionContext, (SQSEvent) arg); |
| 106 | + messageScope = messageContext.makeCurrent(); |
| 107 | + } |
| 108 | + } |
| 109 | + return new AdviceScope( |
| 110 | + lambdaRequest, functionContext, functionScope, messageContext, messageScope); |
89 | 111 | } |
| 112 | + |
| 113 | + public void end(Object arg, @Nullable Object result, @Nullable Throwable throwable) { |
| 114 | + if (messageScope != null) { |
| 115 | + messageScope.close(); |
| 116 | + AwsLambdaSingletons.messageInstrumenter() |
| 117 | + .end(messageContext, (SQSEvent) arg, null, throwable); |
| 118 | + } |
| 119 | + if (functionScope != null) { |
| 120 | + functionScope.close(); |
| 121 | + functionInstrumenter().end(functionContext, lambdaRequest, result, throwable); |
| 122 | + } |
| 123 | + OpenTelemetrySdkAccess.forceFlush(flushTimeout().toNanos(), TimeUnit.NANOSECONDS); |
| 124 | + } |
| 125 | + } |
| 126 | + |
| 127 | + @Nullable |
| 128 | + @Advice.OnMethodEnter(suppress = Throwable.class) |
| 129 | + public static AdviceScope onEnter( |
| 130 | + @Advice.Argument(value = 0, typing = Typing.DYNAMIC) Object arg, |
| 131 | + @Advice.Argument(1) Context context) { |
| 132 | + return AdviceScope.start(arg, context); |
90 | 133 | } |
91 | 134 |
|
92 | 135 | @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) |
93 | 136 | public static void stopSpan( |
94 | 137 | @Advice.Argument(value = 0, typing = Typing.DYNAMIC) Object arg, |
95 | | - @Advice.Return Object result, |
96 | | - @Advice.Thrown Throwable throwable, |
97 | | - @Advice.Local("otelInput") AwsLambdaRequest input, |
98 | | - @Advice.Local("otelFunctionContext") io.opentelemetry.context.Context functionContext, |
99 | | - @Advice.Local("otelFunctionScope") Scope functionScope, |
100 | | - @Advice.Local("otelMessageContext") io.opentelemetry.context.Context messageContext, |
101 | | - @Advice.Local("otelMessageScope") Scope messageScope) { |
102 | | - |
103 | | - if (messageScope != null) { |
104 | | - messageScope.close(); |
105 | | - AwsLambdaSingletons.messageInstrumenter() |
106 | | - .end(messageContext, (SQSEvent) arg, null, throwable); |
107 | | - } |
108 | | - |
109 | | - if (functionScope != null) { |
110 | | - functionScope.close(); |
111 | | - AwsLambdaSingletons.functionInstrumenter().end(functionContext, input, result, throwable); |
| 138 | + @Advice.Return @Nullable Object result, |
| 139 | + @Advice.Thrown @Nullable Throwable throwable, |
| 140 | + @Advice.Enter @Nullable AdviceScope adviceScope) { |
| 141 | + if (adviceScope != null) { |
| 142 | + adviceScope.end(arg, result, throwable); |
112 | 143 | } |
113 | | - |
114 | | - OpenTelemetrySdkAccess.forceFlush(flushTimeout().toNanos(), TimeUnit.NANOSECONDS); |
115 | 144 | } |
116 | 145 | } |
117 | 146 | } |
0 commit comments