Skip to content

Commit

Permalink
Convert camel instrumentation to instrumenter api (open-telemetry#4973)
Browse files Browse the repository at this point in the history
  • Loading branch information
laurit authored and RashmiRam committed May 23, 2022
1 parent 9a380b0 commit 5d4a188
Show file tree
Hide file tree
Showing 14 changed files with 380 additions and 297 deletions.
3 changes: 3 additions & 0 deletions instrumentation/apache-camel-2.20/javaagent/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down
Original file line number Diff line number Diff line change
@@ -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
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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 + "]";
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
Loading

0 comments on commit 5d4a188

Please sign in to comment.