diff --git a/instrumentation/apache-camel-2.20/javaagent/build.gradle.kts b/instrumentation/apache-camel-2.20/javaagent/build.gradle.kts index b04506082480..447934789251 100644 --- a/instrumentation/apache-camel-2.20/javaagent/build.gradle.kts +++ b/instrumentation/apache-camel-2.20/javaagent/build.gradle.kts @@ -24,6 +24,9 @@ dependencies { // which has jaxb class-level annotations compileOnly("javax.xml.bind:jaxb-api:2.3.1") + compileOnly("com.google.auto.value:auto-value-annotations") + annotationProcessor("com.google.auto.value:auto-value") + testInstrumentation(project(":instrumentation:apache-httpclient:apache-httpclient-2.0:javaagent")) testInstrumentation(project(":instrumentation:servlet:servlet-3.0:javaagent")) testInstrumentation(project(":instrumentation:aws-sdk:aws-sdk-1.11:javaagent")) diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ActiveContextManager.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ActiveContextManager.java new file mode 100644 index 000000000000..b3e128ea5c1c --- /dev/null +++ b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ActiveContextManager.java @@ -0,0 +1,117 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +// Includes work from: +/* + * Apache Camel Opentracing Component + * + * 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 io.opentelemetry.javaagent.instrumentation.apachecamel; + +import static io.opentelemetry.javaagent.instrumentation.apachecamel.CamelSingletons.instrumenter; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import javax.annotation.Nullable; +import org.apache.camel.Exchange; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Utility class for managing active contexts as a stack associated with an exchange. */ +class ActiveContextManager { + + private static final String ACTIVE_CONTEXT_PROPERTY = "OpenTelemetry.activeContext"; + + private static final Logger logger = LoggerFactory.getLogger(ActiveContextManager.class); + + private ActiveContextManager() {} + + /** + * This method activates the supplied context for the supplied exchange. If an existing context is + * found for the exchange it will be pushed onto a stack. + * + * @param context The exchange + * @param request The context + */ + public static void activate(Context context, CamelRequest request) { + Exchange exchange = request.getExchange(); + ContextWithScope parent = exchange.getProperty(ACTIVE_CONTEXT_PROPERTY, ContextWithScope.class); + ContextWithScope contextWithScope = ContextWithScope.activate(parent, context, request); + exchange.setProperty(ACTIVE_CONTEXT_PROPERTY, contextWithScope); + logger.debug("Activated a span: {}", contextWithScope); + } + + /** + * This method deactivates an existing active context associated with the supplied exchange. Once + * deactivated, if a parent span is found associated with the stack for the exchange, it will be + * restored as the current span for the exchange. + * + * @param exchange The exchange + */ + public static Context deactivate(Exchange exchange) { + ContextWithScope contextWithScope = + exchange.getProperty(ACTIVE_CONTEXT_PROPERTY, ContextWithScope.class); + + if (contextWithScope != null) { + contextWithScope.deactivate(exchange.getException()); + exchange.setProperty(ACTIVE_CONTEXT_PROPERTY, contextWithScope.getParent()); + logger.debug("Deactivated span: {}", contextWithScope); + return contextWithScope.context; + } + + return null; + } + + private static class ContextWithScope { + @Nullable private final ContextWithScope parent; + @Nullable private final Context context; + private final CamelRequest request; + @Nullable private final Scope scope; + + public ContextWithScope( + ContextWithScope parent, Context context, CamelRequest request, Scope scope) { + this.parent = parent; + this.context = context; + this.request = request; + this.scope = scope; + } + + public static ContextWithScope activate( + ContextWithScope parent, Context context, CamelRequest request) { + Scope scope = context != null ? context.makeCurrent() : null; + return new ContextWithScope(parent, context, request, scope); + } + + public ContextWithScope getParent() { + return parent; + } + + public void deactivate(Exception exception) { + if (scope == null) { + return; + } + scope.close(); + instrumenter().end(context, request, null, exception); + } + + @Override + public String toString() { + return "ContextWithScope [context=" + context + ", scope=" + scope + "]"; + } + } +} diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ActiveSpanManager.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ActiveSpanManager.java deleted file mode 100644 index 242ce34d0fff..000000000000 --- a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ActiveSpanManager.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * 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 io.opentelemetry.javaagent.instrumentation.apachecamel; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.context.Scope; -import javax.annotation.Nullable; -import org.apache.camel.Exchange; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** Utility class for managing active spans as a stack associated with an exchange. */ -class ActiveSpanManager { - - private static final String ACTIVE_SPAN_PROPERTY = "OpenTelemetry.activeSpan"; - - private static final Logger logger = LoggerFactory.getLogger(ActiveSpanManager.class); - - private ActiveSpanManager() {} - - public static Span getSpan(Exchange exchange) { - SpanWithScope spanWithScope = exchange.getProperty(ACTIVE_SPAN_PROPERTY, SpanWithScope.class); - if (spanWithScope != null) { - return spanWithScope.getSpan(); - } - return null; - } - - /** - * This method activates the supplied span for the supplied exchange. If an existing span is found - * for the exchange, this will be pushed onto a stack. - * - * @param exchange The exchange - * @param span The span - */ - public static void activate(Exchange exchange, Span span, SpanKind spanKind) { - - SpanWithScope parent = exchange.getProperty(ACTIVE_SPAN_PROPERTY, SpanWithScope.class); - SpanWithScope spanWithScope = SpanWithScope.activate(span, parent, spanKind); - exchange.setProperty(ACTIVE_SPAN_PROPERTY, spanWithScope); - logger.debug("Activated a span: {}", spanWithScope); - } - - /** - * This method deactivates an existing active span associated with the supplied exchange. Once - * deactivated, if a parent span is found associated with the stack for the exchange, it will be - * restored as the current span for that exchange. - * - * @param exchange The exchange - */ - public static void deactivate(Exchange exchange) { - - SpanWithScope spanWithScope = exchange.getProperty(ACTIVE_SPAN_PROPERTY, SpanWithScope.class); - - if (spanWithScope != null) { - spanWithScope.deactivate(); - exchange.setProperty(ACTIVE_SPAN_PROPERTY, spanWithScope.getParent()); - logger.debug("Deactivated span: {}", spanWithScope); - } - } - - public static class SpanWithScope { - @Nullable private final SpanWithScope parent; - private final Span span; - private final Scope scope; - - public SpanWithScope(SpanWithScope parent, Span span, Scope scope) { - this.parent = parent; - this.span = span; - this.scope = scope; - } - - public static SpanWithScope activate(Span span, SpanWithScope parent, SpanKind spanKind) { - Scope scope = null; - if (isClientSpan(spanKind)) { - scope = CamelTracer.TRACER.startClientScope(span); - } else { - scope = span.makeCurrent(); - } - - return new SpanWithScope(parent, span, scope); - } - - private static boolean isClientSpan(SpanKind kind) { - return (SpanKind.CLIENT.equals(kind) || SpanKind.PRODUCER.equals(kind)); - } - - public SpanWithScope getParent() { - return parent; - } - - public Span getSpan() { - return span; - } - - public void deactivate() { - span.end(); - scope.close(); - } - - @Override - public String toString() { - return "SpanWithScope [span=" + span + ", scope=" + scope + "]"; - } - } -} diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelEventNotifier.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelEventNotifier.java index 8604e944d1c5..7bfadc58f4a6 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelEventNotifier.java +++ b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelEventNotifier.java @@ -23,7 +23,9 @@ package io.opentelemetry.javaagent.instrumentation.apachecamel; -import io.opentelemetry.api.trace.Span; +import static io.opentelemetry.javaagent.instrumentation.apachecamel.CamelSingletons.getSpanDecorator; +import static io.opentelemetry.javaagent.instrumentation.apachecamel.CamelSingletons.instrumenter; + import io.opentelemetry.context.Context; import java.util.EventObject; import org.apache.camel.management.event.ExchangeSendingEvent; @@ -38,51 +40,52 @@ final class CamelEventNotifier extends EventNotifierSupport { @Override public void notify(EventObject event) { - - try { - if (event instanceof ExchangeSendingEvent) { - onExchangeSending((ExchangeSendingEvent) event); - } else if (event instanceof ExchangeSentEvent) { - onExchangeSent((ExchangeSentEvent) event); - } - } catch (Throwable t) { - logger.warn("Failed to capture tracing data", t); + if (event instanceof ExchangeSendingEvent) { + onExchangeSending((ExchangeSendingEvent) event); + } else if (event instanceof ExchangeSentEvent) { + onExchangeSent((ExchangeSentEvent) event); } } /** Camel about to send (outbound). */ private static void onExchangeSending(ExchangeSendingEvent ese) { - SpanDecorator sd = CamelTracer.TRACER.getSpanDecorator(ese.getEndpoint()); + SpanDecorator sd = getSpanDecorator(ese.getEndpoint()); if (!sd.shouldStartNewSpan()) { return; } - String name = - sd.getOperationName(ese.getExchange(), ese.getEndpoint(), CamelDirection.OUTBOUND); - Context context = CamelTracer.TRACER.startSpan(name, sd.getInitiatorSpanKind()); - Span span = Span.fromContext(context); - sd.pre(span, ese.getExchange(), ese.getEndpoint(), CamelDirection.OUTBOUND); - ActiveSpanManager.activate(ese.getExchange(), span, sd.getInitiatorSpanKind()); + CamelRequest request = + CamelRequest.create( + sd, + ese.getExchange(), + ese.getEndpoint(), + CamelDirection.OUTBOUND, + sd.getInitiatorSpanKind()); + Context context = startOnExchangeSending(request); + + ActiveContextManager.activate(context, request); CamelPropagationUtil.injectParent(context, ese.getExchange().getIn().getHeaders()); - logger.debug("[Exchange sending] Initiator span started: {}", span); + logger.debug("[Exchange sending] Initiator span started: {}", context); + } + + private static Context startOnExchangeSending(CamelRequest request) { + Context parentContext = Context.current(); + if (!instrumenter().shouldStart(parentContext, request)) { + return null; + } + return instrumenter().start(parentContext, request); } /** Camel finished sending (outbound). Finish span and remove it from CAMEL holder. */ private static void onExchangeSent(ExchangeSentEvent event) { - SpanDecorator sd = CamelTracer.TRACER.getSpanDecorator(event.getEndpoint()); + SpanDecorator sd = getSpanDecorator(event.getEndpoint()); if (!sd.shouldStartNewSpan()) { return; } - Span span = ActiveSpanManager.getSpan(event.getExchange()); - if (span != null) { - logger.debug("[Exchange sent] Initiator span finished: {}", span); - sd.post(span, event.getExchange(), event.getEndpoint()); - ActiveSpanManager.deactivate(event.getExchange()); - } else { - logger.warn("Could not find managed span for exchange: {}", event.getExchange()); - } + Context context = ActiveContextManager.deactivate(event.getExchange()); + logger.debug("[Exchange sent] Initiator span finished: {}", context); } @Override diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelRequest.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelRequest.java new file mode 100644 index 000000000000..386a969ceb95 --- /dev/null +++ b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelRequest.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.apachecamel; + +import com.google.auto.value.AutoValue; +import io.opentelemetry.api.trace.SpanKind; +import org.apache.camel.Endpoint; +import org.apache.camel.Exchange; + +@AutoValue +abstract class CamelRequest { + + public static CamelRequest create( + SpanDecorator spanDecorator, + Exchange exchange, + Endpoint endpoint, + CamelDirection camelDirection, + SpanKind spanKind) { + return new AutoValue_CamelRequest(spanDecorator, exchange, endpoint, camelDirection, spanKind); + } + + public abstract SpanDecorator getSpanDecorator(); + + public abstract Exchange getExchange(); + + public abstract Endpoint getEndpoint(); + + public abstract CamelDirection getCamelDirection(); + + public abstract SpanKind getSpanKind(); +} diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelRoutePolicy.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelRoutePolicy.java index f9ff5557950e..2159aa7961bf 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelRoutePolicy.java +++ b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelRoutePolicy.java @@ -23,6 +23,9 @@ package io.opentelemetry.javaagent.instrumentation.apachecamel; +import static io.opentelemetry.javaagent.instrumentation.apachecamel.CamelSingletons.getSpanDecorator; +import static io.opentelemetry.javaagent.instrumentation.apachecamel.CamelSingletons.instrumenter; + import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Context; @@ -36,23 +39,30 @@ final class CamelRoutePolicy extends RoutePolicySupport { private static final Logger logger = LoggerFactory.getLogger(CamelRoutePolicy.class); - private static Span spanOnExchangeBegin( - Route route, Exchange exchange, SpanDecorator sd, Context parentContext, SpanKind spanKind) { + private static Context spanOnExchangeBegin( + Route route, Exchange exchange, SpanDecorator sd, Context parentContext) { Span activeSpan = Span.fromContext(parentContext); if (!activeSpan.getSpanContext().isValid()) { parentContext = CamelPropagationUtil.extractParent(exchange.getIn().getHeaders(), route.getEndpoint()); } - String name = sd.getOperationName(exchange, route.getEndpoint(), CamelDirection.INBOUND); - Context context = CamelTracer.TRACER.startSpan(parentContext, name, spanKind); - return Span.fromContext(context); + SpanKind spanKind = spanKind(activeSpan, sd); + CamelRequest request = + CamelRequest.create(sd, exchange, route.getEndpoint(), CamelDirection.INBOUND, spanKind); + sd.updateServerSpanName(parentContext, exchange, route.getEndpoint(), CamelDirection.INBOUND); + + if (!instrumenter().shouldStart(parentContext, request)) { + return null; + } + Context context = instrumenter().start(parentContext, request); + ActiveContextManager.activate(context, request); + return context; } - private static SpanKind spanKind(Context context, SpanDecorator sd) { - Span activeSpan = Span.fromContext(context); + private static SpanKind spanKind(Span activeSpan, SpanDecorator sd) { // if there's an active span, this is not a root span which we always mark as INTERNAL - return (activeSpan.getSpanContext().isValid() ? SpanKind.INTERNAL : sd.getReceiverSpanKind()); + return activeSpan.getSpanContext().isValid() ? SpanKind.INTERNAL : sd.getReceiverSpanKind(); } /** @@ -61,35 +71,16 @@ private static SpanKind spanKind(Context context, SpanDecorator sd) { */ @Override public void onExchangeBegin(Route route, Exchange exchange) { - try { - SpanDecorator sd = CamelTracer.TRACER.getSpanDecorator(route.getEndpoint()); - Context parentContext = Context.current(); - SpanKind spanKind = spanKind(parentContext, sd); - Span span = spanOnExchangeBegin(route, exchange, sd, parentContext, spanKind); - sd.pre(span, exchange, route.getEndpoint(), CamelDirection.INBOUND); - ActiveSpanManager.activate(exchange, span, spanKind); - logger.debug("[Route start] Receiver span started {}", span); - } catch (Throwable t) { - logger.warn("Failed to capture tracing data", t); - } + SpanDecorator sd = getSpanDecorator(route.getEndpoint()); + Context parentContext = Context.current(); + Context context = spanOnExchangeBegin(route, exchange, sd, parentContext); + logger.debug("[Route start] Receiver span started {}", context); } /** Route exchange done. Get active CAMEL span, finish, remove from CAMEL holder. */ @Override public void onExchangeDone(Route route, Exchange exchange) { - try { - Span span = ActiveSpanManager.getSpan(exchange); - if (span != null) { - - logger.debug("[Route finished] Receiver span finished {}", span); - SpanDecorator sd = CamelTracer.TRACER.getSpanDecorator(route.getEndpoint()); - sd.post(span, exchange, route.getEndpoint()); - ActiveSpanManager.deactivate(exchange); - } else { - logger.warn("Could not find managed span for exchange={}", exchange); - } - } catch (Throwable t) { - logger.warn("Failed to capture tracing data", t); - } + Context context = ActiveContextManager.deactivate(exchange); + logger.debug("[Route finished] Receiver span finished {}", context); } } diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelSingletons.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelSingletons.java new file mode 100644 index 000000000000..16153d7e643f --- /dev/null +++ b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelSingletons.java @@ -0,0 +1,93 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.apachecamel; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor; +import io.opentelemetry.javaagent.instrumentation.apachecamel.decorators.DecoratorRegistry; +import javax.annotation.Nullable; +import org.apache.camel.Endpoint; +import org.apache.camel.util.StringHelper; + +public final class CamelSingletons { + + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.apache-camel-2.20"; + + private static final DecoratorRegistry registry = new DecoratorRegistry(); + private static final Instrumenter INSTRUMENTER; + + static { + SpanNameExtractor spanNameExtractor = + camelRequest -> + camelRequest + .getSpanDecorator() + .getOperationName( + camelRequest.getExchange(), + camelRequest.getEndpoint(), + camelRequest.getCamelDirection()); + + AttributesExtractor attributesExtractor = + new AttributesExtractor() { + + @Override + public void onStart(AttributesBuilder attributes, CamelRequest camelRequest) { + SpanDecorator spanDecorator = camelRequest.getSpanDecorator(); + spanDecorator.pre( + attributes, + camelRequest.getExchange(), + camelRequest.getEndpoint(), + camelRequest.getCamelDirection()); + } + + @Override + public void onEnd( + AttributesBuilder attributes, + CamelRequest camelRequest, + @Nullable Void unused, + @Nullable Throwable error) { + SpanDecorator spanDecorator = camelRequest.getSpanDecorator(); + spanDecorator.post(attributes, camelRequest.getExchange(), camelRequest.getEndpoint()); + } + }; + + SpanStatusExtractor spanStatusExtractor = + (request, unused, error) -> { + if (request.getExchange().isFailed()) { + return StatusCode.ERROR; + } + return null; + }; + + InstrumenterBuilder builder = + Instrumenter.builder(GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanNameExtractor); + builder.addAttributesExtractor(attributesExtractor); + builder.setSpanStatusExtractor(spanStatusExtractor); + + INSTRUMENTER = builder.newInstrumenter(request -> request.getSpanKind()); + } + + public static Instrumenter instrumenter() { + return INSTRUMENTER; + } + + public static SpanDecorator getSpanDecorator(Endpoint endpoint) { + String component = ""; + String uri = endpoint.getEndpointUri(); + String[] splitUri = StringHelper.splitOnCharacter(uri, ":", 2); + if (splitUri[1] != null) { + component = splitUri[0]; + } + return registry.forComponent(component); + } + + private CamelSingletons() {} +} diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelTracer.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelTracer.java deleted file mode 100644 index 2adcfa6dd931..000000000000 --- a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelTracer.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * 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 io.opentelemetry.javaagent.instrumentation.apachecamel; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import io.opentelemetry.javaagent.instrumentation.apachecamel.decorators.DecoratorRegistry; -import org.apache.camel.Endpoint; -import org.apache.camel.util.StringHelper; - -class CamelTracer extends BaseTracer { - - public static final CamelTracer TRACER = new CamelTracer(); - - private final DecoratorRegistry registry = new DecoratorRegistry(); - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.apache-camel-2.20"; - } - - public Scope startClientScope(Span span) { - Context current = super.withClientSpan(Context.current(), span); - return current.makeCurrent(); - } - - public SpanDecorator getSpanDecorator(Endpoint endpoint) { - - String component = ""; - String uri = endpoint.getEndpointUri(); - String[] splitUri = StringHelper.splitOnCharacter(uri, ":", 2); - if (splitUri[1] != null) { - component = splitUri[0]; - } - return registry.forComponent(component); - } -} diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/SpanDecorator.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/SpanDecorator.java index 31379b5c5949..6a1a99ad6ed2 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/SpanDecorator.java +++ b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/SpanDecorator.java @@ -23,8 +23,9 @@ package io.opentelemetry.javaagent.instrumentation.apachecamel; -import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.context.Context; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; @@ -52,25 +53,32 @@ public interface SpanDecorator { * This method adds appropriate details (tags/logs) to the supplied span based on the pre * processing of the exchange. * - * @param span The span + * @param attributes The span attributes * @param exchange The exchange * @param endpoint The endpoint */ - void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection); + void pre( + AttributesBuilder attributes, + Exchange exchange, + Endpoint endpoint, + CamelDirection camelDirection); /** * This method adds appropriate details (tags/logs) to the supplied span based on the post * processing of the exchange. * - * @param span The span + * @param attributes The span attributes * @param exchange The exchange * @param endpoint The endpoint */ - void post(Span span, Exchange exchange, Endpoint endpoint); + void post(AttributesBuilder attributes, Exchange exchange, Endpoint endpoint); /** Returns the 'span.kind' value for use when the component is initiating a communication. */ SpanKind getInitiatorSpanKind(); /** Returns the 'span.kind' value for use when the component is receiving a communication. */ SpanKind getReceiverSpanKind(); + + void updateServerSpanName( + Context context, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection); } diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/BaseSpanDecorator.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/BaseSpanDecorator.java index fa1caa8a1039..6e71524912bb 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/BaseSpanDecorator.java +++ b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/BaseSpanDecorator.java @@ -23,9 +23,9 @@ package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; -import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.config.Config; import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; import io.opentelemetry.javaagent.instrumentation.apachecamel.SpanDecorator; @@ -96,21 +96,18 @@ public String getOperationName( } @Override - public void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { + public void pre( + AttributesBuilder attributes, + Exchange exchange, + Endpoint endpoint, + CamelDirection camelDirection) { if (CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) { - span.setAttribute("apache-camel.uri", URISupport.sanitizeUri(endpoint.getEndpointUri())); + attributes.put("apache-camel.uri", URISupport.sanitizeUri(endpoint.getEndpointUri())); } } @Override - public void post(Span span, Exchange exchange, Endpoint endpoint) { - if (exchange.isFailed()) { - span.setStatus(StatusCode.ERROR); - if (exchange.getException() != null) { - span.recordException(exchange.getException()); - } - } - } + public void post(AttributesBuilder attributes, Exchange exchange, Endpoint endpoint) {} @Override public SpanKind getInitiatorSpanKind() { @@ -121,4 +118,8 @@ public SpanKind getInitiatorSpanKind() { public SpanKind getReceiverSpanKind() { return SpanKind.SERVER; } + + @Override + public void updateServerSpanName( + Context context, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) {} } diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java index 32b9740da9c0..65d029ef0bf1 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java +++ b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java @@ -23,7 +23,7 @@ package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; -import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.instrumentation.api.db.SqlStatementSanitizer; import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; @@ -109,17 +109,21 @@ private String getDbName(Endpoint endpoint) { } @Override - public void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - super.pre(span, exchange, endpoint, camelDirection); + public void pre( + AttributesBuilder attributes, + Exchange exchange, + Endpoint endpoint, + CamelDirection camelDirection) { + super.pre(attributes, exchange, endpoint, camelDirection); - span.setAttribute(SemanticAttributes.DB_SYSTEM, system); + attributes.put(SemanticAttributes.DB_SYSTEM, system); String statement = getStatement(exchange, endpoint); if (statement != null) { - span.setAttribute(SemanticAttributes.DB_STATEMENT, statement); + attributes.put(SemanticAttributes.DB_STATEMENT, statement); } String dbName = getDbName(endpoint); if (dbName != null) { - span.setAttribute(SemanticAttributes.DB_NAME, dbName); + attributes.put(SemanticAttributes.DB_NAME, dbName); } } } diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/HttpSpanDecorator.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/HttpSpanDecorator.java index f2aa2b8514c4..482d34f8a9db 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/HttpSpanDecorator.java +++ b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/HttpSpanDecorator.java @@ -23,6 +23,7 @@ package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; +import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.tracer.ServerSpan; @@ -81,20 +82,19 @@ public String getOperationName( } @Override - public void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - super.pre(span, exchange, endpoint, camelDirection); + public void pre( + AttributesBuilder attributes, + Exchange exchange, + Endpoint endpoint, + CamelDirection camelDirection) { + super.pre(attributes, exchange, endpoint, camelDirection); String httpUrl = getHttpUrl(exchange, endpoint); if (httpUrl != null) { - span.setAttribute(SemanticAttributes.HTTP_URL, httpUrl); + attributes.put(SemanticAttributes.HTTP_URL, httpUrl); } - span.setAttribute(SemanticAttributes.HTTP_METHOD, getHttpMethod(exchange, endpoint)); - - Span serverSpan = ServerSpan.fromContextOrNull(Context.current()); - if (shouldUpdateServerSpanName(serverSpan, camelDirection)) { - updateServerSpanName(serverSpan, exchange, endpoint); - } + attributes.put(SemanticAttributes.HTTP_METHOD, getHttpMethod(exchange, endpoint)); } private static boolean shouldSetPathAsName(CamelDirection camelDirection) { @@ -125,6 +125,15 @@ private void updateServerSpanName(Span serverSpan, Exchange exchange, Endpoint e } } + @Override + public void updateServerSpanName( + Context context, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { + Span serverSpan = ServerSpan.fromContextOrNull(context); + if (shouldUpdateServerSpanName(serverSpan, camelDirection)) { + updateServerSpanName(serverSpan, exchange, endpoint); + } + } + protected String getHttpUrl(Exchange exchange, Endpoint endpoint) { Object url = exchange.getIn().getHeader(Exchange.HTTP_URL); if (url instanceof String) { @@ -145,13 +154,13 @@ protected String getHttpUrl(Exchange exchange, Endpoint endpoint) { } @Override - public void post(Span span, Exchange exchange, Endpoint endpoint) { - super.post(span, exchange, endpoint); + public void post(AttributesBuilder attributes, Exchange exchange, Endpoint endpoint) { + super.post(attributes, exchange, endpoint); if (exchange.hasOut()) { Object responseCode = exchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE); if (responseCode instanceof Integer) { - span.setAttribute(SemanticAttributes.HTTP_STATUS_CODE, (Integer) responseCode); + attributes.put(SemanticAttributes.HTTP_STATUS_CODE, (Integer) responseCode); } } } diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/KafkaSpanDecorator.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/KafkaSpanDecorator.java index 52c14b027621..4a7aef02fca0 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/KafkaSpanDecorator.java +++ b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/KafkaSpanDecorator.java @@ -23,7 +23,7 @@ package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; -import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.util.Map; @@ -53,31 +53,35 @@ public String getDestination(Exchange exchange, Endpoint endpoint) { } @Override - public void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - super.pre(span, exchange, endpoint, camelDirection); + public void pre( + AttributesBuilder attributes, + Exchange exchange, + Endpoint endpoint, + CamelDirection camelDirection) { + super.pre(attributes, exchange, endpoint, camelDirection); - span.setAttribute(SemanticAttributes.MESSAGING_OPERATION, "process"); - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION_KIND, "topic"); + attributes.put(SemanticAttributes.MESSAGING_OPERATION, "process"); + attributes.put(SemanticAttributes.MESSAGING_DESTINATION_KIND, "topic"); Integer partition = exchange.getIn().getHeader(PARTITION, Integer.class); if (partition != null) { - span.setAttribute(SemanticAttributes.MESSAGING_KAFKA_PARTITION, partition); + attributes.put(SemanticAttributes.MESSAGING_KAFKA_PARTITION, partition); } if (CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) { String partitionKey = (String) exchange.getIn().getHeader(PARTITION_KEY); if (partitionKey != null) { - span.setAttribute("apache-camel.kafka.partitionKey", partitionKey); + attributes.put("apache-camel.kafka.partitionKey", partitionKey); } String key = (String) exchange.getIn().getHeader(KEY); if (key != null) { - span.setAttribute("apache-camel.kafka.key", key); + attributes.put("apache-camel.kafka.key", key); } String offset = getValue(exchange, OFFSET, Long.class); if (offset != null) { - span.setAttribute("apache-camel.kafka.offset", offset); + attributes.put("apache-camel.kafka.offset", offset); } } } diff --git a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/MessagingSpanDecorator.java b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/MessagingSpanDecorator.java index e300400df2e1..3b04fbee442e 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/MessagingSpanDecorator.java +++ b/instrumentation/apache-camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/MessagingSpanDecorator.java @@ -23,7 +23,7 @@ package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; -import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; @@ -51,14 +51,18 @@ public String getOperationName( } @Override - public void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - super.pre(span, exchange, endpoint, camelDirection); + public void pre( + AttributesBuilder attributes, + Exchange exchange, + Endpoint endpoint, + CamelDirection camelDirection) { + super.pre(attributes, exchange, endpoint, camelDirection); - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION, getDestination(exchange, endpoint)); + attributes.put(SemanticAttributes.MESSAGING_DESTINATION, getDestination(exchange, endpoint)); String messageId = getMessageId(exchange); if (messageId != null) { - span.setAttribute(SemanticAttributes.MESSAGING_MESSAGE_ID, messageId); + attributes.put(SemanticAttributes.MESSAGING_MESSAGE_ID, messageId); } }