|
20 | 20 | import io.opentelemetry.context.Scope; |
21 | 21 | import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; |
22 | 22 | import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; |
| 23 | +import javax.annotation.Nullable; |
23 | 24 | import net.bytebuddy.asm.Advice; |
| 25 | +import net.bytebuddy.asm.Advice.AssignReturned; |
| 26 | +import net.bytebuddy.asm.Advice.AssignReturned.ToArguments.ToArgument; |
24 | 27 | import net.bytebuddy.description.type.TypeDescription; |
25 | 28 | import net.bytebuddy.matcher.ElementMatcher; |
26 | 29 | import org.apache.http.HttpHost; |
@@ -123,171 +126,140 @@ public void transform(TypeTransformer transformer) { |
123 | 126 | this.getClass().getName() + "$RequestWithHandlerAdvice"); |
124 | 127 | } |
125 | 128 |
|
126 | | - @SuppressWarnings("unused") |
127 | | - public static class UriRequestAdvice { |
| 129 | + public static class AdviceScope { |
| 130 | + private final ApacheHttpClientRequest otelRequest; |
| 131 | + private final Context parentContext; |
| 132 | + private final Context context; |
| 133 | + private final Scope scope; |
| 134 | + |
| 135 | + private AdviceScope( |
| 136 | + ApacheHttpClientRequest otelRequest, Context parentContext, Context context, Scope scope) { |
| 137 | + this.otelRequest = otelRequest; |
| 138 | + this.parentContext = parentContext; |
| 139 | + this.context = context; |
| 140 | + this.scope = scope; |
| 141 | + } |
128 | 142 |
|
129 | | - @Advice.OnMethodEnter(suppress = Throwable.class) |
130 | | - public static void methodEnter( |
131 | | - @Advice.Argument(0) HttpUriRequest request, |
132 | | - @Advice.Local("otelRequest") ApacheHttpClientRequest otelRequest, |
133 | | - @Advice.Local("otelContext") Context context, |
134 | | - @Advice.Local("otelScope") Scope scope) { |
| 143 | + @Nullable |
| 144 | + public static AdviceScope start(ApacheHttpClientRequest otelRequest) { |
135 | 145 | Context parentContext = currentContext(); |
136 | | - |
137 | | - otelRequest = new ApacheHttpClientRequest(request); |
138 | | - |
139 | 146 | if (!instrumenter().shouldStart(parentContext, otelRequest)) { |
140 | | - return; |
| 147 | + return null; |
141 | 148 | } |
142 | | - |
143 | | - context = instrumenter().start(parentContext, otelRequest); |
144 | | - scope = context.makeCurrent(); |
| 149 | + Context context = instrumenter().start(parentContext, otelRequest); |
| 150 | + return new AdviceScope(otelRequest, parentContext, context, context.makeCurrent()); |
145 | 151 | } |
146 | 152 |
|
147 | | - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) |
148 | | - public static void methodExit( |
149 | | - @Advice.Argument(0) HttpUriRequest request, |
150 | | - @Advice.Return Object result, |
151 | | - @Advice.Thrown Throwable throwable, |
152 | | - @Advice.Local("otelRequest") ApacheHttpClientRequest otelRequest, |
153 | | - @Advice.Local("otelContext") Context context, |
154 | | - @Advice.Local("otelScope") Scope scope) { |
155 | | - if (scope == null) { |
156 | | - return; |
157 | | - } |
| 153 | + public <T> ResponseHandler<T> wrapHandler(ResponseHandler<T> handler) { |
| 154 | + return new WrappingStatusSettingResponseHandler<>( |
| 155 | + context, parentContext, otelRequest, handler); |
| 156 | + } |
158 | 157 |
|
| 158 | + public void end(@Nullable Object result, @Nullable Throwable throwable) { |
159 | 159 | scope.close(); |
160 | 160 | ApacheHttpClientHelper.doMethodExit(context, otelRequest, result, throwable); |
161 | 161 | } |
162 | 162 | } |
163 | 163 |
|
164 | 164 | @SuppressWarnings("unused") |
165 | | - public static class UriRequestWithHandlerAdvice { |
| 165 | + public static class UriRequestAdvice { |
166 | 166 |
|
167 | 167 | @Advice.OnMethodEnter(suppress = Throwable.class) |
168 | | - public static void methodEnter( |
169 | | - @Advice.Argument(0) HttpUriRequest request, |
170 | | - @Advice.Argument(value = 1, readOnly = false) ResponseHandler<?> handler, |
171 | | - @Advice.Local("otelRequest") ApacheHttpClientRequest otelRequest, |
172 | | - @Advice.Local("otelContext") Context context, |
173 | | - @Advice.Local("otelScope") Scope scope) { |
174 | | - Context parentContext = currentContext(); |
| 168 | + public static AdviceScope methodEnter(@Advice.Argument(0) HttpUriRequest request) { |
| 169 | + return AdviceScope.start(new ApacheHttpClientRequest(request)); |
| 170 | + } |
175 | 171 |
|
176 | | - otelRequest = new ApacheHttpClientRequest(request); |
| 172 | + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) |
| 173 | + public static void methodExit( |
| 174 | + @Advice.Argument(0) HttpUriRequest request, |
| 175 | + @Advice.Return @Nullable Object result, |
| 176 | + @Advice.Thrown @Nullable Throwable throwable, |
| 177 | + @Advice.Enter @Nullable AdviceScope adviceScope) { |
177 | 178 |
|
178 | | - if (!instrumenter().shouldStart(parentContext, otelRequest)) { |
179 | | - return; |
| 179 | + if (adviceScope != null) { |
| 180 | + adviceScope.end(result, throwable); |
180 | 181 | } |
| 182 | + } |
| 183 | + } |
181 | 184 |
|
182 | | - context = instrumenter().start(parentContext, otelRequest); |
183 | | - scope = context.makeCurrent(); |
| 185 | + @SuppressWarnings("unused") |
| 186 | + public static class UriRequestWithHandlerAdvice { |
| 187 | + |
| 188 | + @AssignReturned.ToArguments(@ToArgument(value = 1, index = 1)) |
| 189 | + @Advice.OnMethodEnter(suppress = Throwable.class) |
| 190 | + public static Object[] methodEnter( |
| 191 | + @Advice.Argument(0) HttpUriRequest request, |
| 192 | + @Advice.Argument(1) ResponseHandler<?> handler) { |
184 | 193 |
|
| 194 | + AdviceScope adviceScope = AdviceScope.start(new ApacheHttpClientRequest(request)); |
185 | 195 | // Wrap the handler so we capture the status code |
186 | | - if (handler != null) { |
187 | | - handler = |
188 | | - new WrappingStatusSettingResponseHandler<>( |
189 | | - context, parentContext, otelRequest, handler); |
190 | | - } |
| 196 | + return new Object[] { |
| 197 | + adviceScope, adviceScope == null ? handler : adviceScope.wrapHandler(handler) |
| 198 | + }; |
191 | 199 | } |
192 | 200 |
|
193 | 201 | @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) |
194 | 202 | public static void methodExit( |
195 | | - @Advice.Argument(0) HttpUriRequest request, |
196 | 203 | @Advice.Return Object result, |
197 | 204 | @Advice.Thrown Throwable throwable, |
198 | | - @Advice.Local("otelRequest") ApacheHttpClientRequest otelRequest, |
199 | | - @Advice.Local("otelContext") Context context, |
200 | | - @Advice.Local("otelScope") Scope scope) { |
201 | | - if (scope == null) { |
202 | | - return; |
203 | | - } |
| 205 | + @Advice.Enter Object[] enterResult) { |
204 | 206 |
|
205 | | - scope.close(); |
206 | | - ApacheHttpClientHelper.doMethodExit(context, otelRequest, result, throwable); |
| 207 | + AdviceScope adviceScope = (AdviceScope) enterResult[0]; |
| 208 | + if (adviceScope != null) { |
| 209 | + adviceScope.end(result, throwable); |
| 210 | + } |
207 | 211 | } |
208 | 212 | } |
209 | 213 |
|
210 | 214 | @SuppressWarnings("unused") |
211 | 215 | public static class RequestAdvice { |
212 | 216 |
|
213 | 217 | @Advice.OnMethodEnter(suppress = Throwable.class) |
214 | | - public static void methodEnter( |
215 | | - @Advice.Argument(0) HttpHost host, |
216 | | - @Advice.Argument(1) HttpRequest request, |
217 | | - @Advice.Local("otelRequest") ApacheHttpClientRequest otelRequest, |
218 | | - @Advice.Local("otelContext") Context context, |
219 | | - @Advice.Local("otelScope") Scope scope) { |
220 | | - Context parentContext = currentContext(); |
221 | | - |
222 | | - otelRequest = new ApacheHttpClientRequest(host, request); |
223 | | - |
224 | | - if (!instrumenter().shouldStart(parentContext, otelRequest)) { |
225 | | - return; |
226 | | - } |
227 | | - |
228 | | - context = instrumenter().start(parentContext, otelRequest); |
229 | | - scope = context.makeCurrent(); |
| 218 | + public static AdviceScope methodEnter( |
| 219 | + @Advice.Argument(0) HttpHost host, @Advice.Argument(1) HttpRequest request) { |
| 220 | + return AdviceScope.start(new ApacheHttpClientRequest(host, request)); |
230 | 221 | } |
231 | 222 |
|
232 | 223 | @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) |
233 | 224 | public static void methodExit( |
234 | 225 | @Advice.Return Object result, |
235 | 226 | @Advice.Thrown Throwable throwable, |
236 | | - @Advice.Local("otelRequest") ApacheHttpClientRequest otelRequest, |
237 | | - @Advice.Local("otelContext") Context context, |
238 | | - @Advice.Local("otelScope") Scope scope) { |
239 | | - if (scope == null) { |
240 | | - return; |
241 | | - } |
| 227 | + @Advice.Enter AdviceScope adviceScope) { |
242 | 228 |
|
243 | | - scope.close(); |
244 | | - ApacheHttpClientHelper.doMethodExit(context, otelRequest, result, throwable); |
| 229 | + if (adviceScope != null) { |
| 230 | + adviceScope.end(result, throwable); |
| 231 | + } |
245 | 232 | } |
246 | 233 | } |
247 | 234 |
|
248 | 235 | @SuppressWarnings("unused") |
249 | 236 | public static class RequestWithHandlerAdvice { |
250 | 237 |
|
| 238 | + @AssignReturned.ToArguments(@ToArgument(value = 2, index = 1)) |
251 | 239 | @Advice.OnMethodEnter(suppress = Throwable.class) |
252 | | - public static void methodEnter( |
| 240 | + public static Object[] methodEnter( |
253 | 241 | @Advice.Argument(0) HttpHost host, |
254 | 242 | @Advice.Argument(1) HttpRequest request, |
255 | | - @Advice.Argument(value = 2, readOnly = false) ResponseHandler<?> handler, |
256 | | - @Advice.Local("otelRequest") ApacheHttpClientRequest otelRequest, |
257 | | - @Advice.Local("otelContext") Context context, |
258 | | - @Advice.Local("otelScope") Scope scope) { |
259 | | - Context parentContext = currentContext(); |
260 | | - |
261 | | - otelRequest = new ApacheHttpClientRequest(host, request); |
262 | | - |
263 | | - if (!instrumenter().shouldStart(parentContext, otelRequest)) { |
264 | | - return; |
265 | | - } |
266 | | - |
267 | | - context = instrumenter().start(parentContext, otelRequest); |
268 | | - scope = context.makeCurrent(); |
269 | | - |
270 | | - // Wrap the handler so we capture the status code |
271 | | - if (handler != null) { |
272 | | - handler = |
273 | | - new WrappingStatusSettingResponseHandler<>( |
274 | | - context, parentContext, otelRequest, handler); |
275 | | - } |
| 243 | + @Advice.Argument(2) ResponseHandler<?> handler) { |
| 244 | + |
| 245 | + AdviceScope adviceScope = AdviceScope.start(new ApacheHttpClientRequest(host, request)); |
| 246 | + return new Object[] { |
| 247 | + adviceScope, |
| 248 | + // Wrap the handler so we capture the status code |
| 249 | + adviceScope == null ? handler : adviceScope.wrapHandler(handler) |
| 250 | + }; |
276 | 251 | } |
277 | 252 |
|
278 | 253 | @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) |
279 | 254 | public static void methodExit( |
280 | 255 | @Advice.Return Object result, |
281 | 256 | @Advice.Thrown Throwable throwable, |
282 | | - @Advice.Local("otelRequest") ApacheHttpClientRequest otelRequest, |
283 | | - @Advice.Local("otelContext") Context context, |
284 | | - @Advice.Local("otelScope") Scope scope) { |
285 | | - if (scope == null) { |
286 | | - return; |
287 | | - } |
| 257 | + @Advice.Enter Object[] enterResult) { |
288 | 258 |
|
289 | | - scope.close(); |
290 | | - ApacheHttpClientHelper.doMethodExit(context, otelRequest, result, throwable); |
| 259 | + AdviceScope adviceScope = (AdviceScope) enterResult[0]; |
| 260 | + if (adviceScope != null) { |
| 261 | + adviceScope.end(result, throwable); |
| 262 | + } |
291 | 263 | } |
292 | 264 | } |
293 | 265 | } |
0 commit comments