From cf34e48f566ca7614d1e65303a107ee9a7616518 Mon Sep 17 00:00:00 2001 From: Jose Montoya Date: Wed, 29 Jul 2020 04:10:12 -0500 Subject: [PATCH 1/4] opentracing: fixes header extraction --- .../opentelemetry/OpenTelemetryTracer.java | 4 +- components/camel-opentracing/pom.xml | 22 +++++ .../camel/opentracing/OpenTracingTracer.java | 36 ++++++-- .../CamelOpenTracingTestSupport.java | 2 +- .../integration/InterprocessTest.java | 91 +++++++++++++++++++ .../java/org/apache/camel/tracing/Tracer.java | 10 +- 6 files changed, 149 insertions(+), 16 deletions(-) create mode 100644 components/camel-opentracing/src/test/java/org/apache/camel/opentracing/integration/InterprocessTest.java diff --git a/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java b/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java index 3decb8f403e4f..2adc5c2c39987 100644 --- a/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java +++ b/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java @@ -23,10 +23,12 @@ import io.opentelemetry.trace.DefaultTracer; import io.opentelemetry.trace.Span; import io.opentelemetry.trace.Tracer; +import org.apache.camel.Exchange; import org.apache.camel.api.management.ManagedResource; import org.apache.camel.opentelemetry.propagators.OpenTelemetrySetter; import org.apache.camel.tracing.InjectAdapter; import org.apache.camel.tracing.SpanAdapter; +import org.apache.camel.tracing.SpanDecorator; import org.apache.camel.tracing.SpanKind; @ManagedResource(description = "OpenTelemetryTracer") @@ -76,7 +78,7 @@ protected SpanAdapter startSendingEventSpan(String operationName, SpanKind kind, } @Override - protected SpanAdapter startExchangeBeginSpan(String operationName, SpanKind kind, SpanAdapter parent) { + protected SpanAdapter startExchangeBeginSpan(Exchange exchange, SpanDecorator sd, String operationName, SpanKind kind, SpanAdapter parent) { Span.Builder builder = tracer.spanBuilder(operationName); if (parent != null) { OpenTelemetrySpanAdapter oTelSpanWrapper = (OpenTelemetrySpanAdapter) parent; diff --git a/components/camel-opentracing/pom.xml b/components/camel-opentracing/pom.xml index f8907963a419b..2a4d6c5a42fdc 100644 --- a/components/camel-opentracing/pom.xml +++ b/components/camel-opentracing/pom.xml @@ -94,6 +94,28 @@ test test-jar + + org.apache.camel + camel-http + test + + + org.apache.camel + camel-jetty + test + + + org.glassfish.grizzly + grizzly-http-client + 1.16 + test + + + io.opentracing.contrib + opentracing-grizzly-ahc + 0.1.3 + test + org.apache.camel camel-test-spring-junit5 diff --git a/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingTracer.java b/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingTracer.java index c15efced145c9..1001d5d1aa849 100644 --- a/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingTracer.java +++ b/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingTracer.java @@ -18,6 +18,8 @@ import java.util.Set; +import io.opentracing.Span; +import io.opentracing.SpanContext; import io.opentracing.Tracer; import io.opentracing.Tracer.SpanBuilder; import io.opentracing.contrib.tracerresolver.TracerResolver; @@ -29,7 +31,9 @@ import org.apache.camel.spi.RoutePolicy; import org.apache.camel.tracing.InjectAdapter; import org.apache.camel.tracing.SpanAdapter; +import org.apache.camel.tracing.SpanDecorator; import org.apache.camel.tracing.SpanKind; +import org.apache.camel.tracing.decorators.AbstractInternalSpanDecorator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,10 +59,13 @@ public OpenTracingTracer() { } private String mapToSpanKind(SpanKind kind) { - if (kind == SpanKind.SPAN_KIND_CLIENT) { - return Tags.SPAN_KIND_CLIENT; + switch (kind) { + case SPAN_KIND_CLIENT: return Tags.SPAN_KIND_CLIENT; + case SPAN_KIND_SERVER: return Tags.SPAN_KIND_SERVER; + case CONSUMER: return Tags.SPAN_KIND_CONSUMER; + case PRODUCER: return Tags.SPAN_KIND_PRODUCER; + default: return null; } - return Tags.SPAN_KIND_SERVER; } @@ -97,12 +104,27 @@ protected void initTracer() { return new OpenTracingSpanAdapter(spanBuilder.start()); } - @Override protected SpanAdapter startExchangeBeginSpan(String operationName, SpanKind kind, SpanAdapter parent) { - SpanBuilder spanBuilder = tracer.buildSpan(operationName); + @Override protected SpanAdapter startExchangeBeginSpan(Exchange exchange, SpanDecorator sd, String operationName, SpanKind kind, SpanAdapter parent) { + SpanBuilder builder = tracer.buildSpan(operationName); if (parent != null) { - spanBuilder.asChildOf(((OpenTracingSpanAdapter) parent).getOpenTracingSpan()); + // we found a Span already associated with this exchange, use it as parent + Span parentFromExchange = ((OpenTracingSpanAdapter) parent).getOpenTracingSpan(); + builder.asChildOf(parentFromExchange); + } else { + SpanContext parentFromHeaders = tracer.extract(Format.Builtin.TEXT_MAP, new OpenTracingExtractAdapter(sd.getExtractAdapter(exchange.getIn().getHeaders(), encoding))); + + if (parentFromHeaders != null) { + // this means it's an inter-process request or the context was manually injected into the headers + // we add the server tag + builder.asChildOf(parentFromHeaders).withTag(Tags.SPAN_KIND.getKey(), mapToSpanKind(sd.getReceiverSpanKind())); + } else if (!(sd instanceof AbstractInternalSpanDecorator)) { + // no parent found anywhere and it's not an internal endpoint + // we add the server tag + builder.withTag(Tags.SPAN_KIND.getKey(), mapToSpanKind(sd.getReceiverSpanKind())); + } } - return new OpenTracingSpanAdapter(spanBuilder.start()); + + return new OpenTracingSpanAdapter(builder.start()); } public Tracer getTracer() { diff --git a/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/CamelOpenTracingTestSupport.java b/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/CamelOpenTracingTestSupport.java index a6c3a88e69e60..c13ca57cdfab8 100644 --- a/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/CamelOpenTracingTestSupport.java +++ b/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/CamelOpenTracingTestSupport.java @@ -162,7 +162,7 @@ protected void verifySpan(int index, SpanTestData[] testdata, List spa if (!td.getTags().isEmpty()) { for (Map.Entry entry : td.getTags().entrySet()) { - assertEquals(entry.getValue(), span.tags().get(entry.getKey())); + assertEquals(entry.getValue(), String.valueOf(span.tags().get(entry.getKey()))); } } diff --git a/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/integration/InterprocessTest.java b/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/integration/InterprocessTest.java new file mode 100644 index 0000000000000..4ad27aa063b42 --- /dev/null +++ b/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/integration/InterprocessTest.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.opentracing.integration; + + +import com.ning.http.client.AsyncHttpClient; +import com.ning.http.client.AsyncHttpClientConfig; +import io.opentracing.contrib.grizzly.ahc.TracingRequestFilter; +import io.opentracing.tag.Tags; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.opentracing.CamelOpenTracingTestSupport; +import org.apache.camel.opentracing.SpanTestData; +import org.apache.camel.test.AvailablePortFinder; +import org.junit.jupiter.api.Test; + + +public class InterprocessTest extends CamelOpenTracingTestSupport { + private static final String URL = "http://localhost:" + AvailablePortFinder.getNextAvailable() + "/test"; + private static final String URI = "jetty:" + URL; + + private static SpanTestData[] testdata = { + new SpanTestData().setLabel("jetty:start server").setUri(URI).setOperation("GET") + .setKind("server") + .addTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER) + .addTag(Tags.COMPONENT.getKey(), "camel-jetty") + .addTag(Tags.HTTP_URL.getKey(), URL) + .addTag(Tags.HTTP_METHOD.getKey(), "GET") + // jetty does not set the http response code header + // this is where instrumentation has value + // .addTag(Tags.HTTP_STATUS.getKey(), "200") + .setParentId(1), + new SpanTestData().setLabel("ahc: client").setUri(null).setOperation("HTTP::GET") + .setKind("client") + .addTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT) + .addTag(Tags.COMPONENT.getKey(), "java-grizzly-ahc") + .addTag(Tags.HTTP_URL.getKey(), URL) + .addTag(Tags.HTTP_METHOD.getKey(), "GET") + .addTag(Tags.HTTP_STATUS.getKey(), "200") + }; + + public InterprocessTest() { + super(testdata); + } + + @Test + public void testBridgeEndpoint() throws Exception { + AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder() + .addRequestFilter(new TracingRequestFilter(getTracer())) + .build(); + + try (AsyncHttpClient client = new AsyncHttpClient(config)) { + client.prepareGet(URL).execute().get(); + } + + verify(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + Processor serviceProc = new Processor() { + public void process(Exchange exchange) throws Exception { + // get the request URL and copy it to the request body + String uri = exchange.getIn().getHeader(Exchange.HTTP_URI, String.class); + exchange.getMessage().setBody(uri); + } + }; + + from(URI).process(serviceProc); + } + }; + } +} diff --git a/components/camel-tracing/src/main/java/org/apache/camel/tracing/Tracer.java b/components/camel-tracing/src/main/java/org/apache/camel/tracing/Tracer.java index 116aa67caf786..ada33b2236e6c 100644 --- a/components/camel-tracing/src/main/java/org/apache/camel/tracing/Tracer.java +++ b/components/camel-tracing/src/main/java/org/apache/camel/tracing/Tracer.java @@ -71,14 +71,14 @@ public abstract class Tracer extends ServiceSupport implements RoutePolicyFactor private final TracingEventNotifier eventNotifier = new TracingEventNotifier(); private Set excludePatterns = new HashSet<>(0); private InterceptStrategy tracingStrategy; - private boolean encoding; + protected boolean encoding; private CamelContext camelContext; protected abstract void initTracer(); protected abstract SpanAdapter startSendingEventSpan(String operationName, SpanKind kind, SpanAdapter parent); - protected abstract SpanAdapter startExchangeBeginSpan(String operationName, SpanKind kind, SpanAdapter parent); + protected abstract SpanAdapter startExchangeBeginSpan(Exchange exchange, SpanDecorator sd, String operationName, SpanKind kind, SpanAdapter parent); protected abstract void finishSpan(SpanAdapter span); @@ -283,11 +283,7 @@ public void onExchangeBegin(Route route, Exchange exchange) { SpanDecorator sd = getSpanDecorator(route.getEndpoint()); SpanAdapter parent = ActiveSpanManager.getSpan(exchange); SpanAdapter span; - if (parent == null && !(sd instanceof AbstractInternalSpanDecorator)) { - span = startExchangeBeginSpan(sd.getOperationName(exchange, route.getEndpoint()), sd.getReceiverSpanKind(), null); - } else { - span = startExchangeBeginSpan(sd.getOperationName(exchange, route.getEndpoint()), null, parent); - } + span = startExchangeBeginSpan(exchange, sd, sd.getOperationName(exchange, route.getEndpoint()), sd.getReceiverSpanKind(), parent); sd.pre(span, exchange, route.getEndpoint()); ActiveSpanManager.activate(exchange, span); if (LOG.isTraceEnabled()) { From b0f3d5c43b66896caa61248926672d3871ada8c9 Mon Sep 17 00:00:00 2001 From: Jose Montoya Date: Wed, 29 Jul 2020 04:54:01 -0500 Subject: [PATCH 2/4] opentracing: fixes tests --- .../apache/camel/opentracing/EIPTracingActiveSpanTest.java | 6 +++--- .../opentracing/OpentracingSpanCollectorInRegistryTest.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/EIPTracingActiveSpanTest.java b/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/EIPTracingActiveSpanTest.java index 35867577a0724..0988c961f0693 100644 --- a/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/EIPTracingActiveSpanTest.java +++ b/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/EIPTracingActiveSpanTest.java @@ -24,8 +24,8 @@ import org.apache.camel.RoutesBuilder; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.spi.InterceptStrategy; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; public class EIPTracingActiveSpanTest extends CamelOpenTracingTestSupport { @@ -41,8 +41,8 @@ public EIPTracingActiveSpanTest() { super(testdata); } - @BeforeAll - public void setUp() throws Exception { + @Override + public void doPreSetup() { GlobalTracerTestUtil.resetGlobalTracer(); } diff --git a/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/OpentracingSpanCollectorInRegistryTest.java b/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/OpentracingSpanCollectorInRegistryTest.java index e9dcfc9897c8e..175fa24d7b48d 100644 --- a/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/OpentracingSpanCollectorInRegistryTest.java +++ b/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/OpentracingSpanCollectorInRegistryTest.java @@ -22,8 +22,8 @@ import org.apache.camel.BindToRegistry; import org.apache.camel.CamelContext; import org.apache.camel.test.junit5.CamelTestSupport; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -34,8 +34,8 @@ public class OpentracingSpanCollectorInRegistryTest extends CamelTestSupport { @BindToRegistry("tracer") private NoopTracer c = NoopTracerFactory.create(); - @BeforeAll - public void setUp() throws Exception { + @Override + public void doPreSetup() { GlobalTracerTestUtil.resetGlobalTracer(); } From 3944817b6f06826e448f725062bde4284e41a2eb Mon Sep 17 00:00:00 2001 From: Jose Montoya Date: Wed, 29 Jul 2020 04:58:46 -0500 Subject: [PATCH 3/4] opentelemetry: fixes header extraction --- .../opentelemetry/OpenTelemetryTracer.java | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java b/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java index 2adc5c2c39987..e4421e86238c3 100644 --- a/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java +++ b/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java @@ -20,16 +20,18 @@ import io.grpc.Context; import io.opentelemetry.OpenTelemetry; -import io.opentelemetry.trace.DefaultTracer; -import io.opentelemetry.trace.Span; -import io.opentelemetry.trace.Tracer; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.DefaultContextPropagators; +import io.opentelemetry.trace.*; import org.apache.camel.Exchange; import org.apache.camel.api.management.ManagedResource; +import org.apache.camel.opentelemetry.propagators.OpenTelemetryGetter; import org.apache.camel.opentelemetry.propagators.OpenTelemetrySetter; import org.apache.camel.tracing.InjectAdapter; import org.apache.camel.tracing.SpanAdapter; import org.apache.camel.tracing.SpanDecorator; import org.apache.camel.tracing.SpanKind; +import org.apache.camel.tracing.decorators.AbstractInternalSpanDecorator; @ManagedResource(description = "OpenTelemetryTracer") public class OpenTelemetryTracer extends org.apache.camel.tracing.Tracer { @@ -45,10 +47,13 @@ public void setTracer(Tracer tracer) { } private Span.Kind mapToSpanKind(SpanKind kind) { - if (kind == SpanKind.SPAN_KIND_CLIENT) { - return Span.Kind.CLIENT; + switch (kind) { + case SPAN_KIND_CLIENT: return Span.Kind.CLIENT; + case SPAN_KIND_SERVER: return Span.Kind.SERVER; + case CONSUMER: return Span.Kind.CONSUMER; + case PRODUCER: return Span.Kind.PRODUCER; + default: return Span.Kind.SERVER; } - return Span.Kind.SERVER; } @Override @@ -81,8 +86,18 @@ protected SpanAdapter startSendingEventSpan(String operationName, SpanKind kind, protected SpanAdapter startExchangeBeginSpan(Exchange exchange, SpanDecorator sd, String operationName, SpanKind kind, SpanAdapter parent) { Span.Builder builder = tracer.spanBuilder(operationName); if (parent != null) { - OpenTelemetrySpanAdapter oTelSpanWrapper = (OpenTelemetrySpanAdapter) parent; - builder = builder.setParent(((OpenTelemetrySpanAdapter) parent).getOpenTelemetrySpan()); + OpenTelemetrySpanAdapter spanFromExchange = (OpenTelemetrySpanAdapter) parent; + builder = builder.setParent((spanFromExchange).getOpenTelemetrySpan()); + } else { + Context ctx = OpenTelemetry.getPropagators().getHttpTextFormat().extract(Context.current(), sd.getExtractAdapter(exchange.getIn().getHeaders(), encoding), new OpenTelemetryGetter()); + Span span = TracingContextUtils.getSpan(ctx); + SpanContext parentFromHeaders = span.getContext(); + + if (parentFromHeaders != null && parentFromHeaders.isValid()) { + builder.setParent(parentFromHeaders).setSpanKind(mapToSpanKind(sd.getReceiverSpanKind())); + } else if (!(sd instanceof AbstractInternalSpanDecorator)) { + builder.setSpanKind(mapToSpanKind(sd.getReceiverSpanKind())); + } } return new OpenTelemetrySpanAdapter(builder.startSpan()); From 0ecce91f2dfa8bb1e03644638200ff770787ca07 Mon Sep 17 00:00:00 2001 From: Jose Montoya Date: Wed, 29 Jul 2020 05:02:40 -0500 Subject: [PATCH 4/4] checkstyle --- .../camel/opentelemetry/OpenTelemetryTracer.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java b/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java index e4421e86238c3..2ef3699bcd357 100644 --- a/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java +++ b/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetryTracer.java @@ -20,9 +20,11 @@ import io.grpc.Context; import io.opentelemetry.OpenTelemetry; -import io.opentelemetry.context.propagation.ContextPropagators; -import io.opentelemetry.context.propagation.DefaultContextPropagators; -import io.opentelemetry.trace.*; +import io.opentelemetry.trace.DefaultTracer; +import io.opentelemetry.trace.Span; +import io.opentelemetry.trace.SpanContext; +import io.opentelemetry.trace.Tracer; +import io.opentelemetry.trace.TracingContextUtils; import org.apache.camel.Exchange; import org.apache.camel.api.management.ManagedResource; import org.apache.camel.opentelemetry.propagators.OpenTelemetryGetter; @@ -87,7 +89,7 @@ protected SpanAdapter startExchangeBeginSpan(Exchange exchange, SpanDecorator sd Span.Builder builder = tracer.spanBuilder(operationName); if (parent != null) { OpenTelemetrySpanAdapter spanFromExchange = (OpenTelemetrySpanAdapter) parent; - builder = builder.setParent((spanFromExchange).getOpenTelemetrySpan()); + builder = builder.setParent(spanFromExchange.getOpenTelemetrySpan()); } else { Context ctx = OpenTelemetry.getPropagators().getHttpTextFormat().extract(Context.current(), sd.getExtractAdapter(exchange.getIn().getHeaders(), encoding), new OpenTelemetryGetter()); Span span = TracingContextUtils.getSpan(ctx);