From 4575011fa9073dd759b4bb95bb1d33d1e4d28699 Mon Sep 17 00:00:00 2001 From: Pavol Loffay Date: Wed, 9 Dec 2020 18:14:29 +0100 Subject: [PATCH 1/7] Support JAX-RS client typed entities - message body writer/reader Signed-off-by: Pavol Loffay --- .../JaxrsClientBodyInstrumentationTest.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java b/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java index 177297c15..89a2213c8 100644 --- a/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java +++ b/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java @@ -18,8 +18,14 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.sdk.trace.data.SpanData; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; import java.util.List; import java.util.concurrent.TimeoutException; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; @@ -28,6 +34,8 @@ import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.MessageBodyWriter; import org.hypertrace.agent.core.HypertraceSemanticAttributes; import org.hypertrace.agent.testing.AbstractInstrumenterTest; import org.hypertrace.agent.testing.TestHttpServer; @@ -99,6 +107,9 @@ public void postJson() throws TimeoutException, InterruptedException { ClientBuilder clientBuilder = ClientBuilder.newBuilder(); Client client = clientBuilder.build(); + MyDto myDto = new MyDto(); + myDto.name = "foo"; + Response response = client .target(String.format("http://localhost:%d/post", testHttpServer.port())) @@ -124,6 +135,39 @@ public void postJson() throws TimeoutException, InterruptedException { clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); } + @Test + public void postJsonDto() throws TimeoutException, InterruptedException { + ClientBuilder clientBuilder = ClientBuilder.newBuilder(); + Client client = clientBuilder.register(MyDtoMessageBodyWriter.class).build(); + + MyDto myDto = new MyDto(); + myDto.name = "name"; + + Response response = + client + .target(String.format("http://localhost:%d/post", testHttpServer.port())) + .request() + .header("test-request-header", "test-header-value") + .post(Entity.json(myDto)); + Assertions.assertEquals(204, response.getStatus()); + + TEST_WRITER.waitForTraces(1); + List> traces = TEST_WRITER.getTraces(); + Assertions.assertEquals(1, traces.size()); + Assertions.assertEquals(1, traces.get(0).size()); + SpanData clientSpan = traces.get(0).get(0); + + Assertions.assertEquals( + "test-value", + clientSpan + .getAttributes() + .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); + Assertions.assertEquals( + JSON, clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); + Assertions.assertNull( + clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + } + @Test public void postUrlEncoded() throws TimeoutException, InterruptedException { ClientBuilder clientBuilder = ClientBuilder.newBuilder(); @@ -154,4 +198,32 @@ public void postUrlEncoded() throws TimeoutException, InterruptedException { Assertions.assertNull( clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); } + + public static class MyDto { + public String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class MyDtoMessageBodyWriter implements MessageBodyWriter { + + @Override + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, + MediaType mediaType) { + return true; + } + + @Override + public void writeTo(MyDto myDto, Class type, Type genericType, Annotation[] annotations, + MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) + throws IOException, WebApplicationException { + entityStream.write(myDto.name.getBytes()); + } + } } From 35af73fec47f6ef94a1e4014870c08b8ace390e9 Mon Sep 17 00:00:00 2001 From: Pavol Loffay Date: Thu, 10 Dec 2020 12:37:04 +0100 Subject: [PATCH 2/7] working Signed-off-by: Pavol Loffay --- .../InputStreamInstrumentationModule.java | 12 ++- .../jaxrs-client-2.0/build.gradle.kts | 2 + .../v2_0/JaxrsClientBodyCaptureFilter.java | 45 +-------- .../v2_0/JaxrsClientEntityInterceptor.java | 94 +++++++++++++++---- .../JaxrsClientBodyInstrumentationTest.java | 29 +++--- .../agent/core/ContentLengthUtils.java | 12 +++ 6 files changed, 116 insertions(+), 78 deletions(-) diff --git a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/InputStreamInstrumentationModule.java b/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/InputStreamInstrumentationModule.java index e2deb95bb..890db6afe 100644 --- a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/InputStreamInstrumentationModule.java +++ b/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/InputStreamInstrumentationModule.java @@ -36,9 +36,19 @@ import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.hypertrace.agent.core.GlobalObjectRegistry; /** - * Maybe we could add optimization to instrument the input streams only when certain classes are + * {@link InputStream} instrumentation. The type matcher applies to all implementations. However + * only streams that are in the {@link GlobalObjectRegistry#inputStreamToSpanAndBufferMap} are + * instrumented, otherwise the instrumentation is noop. + * + *

If the stream is in the {@link GlobalObjectRegistry#inputStreamToSpanAndBufferMap} then result + * of read methods is also passed to the buffered stream (value) from the map. The instrumentation + * adds buffer to span from the map when read is finished (return -1), creates new span with buffer + * when the original span is not recording. + * + *

Maybe we could add optimization to instrument the input streams only when certain classes are * present in classloader e.g. classes from frameworks that we instrument. */ @AutoService(InstrumentationModule.class) diff --git a/instrumentation/jaxrs-client-2.0/build.gradle.kts b/instrumentation/jaxrs-client-2.0/build.gradle.kts index 905a84af0..92cf53aff 100644 --- a/instrumentation/jaxrs-client-2.0/build.gradle.kts +++ b/instrumentation/jaxrs-client-2.0/build.gradle.kts @@ -32,10 +32,12 @@ val versions: Map by extra dependencies { api("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-jaxrs-client-2.0-common:${versions["opentelemetry_java_agent"]}") + api(project(":instrumentation:apache-httpclient-4.0")) compileOnly("javax.ws.rs:javax.ws.rs-api:2.0.1") testImplementation(project(":testing-common")) testImplementation("org.glassfish.jersey.core:jersey-client:2.27") testImplementation("org.glassfish.jersey.inject:jersey-hk2:2.27") + } diff --git a/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyCaptureFilter.java b/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyCaptureFilter.java index 44fcaf99c..0ce2f8077 100644 --- a/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyCaptureFilter.java +++ b/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyCaptureFilter.java @@ -26,11 +26,8 @@ import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.client.ClientResponseContext; import javax.ws.rs.client.ClientResponseFilter; -import javax.ws.rs.core.Form; -import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import org.hypertrace.agent.config.Config.AgentConfig; -import org.hypertrace.agent.core.ContentTypeUtils; import org.hypertrace.agent.core.HypertraceConfig; import org.hypertrace.agent.core.HypertraceSemanticAttributes; import org.slf4j.Logger; @@ -57,28 +54,8 @@ public void filter(ClientRequestContext requestContext) { HypertraceSemanticAttributes::httpRequestHeader, requestContext.getStringHeaders()); } - if (requestContext.hasEntity() - && agentConfig.getDataCapture().getHttpBody().getRequest().getValue()) { - MediaType mediaType = requestContext.getMediaType(); - if (mediaType == null || !ContentTypeUtils.shouldCapture(mediaType.toString())) { - return; - } - - Object entity = requestContext.getEntity(); - if (entity != null) { - if (entity instanceof Form) { - Form form = (Form) entity; - String content = getUrlEncodedContent(form); - currentSpan.setAttribute(HypertraceSemanticAttributes.HTTP_REQUEST_BODY, content); - } else { - currentSpan.setAttribute( - HypertraceSemanticAttributes.HTTP_REQUEST_BODY, entity.toString()); - } - } - } - requestContext.getEntity(); } catch (Exception ex) { - log.error("Exception while getting request entity or headers", ex); + log.error("Exception while getting request headers", ex); } } @@ -100,26 +77,8 @@ public void filter(ClientRequestContext requestContext, ClientResponseContext re responseContext.getHeaders()); } } catch (Exception ex) { - log.error("Exception while getting response entity or headers", ex); - } - } - - private static String getUrlEncodedContent(Form form) { - MultivaluedMap formMap = form.asMap(); - StringBuilder sb = new StringBuilder(); - if (formMap != null) { - for (Map.Entry> entry : formMap.entrySet()) { - if (sb.length() > 0) { - sb.append("&"); - } - for (String value : entry.getValue()) { - sb.append(entry.getKey()); - sb.append("="); - sb.append(value); - } - } + log.error("Exception while getting response headers", ex); } - return sb.toString(); } private static void captureHeaders( diff --git a/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientEntityInterceptor.java b/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientEntityInterceptor.java index dde6e4555..7972fd644 100644 --- a/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientEntityInterceptor.java +++ b/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientEntityInterceptor.java @@ -19,60 +19,114 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0.ClientTracingFilter; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.ReaderInterceptor; import javax.ws.rs.ext.ReaderInterceptorContext; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; import org.hypertrace.agent.config.Config.AgentConfig; +import org.hypertrace.agent.core.ContentEncodingUtils; +import org.hypertrace.agent.core.ContentLengthUtils; import org.hypertrace.agent.core.ContentTypeUtils; +import org.hypertrace.agent.core.GlobalObjectRegistry; +import org.hypertrace.agent.core.GlobalObjectRegistry.SpanAndBuffer; import org.hypertrace.agent.core.HypertraceConfig; import org.hypertrace.agent.core.HypertraceSemanticAttributes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class JaxrsClientEntityInterceptor implements ReaderInterceptor { +public class JaxrsClientEntityInterceptor implements ReaderInterceptor, WriterInterceptor { private static final Logger log = LoggerFactory.getLogger(JaxrsClientEntityInterceptor.class); private static final Tracer TRACER = OpenTelemetry.getGlobalTracer("org.hypertrace.java.jaxrs.client"); + /** Writing response body to input stream */ @Override public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException { - Object entity = context.proceed(); + MediaType mediaType = context.getMediaType(); + AgentConfig agentConfig = HypertraceConfig.get(); + if (mediaType == null + || !ContentTypeUtils.shouldCapture(mediaType.toString()) + || !agentConfig.getDataCapture().getHttpBody().getResponse().getValue()) { + return context.proceed(); + } Object spanObj = context.getProperty(ClientTracingFilter.SPAN_PROPERTY_NAME); if (!(spanObj instanceof Span)) { log.error( "Span object is not present in the context properties, response object will not be captured"); - return entity; + return context.proceed(); } Span currentSpan = (Span) spanObj; - MediaType mediaType = context.getMediaType(); - AgentConfig agentConfig = HypertraceConfig.get(); - if (mediaType == null - || !ContentTypeUtils.shouldCapture(mediaType.toString()) - || !agentConfig.getDataCapture().getHttpBody().getResponse().getValue()) { - return entity; + InputStream entityStream = context.getInputStream(); + Object entity = null; + try { + String encodingStr = context.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING); + String contentLengthStr = context.getHeaders().getFirst(HttpHeaders.CONTENT_LENGTH); + int contentLength = ContentLengthUtils.parseLength(contentLengthStr); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(contentLength); + GlobalObjectRegistry.inputStreamToSpanAndBufferMap.put( + entityStream, + new SpanAndBuffer( + currentSpan, + buffer, + HypertraceSemanticAttributes.HTTP_RESPONSE_BODY, + ContentEncodingUtils.toCharset(encodingStr))); + entity = context.proceed(); + } catch (Exception ex) { + log.error("Exception while capturing response body", ex); + } + return entity; + } + + /** Writing request body to output stream */ + @Override + public void aroundWriteTo(WriterInterceptorContext context) + throws IOException, WebApplicationException { + + Object spanObj = context.getProperty(ClientTracingFilter.SPAN_PROPERTY_NAME); + if (!(spanObj instanceof Span)) { + log.error( + "Span object is not present in the context properties, request body will not be captured"); + context.proceed(); + return; } + Span currentSpan = (Span) spanObj; - if (currentSpan.isRecording()) { - currentSpan.setAttribute(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY, entity.toString()); - } else { - TRACER - .spanBuilder(HypertraceSemanticAttributes.ADDITIONAL_DATA_SPAN_NAME) - .setParent(Context.root().with(currentSpan)) - .setAttribute(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY, entity.toString()) - .startSpan() - .end(); + AgentConfig agentConfig = HypertraceConfig.get(); + if (agentConfig.getDataCapture().getHttpBody().getRequest().getValue()) { + MediaType mediaType = context.getMediaType(); + if (mediaType == null || !ContentTypeUtils.shouldCapture(mediaType.toString())) { + context.proceed(); + return; + } } - return entity; + // TODO length is not known + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + OutputStream entityStream = context.getOutputStream(); + try { + GlobalObjectRegistry.outputStreamToBufferMap.put(entityStream, buffer); + context.proceed(); + } catch (Exception ex) { + log.error("Failed to capture request body", ex); + } finally { + GlobalObjectRegistry.outputStreamToBufferMap.remove(entityStream); + // TODO encoding is not known + currentSpan.setAttribute(HypertraceSemanticAttributes.HTTP_REQUEST_BODY, buffer.toString()); + } } } diff --git a/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java b/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java index 89a2213c8..1992262ab 100644 --- a/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java +++ b/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java @@ -19,7 +19,6 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.sdk.trace.data.SpanData; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; @@ -34,7 +33,6 @@ import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; -import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import org.hypertrace.agent.core.HypertraceSemanticAttributes; import org.hypertrace.agent.testing.AbstractInstrumenterTest; @@ -163,7 +161,8 @@ public void postJsonDto() throws TimeoutException, InterruptedException { .getAttributes() .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); Assertions.assertEquals( - JSON, clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); + myDto.getJson(), + clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); Assertions.assertNull( clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); } @@ -202,28 +201,30 @@ public void postUrlEncoded() throws TimeoutException, InterruptedException { public static class MyDto { public String name; - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; + public String getJson() { + return "{name:\"" + name + "\"}"; } } public static class MyDtoMessageBodyWriter implements MessageBodyWriter { @Override - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, - MediaType mediaType) { + public boolean isWriteable( + Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return true; } @Override - public void writeTo(MyDto myDto, Class type, Type genericType, Annotation[] annotations, - MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) + public void writeTo( + MyDto myDto, + Class type, + Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap httpHeaders, + OutputStream entityStream) throws IOException, WebApplicationException { - entityStream.write(myDto.name.getBytes()); + entityStream.write((myDto.getJson()).getBytes()); } } } diff --git a/javaagent-core/src/main/java/org/hypertrace/agent/core/ContentLengthUtils.java b/javaagent-core/src/main/java/org/hypertrace/agent/core/ContentLengthUtils.java index b716ba97b..a01d92ee5 100644 --- a/javaagent-core/src/main/java/org/hypertrace/agent/core/ContentLengthUtils.java +++ b/javaagent-core/src/main/java/org/hypertrace/agent/core/ContentLengthUtils.java @@ -21,4 +21,16 @@ private ContentLengthUtils() {} // default content length public static final int DEFAULT = 128; + + public static int parseLength(String lengthStr) { + if (lengthStr == null || lengthStr.isEmpty()) { + return DEFAULT; + } + + try { + return Integer.parseInt(lengthStr); + } catch (Exception ex) { + return DEFAULT; + } + } } From c4043370c7bc4ab4de891c142f942c53b444e903 Mon Sep 17 00:00:00 2001 From: Pavol Loffay Date: Thu, 10 Dec 2020 12:46:58 +0100 Subject: [PATCH 3/7] Split modules Signed-off-by: Pavol Loffay --- .../apache-httpclient-4.0/build.gradle.kts | 4 +++- instrumentation/build.gradle.kts | 1 + instrumentation/java-streams/build.gradle.kts | 3 +++ .../InputStreamInstrumentationModule.java | 16 +++++++++++++++- .../java/inputstream}/InputStreamUtils.java | 16 +++++++++++++++- .../OutputStreamInstrumentationModule.java | 2 +- .../java/outputstream}/OutputStreamUtils.java | 2 +- .../jaxrs-client-2.0/build.gradle.kts | 3 +-- settings.gradle.kts | 2 ++ 9 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 instrumentation/java-streams/build.gradle.kts rename instrumentation/{apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0 => java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream}/InputStreamInstrumentationModule.java (78%) rename instrumentation/{apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0 => java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream}/InputStreamUtils.java (76%) rename instrumentation/{apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0 => java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/outputstream}/OutputStreamInstrumentationModule.java (98%) rename instrumentation/{apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0 => java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/outputstream}/OutputStreamUtils.java (97%) diff --git a/instrumentation/apache-httpclient-4.0/build.gradle.kts b/instrumentation/apache-httpclient-4.0/build.gradle.kts index 228ef49dc..8ee9760d4 100644 --- a/instrumentation/apache-httpclient-4.0/build.gradle.kts +++ b/instrumentation/apache-httpclient-4.0/build.gradle.kts @@ -39,8 +39,10 @@ afterEvaluate{ val versions: Map by extra dependencies { - implementation("org.apache.httpcomponents:httpclient:4.0") + api(project(":instrumentation:java-streams")) api("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-apache-httpclient-4.0:${versions["opentelemetry_java_agent"]}") + implementation("org.apache.httpcomponents:httpclient:4.0") + testImplementation(project(":testing-common")) } diff --git a/instrumentation/build.gradle.kts b/instrumentation/build.gradle.kts index 15ac6067c..03986600b 100644 --- a/instrumentation/build.gradle.kts +++ b/instrumentation/build.gradle.kts @@ -38,6 +38,7 @@ dependencies{ implementation(project(":instrumentation:okhttp:okhttp-3.0")) implementation(project(":instrumentation:apache-httpclient-4.0")) implementation(project(":instrumentation:jaxrs-client-2.0")) + implementation(project(":instrumentation:java-streams")) implementation(project(":otel-extensions")) } diff --git a/instrumentation/java-streams/build.gradle.kts b/instrumentation/java-streams/build.gradle.kts new file mode 100644 index 000000000..f6727627a --- /dev/null +++ b/instrumentation/java-streams/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + `java-library` +} diff --git a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/InputStreamInstrumentationModule.java b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamInstrumentationModule.java similarity index 78% rename from instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/InputStreamInstrumentationModule.java rename to instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamInstrumentationModule.java index 890db6afe..c9ad2da09 100644 --- a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/InputStreamInstrumentationModule.java +++ b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamInstrumentationModule.java @@ -14,7 +14,21 @@ * limitations under the License. */ -package io.opentelemetry.instrumentation.hypertrace.apachehttpclient.v4_0; +package io.opentelemetry.instrumentation.hypertrace.java.inputstream; /* + * Copyright The Hypertrace Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; diff --git a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/InputStreamUtils.java b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamUtils.java similarity index 76% rename from instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/InputStreamUtils.java rename to instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamUtils.java index df08103f6..5cd340516 100644 --- a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/InputStreamUtils.java +++ b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamUtils.java @@ -14,7 +14,21 @@ * limitations under the License. */ -package io.opentelemetry.instrumentation.hypertrace.apachehttpclient.v4_0; +package io.opentelemetry.instrumentation.hypertrace.java.inputstream; /* + * Copyright The Hypertrace Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.AttributeKey; diff --git a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/OutputStreamInstrumentationModule.java b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/outputstream/OutputStreamInstrumentationModule.java similarity index 98% rename from instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/OutputStreamInstrumentationModule.java rename to instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/outputstream/OutputStreamInstrumentationModule.java index fae7dad24..eaede9d8d 100644 --- a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/OutputStreamInstrumentationModule.java +++ b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/outputstream/OutputStreamInstrumentationModule.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.opentelemetry.instrumentation.hypertrace.apachehttpclient.v4_0; +package io.opentelemetry.instrumentation.hypertrace.java.outputstream; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; diff --git a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/OutputStreamUtils.java b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/outputstream/OutputStreamUtils.java similarity index 97% rename from instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/OutputStreamUtils.java rename to instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/outputstream/OutputStreamUtils.java index 93b3dbffc..a9d055e9f 100644 --- a/instrumentation/apache-httpclient-4.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/apachehttpclient/v4_0/OutputStreamUtils.java +++ b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/outputstream/OutputStreamUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.opentelemetry.instrumentation.hypertrace.apachehttpclient.v4_0; +package io.opentelemetry.instrumentation.hypertrace.java.outputstream; import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import java.io.IOException; diff --git a/instrumentation/jaxrs-client-2.0/build.gradle.kts b/instrumentation/jaxrs-client-2.0/build.gradle.kts index 92cf53aff..cc2098c45 100644 --- a/instrumentation/jaxrs-client-2.0/build.gradle.kts +++ b/instrumentation/jaxrs-client-2.0/build.gradle.kts @@ -31,13 +31,12 @@ afterEvaluate{ val versions: Map by extra dependencies { + api(project(":instrumentation:java-streams")) api("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-jaxrs-client-2.0-common:${versions["opentelemetry_java_agent"]}") - api(project(":instrumentation:apache-httpclient-4.0")) compileOnly("javax.ws.rs:javax.ws.rs-api:2.0.1") testImplementation(project(":testing-common")) testImplementation("org.glassfish.jersey.core:jersey-client:2.27") testImplementation("org.glassfish.jersey.inject:jersey-hk2:2.27") - } diff --git a/settings.gradle.kts b/settings.gradle.kts index f74f4b1a9..720536261 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -41,3 +41,5 @@ include("otel-extensions") include("testing-bootstrap") include("instrumentation:jaxrs-client-2.0") findProject(":instrumentation:jaxrs-client-2.0")?.name = "jaxrs-client-2.0" +include("instrumentation:java-streams") +findProject(":instrumentation:java-streams")?.name = "java-streams" From f32eb938adb9d31410984dddf5a799fdd6362018 Mon Sep 17 00:00:00 2001 From: Pavol Loffay Date: Thu, 10 Dec 2020 13:13:41 +0100 Subject: [PATCH 4/7] Add muzzle Signed-off-by: Pavol Loffay --- instrumentation/java-streams/build.gradle.kts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/instrumentation/java-streams/build.gradle.kts b/instrumentation/java-streams/build.gradle.kts index f6727627a..49519b887 100644 --- a/instrumentation/java-streams/build.gradle.kts +++ b/instrumentation/java-streams/build.gradle.kts @@ -1,3 +1,12 @@ plugins { `java-library` + id("net.bytebuddy.byte-buddy") +} + +afterEvaluate{ + io.opentelemetry.instrumentation.gradle.bytebuddy.ByteBuddyPluginConfigurator(project, + sourceSets.main.get(), + "io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCodeGenerationPlugin", + project(":javaagent-tooling").configurations["instrumentationMuzzle"] + configurations.runtimeClasspath + ).configure() } From 38c48efc52ed6ab1ab50ca2b734c95abc5983889 Mon Sep 17 00:00:00 2001 From: Pavol Loffay Date: Thu, 10 Dec 2020 13:17:06 +0100 Subject: [PATCH 5/7] Add comment Signed-off-by: Pavol Loffay --- .../jaxrs/v2_0/JaxrsClientEntityInterceptor.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientEntityInterceptor.java b/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientEntityInterceptor.java index 7972fd644..8663005d8 100644 --- a/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientEntityInterceptor.java +++ b/instrumentation/jaxrs-client-2.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientEntityInterceptor.java @@ -16,9 +16,7 @@ package io.opentelemetry.instrumentation.hypertrace.jaxrs.v2_0; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0.ClientTracingFilter; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -46,9 +44,6 @@ public class JaxrsClientEntityInterceptor implements ReaderInterceptor, WriterIn private static final Logger log = LoggerFactory.getLogger(JaxrsClientEntityInterceptor.class); - private static final Tracer TRACER = - OpenTelemetry.getGlobalTracer("org.hypertrace.java.jaxrs.client"); - /** Writing response body to input stream */ @Override public Object aroundReadFrom(ReaderInterceptorContext context) @@ -70,6 +65,10 @@ public Object aroundReadFrom(ReaderInterceptorContext context) } Span currentSpan = (Span) spanObj; + // TODO as optimization the type could be checked here and if it is a primitive type e.g. String + // it could be read directly. + // context.getType(); + InputStream entityStream = context.getInputStream(); Object entity = null; try { From 3cacecec69e42525ddfb73b0703612a4c803f98a Mon Sep 17 00:00:00 2001 From: Pavol Loffay Date: Thu, 10 Dec 2020 13:18:47 +0100 Subject: [PATCH 6/7] Remove wrong license Signed-off-by: Pavol Loffay --- .../InputStreamInstrumentationModule.java | 16 +--------------- .../java/inputstream/InputStreamUtils.java | 16 +--------------- 2 files changed, 2 insertions(+), 30 deletions(-) diff --git a/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamInstrumentationModule.java b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamInstrumentationModule.java index c9ad2da09..fbb331526 100644 --- a/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamInstrumentationModule.java +++ b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamInstrumentationModule.java @@ -14,21 +14,7 @@ * limitations under the License. */ -package io.opentelemetry.instrumentation.hypertrace.java.inputstream; /* - * Copyright The Hypertrace Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +package io.opentelemetry.instrumentation.hypertrace.java.inputstream; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; diff --git a/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamUtils.java b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamUtils.java index 5cd340516..cb806dca8 100644 --- a/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamUtils.java +++ b/instrumentation/java-streams/src/main/java/io/opentelemetry/instrumentation/hypertrace/java/inputstream/InputStreamUtils.java @@ -14,21 +14,7 @@ * limitations under the License. */ -package io.opentelemetry.instrumentation.hypertrace.java.inputstream; /* - * Copyright The Hypertrace Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +package io.opentelemetry.instrumentation.hypertrace.java.inputstream; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.AttributeKey; From 860674cbde9a556dd779614380d2a40b67a23542 Mon Sep 17 00:00:00 2001 From: Pavol Loffay Date: Thu, 10 Dec 2020 13:34:59 +0100 Subject: [PATCH 7/7] Fix muzzle Signed-off-by: Pavol Loffay --- instrumentation/jaxrs-client-2.0/build.gradle.kts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/jaxrs-client-2.0/build.gradle.kts b/instrumentation/jaxrs-client-2.0/build.gradle.kts index cc2098c45..0a6ab7301 100644 --- a/instrumentation/jaxrs-client-2.0/build.gradle.kts +++ b/instrumentation/jaxrs-client-2.0/build.gradle.kts @@ -16,7 +16,8 @@ muzzle { group = "io.dropwizard" module = "dropwizard-client" versions = "[0.8.0,)" - assertInverse = true + // TODO this is set in OTEL +// assertInverse = true } }