diff --git a/docs/instrumentation-list.yaml b/docs/instrumentation-list.yaml index caffb4395dce..23b8df1abd11 100644 --- a/docs/instrumentation-list.yaml +++ b/docs/instrumentation-list.yaml @@ -2143,7 +2143,14 @@ libraries: - name: camel-2.20 description: | This instrumentation enables tracing for Apache Camel 2.x applications by generating spans for each route execution. For Camel versions 3.5 and newer, users should instead use the native 'camel-opentelemetry' component provided directly by the Camel project. + semantic_conventions: + - HTTP_CLIENT_SPANS + - HTTP_SERVER_SPANS + - DATABASE_CLIENT_SPANS + - MESSAGING_SPANS library_link: https://camel.apache.org/ + features: + - HTTP_ROUTE source_path: instrumentation/camel-2.20 scope: name: io.opentelemetry.camel-2.20 @@ -2173,6 +2180,12 @@ libraries: type: LONG - name: url.full type: STRING + - span_kind: CONSUMER + attributes: + - name: messaging.destination.name + type: STRING + - name: messaging.message.id + type: STRING - span_kind: INTERNAL attributes: - name: http.request.method @@ -2183,6 +2196,10 @@ libraries: type: STRING - name: url.full type: STRING + - span_kind: PRODUCER + attributes: + - name: messaging.destination.name + type: STRING - span_kind: SERVER attributes: - name: http.request.method @@ -2209,6 +2226,14 @@ libraries: type: LONG - name: url.full type: STRING + - span_kind: CONSUMER + attributes: + - name: camel.uri + type: STRING + - name: messaging.destination.name + type: STRING + - name: messaging.message.id + type: STRING - span_kind: INTERNAL attributes: - name: camel.uri @@ -2221,6 +2246,12 @@ libraries: type: STRING - name: url.full type: STRING + - span_kind: PRODUCER + attributes: + - name: camel.uri + type: STRING + - name: messaging.destination.name + type: STRING - span_kind: SERVER attributes: - name: camel.uri @@ -2247,6 +2278,12 @@ libraries: type: LONG - name: url.full type: STRING + - span_kind: CONSUMER + attributes: + - name: messaging.destination.name + type: STRING + - name: messaging.message.id + type: STRING - span_kind: INTERNAL attributes: - name: http.request.method @@ -2257,6 +2294,10 @@ libraries: type: STRING - name: url.full type: STRING + - span_kind: PRODUCER + attributes: + - name: messaging.destination.name + type: STRING - span_kind: SERVER attributes: - name: http.request.method diff --git a/instrumentation/camel-2.20/javaagent/build.gradle.kts b/instrumentation/camel-2.20/javaagent/build.gradle.kts index 207562ed8b01..27fc5cb09e5b 100644 --- a/instrumentation/camel-2.20/javaagent/build.gradle.kts +++ b/instrumentation/camel-2.20/javaagent/build.gradle.kts @@ -43,6 +43,8 @@ dependencies { testImplementation("org.apache.camel:camel-undertow:$camelversion") testImplementation("org.apache.camel:camel-aws:$camelversion") testImplementation("org.apache.camel:camel-cassandraql:$camelversion") + testImplementation("org.apache.camel:camel-jms:$camelversion") + testImplementation("org.apache.activemq:activemq-broker:5.16.5") testImplementation("org.springframework.boot:spring-boot-starter-test:1.5.17.RELEASE") testImplementation("org.springframework.boot:spring-boot-starter:1.5.17.RELEASE") diff --git a/instrumentation/camel-2.20/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/apachecamel/JmsCamelTest.java b/instrumentation/camel-2.20/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/apachecamel/JmsCamelTest.java new file mode 100644 index 000000000000..d2b485f7b061 --- /dev/null +++ b/instrumentation/camel-2.20/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/apachecamel/JmsCamelTest.java @@ -0,0 +1,102 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.apachecamel; + +import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static io.opentelemetry.javaagent.instrumentation.apachecamel.ExperimentalTest.experimental; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes.MESSAGING_DESTINATION_NAME; +import static io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes.MESSAGING_MESSAGE_ID; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import javax.jms.ConnectionFactory; +import org.apache.activemq.ActiveMQConnectionFactory; +import org.apache.activemq.broker.BrokerService; +import org.apache.camel.CamelContext; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.jms.JmsComponent; +import org.apache.camel.impl.DefaultCamelContext; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class JmsCamelTest { + + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static BrokerService broker; + private static CamelContext camelContext; + + @BeforeAll + static void setUp() throws Exception { + broker = new BrokerService(); + broker.setPersistent(false); + broker.setUseJmx(false); + broker.addConnector("vm://localhost"); + broker.start(); + + camelContext = new DefaultCamelContext(); + ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost"); + camelContext.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory)); + + camelContext.addRoutes( + new RouteBuilder() { + @Override + public void configure() { + from("direct:input").to("jms:queue:testQueue"); + from("jms:queue:testQueue").to("mock:result"); + } + }); + + camelContext.start(); + testing.clearData(); + } + + @AfterAll + static void tearDown() throws Exception { + if (camelContext != null) { + camelContext.stop(); + } + if (broker != null) { + broker.stop(); + } + } + + @Test + void testJmsProducerAndConsumer() { + ProducerTemplate template = camelContext.createProducerTemplate(); + template.sendBody("direct:input", "test message"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("input").hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName("queue:testQueue") + .hasKind(SpanKind.PRODUCER) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo(MESSAGING_DESTINATION_NAME, "queue:testQueue"), + equalTo(stringKey("camel.uri"), experimental("jms://queue:testQueue"))), + span -> + span.hasName("queue:testQueue") + .hasKind(SpanKind.CONSUMER) + .hasParent(trace.getSpan(1)) + .hasAttributesSatisfyingExactly( + equalTo(MESSAGING_DESTINATION_NAME, "queue:testQueue"), + equalTo(stringKey("camel.uri"), experimental("jms://queue:testQueue")), + satisfies( + MESSAGING_MESSAGE_ID, + stringAssert -> stringAssert.isInstanceOf(String.class))), + span -> span.hasName("mock").hasKind(SpanKind.CLIENT).hasParent(trace.getSpan(2)))); + } +} diff --git a/instrumentation/camel-2.20/metadata.yaml b/instrumentation/camel-2.20/metadata.yaml index 968f1d58d09d..4c02f7566ff6 100644 --- a/instrumentation/camel-2.20/metadata.yaml +++ b/instrumentation/camel-2.20/metadata.yaml @@ -2,6 +2,13 @@ description: > This instrumentation enables tracing for Apache Camel 2.x applications by generating spans for each route execution. For Camel versions 3.5 and newer, users should instead use the native 'camel-opentelemetry' component provided directly by the Camel project. +semantic_conventions: + - HTTP_CLIENT_SPANS + - HTTP_SERVER_SPANS + - DATABASE_CLIENT_SPANS + - MESSAGING_SPANS +features: + - HTTP_ROUTE library_link: https://camel.apache.org/ configurations: - name: otel.instrumentation.camel.experimental-span-attributes