From b2b32df7180a5e9620f168da56a8ff56e8848692 Mon Sep 17 00:00:00 2001 From: Ales Justin Date: Wed, 15 Sep 2021 14:47:09 +0200 Subject: [PATCH 1/7] Add support for Kafka consumer and producer interceptors, move common Kafka code to library module. --- .../javaagent/build.gradle.kts | 3 +- .../KafkaConsumerInstrumentation.java | 4 +- .../KafkaProducerInstrumentation.java | 4 +- .../kafkaclients/ProducerCallback.java | 2 +- .../kafkaclients/TracingIterable.java | 2 +- .../kafkaclients/TracingIterator.java | 4 +- .../KafkaClientDefaultTest.groovy | 6 +- .../KafkaClientPropagationDisabledTest.groovy | 6 +- ...KafkaClientSuppressReceiveSpansTest.groovy | 9 +- .../library/build.gradle.kts | 23 ++++ .../kafkaclients/KafkaTracing.java | 125 ++++++++++++++++++ .../kafkaclients/KafkaTracingBuilder.java | 65 +++++++++ .../TracingConsumerInterceptor.java | 32 +++++ .../TracingProducerInterceptor.java | 30 +++++ .../kafkaclients/InterceptorsTest.groovy | 117 ++++++++++++++++ .../src/test/resources/log4j.properties | 5 + .../testing/build.gradle.kts | 13 ++ .../kafkaclients}/KafkaClientBaseTest.groovy | 46 ++++--- .../KafkaClientPropagationBaseTest.groovy | 30 +++++ .../javaagent/build.gradle.kts | 7 - .../kafka/KafkaHeadersSetter.java | 18 --- .../library/build.gradle.kts | 9 ++ ...ConsumerAdditionalAttributesExtractor.java | 2 +- .../KafkaConsumerAttributesExtractor.java | 2 +- ...nsumerExperimentalAttributesExtractor.java | 2 +- .../kafka/KafkaConsumerIterableWrapper.java | 2 +- .../kafka/KafkaConsumerIteratorWrapper.java | 2 +- .../kafka/KafkaConsumerRecordGetter.java} | 5 +- .../kafka/KafkaHeadersGetter.java | 37 ++++++ .../kafka/KafkaHeadersSetter.java | 18 +++ ...ProducerAdditionalAttributesExtractor.java | 2 +- .../KafkaProducerAttributesExtractor.java | 2 +- .../kafka/KafkaPropagation.java | 6 +- .../KafkaReceiveAttributesExtractor.java | 2 +- .../kafka/KafkaSingletons.java | 39 ++++++ .../instrumentation/kafka/KafkaUtils.java} | 77 ++++++----- .../kafka}/ReceivedRecords.java | 2 +- .../instrumentation/kafka}/Timer.java | 2 +- .../javaagent/build.gradle.kts | 2 +- .../kafkastreams/KafkaStreamsSingletons.java | 14 +- .../StreamTaskInstrumentation.java | 2 +- .../StreamThreadInstrumentation.java | 2 +- .../javaagent/build.gradle.kts | 2 +- .../KafkaBatchProcessSpanLinksExtractor.java | 6 +- settings.gradle.kts | 5 +- 45 files changed, 670 insertions(+), 125 deletions(-) rename instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/{ => io/opentelemetry/instrumentation/kafkaclients}/KafkaClientDefaultTest.groovy (98%) rename instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/{ => io/opentelemetry/instrumentation/kafkaclients}/KafkaClientPropagationDisabledTest.groovy (95%) rename instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/{ => io/opentelemetry/instrumentation/kafkaclients}/KafkaClientSuppressReceiveSpansTest.groovy (96%) create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/build.gradle.kts create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/resources/log4j.properties create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/testing/build.gradle.kts rename instrumentation/kafka-clients/kafka-clients-0.11/{javaagent/src/test/groovy => testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients}/KafkaClientBaseTest.groovy (88%) create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy delete mode 100644 instrumentation/kafka-clients/kafka-clients-common/javaagent/build.gradle.kts delete mode 100644 instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaHeadersSetter.java create mode 100644 instrumentation/kafka-clients/kafka-clients-common/library/build.gradle.kts rename instrumentation/kafka-clients/kafka-clients-common/{javaagent/src/main/java/io/opentelemetry/javaagent => library/src/main/java/io/opentelemetry}/instrumentation/kafka/KafkaConsumerAdditionalAttributesExtractor.java (94%) rename instrumentation/kafka-clients/kafka-clients-common/{javaagent/src/main/java/io/opentelemetry/javaagent => library/src/main/java/io/opentelemetry}/instrumentation/kafka/KafkaConsumerAttributesExtractor.java (97%) rename instrumentation/kafka-clients/kafka-clients-common/{javaagent/src/main/java/io/opentelemetry/javaagent => library/src/main/java/io/opentelemetry}/instrumentation/kafka/KafkaConsumerExperimentalAttributesExtractor.java (97%) rename instrumentation/kafka-clients/kafka-clients-common/{javaagent/src/main/java/io/opentelemetry/javaagent => library/src/main/java/io/opentelemetry}/instrumentation/kafka/KafkaConsumerIterableWrapper.java (88%) rename instrumentation/kafka-clients/kafka-clients-common/{javaagent/src/main/java/io/opentelemetry/javaagent => library/src/main/java/io/opentelemetry}/instrumentation/kafka/KafkaConsumerIteratorWrapper.java (88%) rename instrumentation/kafka-clients/kafka-clients-common/{javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaHeadersGetter.java => library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerRecordGetter.java} (87%) create mode 100644 instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaHeadersGetter.java create mode 100644 instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaHeadersSetter.java rename instrumentation/kafka-clients/{kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients => kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka}/KafkaProducerAdditionalAttributesExtractor.java (94%) rename instrumentation/kafka-clients/{kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients => kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka}/KafkaProducerAttributesExtractor.java (96%) rename instrumentation/kafka-clients/kafka-clients-common/{javaagent/src/main/java/io/opentelemetry/javaagent => library/src/main/java/io/opentelemetry}/instrumentation/kafka/KafkaPropagation.java (92%) rename instrumentation/kafka-clients/{kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients => kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka}/KafkaReceiveAttributesExtractor.java (97%) create mode 100644 instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaSingletons.java rename instrumentation/kafka-clients/{kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java => kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaUtils.java} (58%) rename instrumentation/kafka-clients/{kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients => kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka}/ReceivedRecords.java (90%) rename instrumentation/kafka-clients/{kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients => kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka}/Timer.java (90%) diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/build.gradle.kts b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/build.gradle.kts index e83069f3d73f..0ebb01973066 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/build.gradle.kts +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/build.gradle.kts @@ -15,11 +15,12 @@ dependencies { compileOnly("com.google.auto.value:auto-value-annotations") annotationProcessor("com.google.auto.value:auto-value") - implementation(project(":instrumentation:kafka-clients:kafka-clients-common:javaagent")) + implementation(project(":instrumentation:kafka-clients:kafka-clients-common:library")) library("org.apache.kafka:kafka-clients:0.11.0.0") testImplementation("org.testcontainers:kafka") + testImplementation(project(":instrumentation:kafka-clients:kafka-clients-0.11:testing")) } tasks { diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerInstrumentation.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerInstrumentation.java index 8674438ce77f..669e70d77068 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerInstrumentation.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerInstrumentation.java @@ -5,9 +5,9 @@ package io.opentelemetry.javaagent.instrumentation.kafkaclients; +import static io.opentelemetry.instrumentation.kafka.KafkaSingletons.consumerReceiveInstrumenter; import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.spanFromContext; -import static io.opentelemetry.javaagent.instrumentation.kafkaclients.KafkaSingletons.consumerReceiveInstrumenter; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; @@ -16,6 +16,8 @@ import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.kafka.ReceivedRecords; +import io.opentelemetry.instrumentation.kafka.Timer; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerInstrumentation.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerInstrumentation.java index 2d6e724de341..c8582fed0945 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerInstrumentation.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerInstrumentation.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.kafkaclients; -import static io.opentelemetry.javaagent.instrumentation.kafkaclients.KafkaSingletons.producerInstrumenter; +import static io.opentelemetry.instrumentation.kafka.KafkaSingletons.producerInstrumenter; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -13,10 +13,10 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.kafka.KafkaPropagation; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaPropagation; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ProducerCallback.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ProducerCallback.java index a500724b8e6c..785ef08d4d90 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ProducerCallback.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ProducerCallback.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.kafkaclients; -import static io.opentelemetry.javaagent.instrumentation.kafkaclients.KafkaSingletons.producerInstrumenter; +import static io.opentelemetry.instrumentation.kafka.KafkaSingletons.producerInstrumenter; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterable.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterable.java index 70da1bc02138..2346ae8fb70e 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterable.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterable.java @@ -6,7 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.kafkaclients; import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaConsumerIterableWrapper; +import io.opentelemetry.instrumentation.kafka.KafkaConsumerIterableWrapper; import java.util.Iterator; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterator.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterator.java index a163f246b440..b6f35835aae0 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterator.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterator.java @@ -5,13 +5,13 @@ package io.opentelemetry.javaagent.instrumentation.kafkaclients; -import static io.opentelemetry.javaagent.instrumentation.kafkaclients.KafkaSingletons.consumerProcessInstrumenter; +import static io.opentelemetry.instrumentation.kafka.KafkaSingletons.consumerProcessInstrumenter; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaConsumerIteratorWrapper; +import io.opentelemetry.instrumentation.kafka.KafkaConsumerIteratorWrapper; import java.util.Iterator; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientDefaultTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientDefaultTest.groovy similarity index 98% rename from instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientDefaultTest.groovy rename to instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientDefaultTest.groovy index 1af6ccf5ac73..ab4cae1a9091 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientDefaultTest.groovy +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientDefaultTest.groovy @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +package io.opentelemetry.instrumentation.kafkaclients + import io.opentelemetry.sdk.trace.data.SpanData import io.opentelemetry.semconv.trace.attributes.SemanticAttributes import org.apache.kafka.clients.producer.ProducerRecord @@ -15,7 +17,7 @@ import static io.opentelemetry.api.trace.SpanKind.CONSUMER import static io.opentelemetry.api.trace.SpanKind.INTERNAL import static io.opentelemetry.api.trace.SpanKind.PRODUCER -class KafkaClientDefaultTest extends KafkaClientBaseTest { +class KafkaClientDefaultTest extends KafkaClientPropagationBaseTest { def "test kafka produce and consume"() { when: @@ -251,4 +253,4 @@ class KafkaClientDefaultTest extends KafkaClientBaseTest { } } } -} +} \ No newline at end of file diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientPropagationDisabledTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationDisabledTest.groovy similarity index 95% rename from instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientPropagationDisabledTest.groovy rename to instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationDisabledTest.groovy index a09efb36d980..b385810befb8 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientPropagationDisabledTest.groovy +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationDisabledTest.groovy @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +package io.opentelemetry.instrumentation.kafkaclients + import io.opentelemetry.semconv.trace.attributes.SemanticAttributes import org.apache.kafka.clients.producer.ProducerRecord @@ -11,7 +13,7 @@ import java.time.Duration import static io.opentelemetry.api.trace.SpanKind.CONSUMER import static io.opentelemetry.api.trace.SpanKind.PRODUCER -class KafkaClientPropagationDisabledTest extends KafkaClientBaseTest { +class KafkaClientPropagationDisabledTest extends KafkaClientPropagationBaseTest { def "should not read remote context when consuming messages if propagation is disabled"() { when: "send message" @@ -93,4 +95,4 @@ class KafkaClientPropagationDisabledTest extends KafkaClientBaseTest { } } } -} +} \ No newline at end of file diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientSuppressReceiveSpansTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientSuppressReceiveSpansTest.groovy similarity index 96% rename from instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientSuppressReceiveSpansTest.groovy rename to instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientSuppressReceiveSpansTest.groovy index 0b60b16a9128..00c36ace65c3 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientSuppressReceiveSpansTest.groovy +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientSuppressReceiveSpansTest.groovy @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +package io.opentelemetry.instrumentation.kafkaclients + import io.opentelemetry.semconv.trace.attributes.SemanticAttributes import org.apache.kafka.clients.producer.ProducerRecord import org.apache.kafka.common.TopicPartition @@ -13,7 +15,7 @@ import static io.opentelemetry.api.trace.SpanKind.CONSUMER import static io.opentelemetry.api.trace.SpanKind.INTERNAL import static io.opentelemetry.api.trace.SpanKind.PRODUCER -class KafkaClientSuppressReceiveSpansTest extends KafkaClientBaseTest { +class KafkaClientSuppressReceiveSpansTest extends KafkaClientPropagationBaseTest { def "test kafka produce and consume"() { when: @@ -29,6 +31,7 @@ class KafkaClientSuppressReceiveSpansTest extends KafkaClientBaseTest { } then: + awaitUntilConsumerIsReady() // check that the message was received def records = consumer.poll(Duration.ofSeconds(5).toMillis()) for (record in records) { @@ -88,6 +91,7 @@ class KafkaClientSuppressReceiveSpansTest extends KafkaClientBaseTest { producer.send(new ProducerRecord<>(SHARED_TOPIC, null)) then: + awaitUntilConsumerIsReady() // check that the message was received def records = consumer.poll(Duration.ofSeconds(5).toMillis()) for (record in records) { @@ -138,6 +142,7 @@ class KafkaClientSuppressReceiveSpansTest extends KafkaClientBaseTest { then: "wait for PRODUCER span" waitForTraces(1) + awaitUntilConsumerIsReady() when: "receive messages" def consumerRecords = consumer.poll(Duration.ofSeconds(5).toMillis()) @@ -179,4 +184,4 @@ class KafkaClientSuppressReceiveSpansTest extends KafkaClientBaseTest { } } } -} +} \ No newline at end of file diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/build.gradle.kts b/instrumentation/kafka-clients/kafka-clients-0.11/library/build.gradle.kts new file mode 100644 index 000000000000..5d5eb9cbfc9b --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + id("otel.library-instrumentation") +} + +val versions: Map by project + +dependencies { + implementation(project(":instrumentation:kafka-clients:kafka-clients-common:library")) + library("org.apache.kafka:kafka-clients:0.11.0.0") + + testImplementation(project(":instrumentation:kafka-clients:kafka-clients-0.11:testing")) + + testImplementation("org.testcontainers:kafka:${versions["org.testcontainers"]}") +} + +tasks { + withType().configureEach { + usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service) + + // TODO run tests both with and without experimental span attributes + jvmArgs("-Dotel.instrumentation.kafka.experimental-span-attributes=true") + } +} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java new file mode 100644 index 000000000000..80f7cc761704 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java @@ -0,0 +1,125 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafkaclients; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.context.propagation.TextMapSetter; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.kafka.KafkaHeadersGetter; +import io.opentelemetry.instrumentation.kafka.KafkaHeadersSetter; +import io.opentelemetry.instrumentation.kafka.KafkaSingletons; +import io.opentelemetry.instrumentation.kafka.ReceivedRecords; +import io.opentelemetry.instrumentation.kafka.Timer; +import java.util.Objects; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.header.Headers; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class KafkaTracing { + + private static final Logger logger = LoggerFactory.getLogger(KafkaTracing.class); + + private static final TextMapGetter GETTER = new KafkaHeadersGetter(); + + private static final TextMapSetter SETTER = new KafkaHeadersSetter(); + + private Instrumenter, Void> producerInstrumenter = + KafkaSingletons.producerInstrumenter(); + private Instrumenter consumerReceiveInstrumenter = + KafkaSingletons.consumerReceiveInstrumenter(); + private Instrumenter, Void> consumerProcessInstrumenter = + KafkaSingletons.consumerProcessInstrumenter(); + + KafkaTracing() {} + + public static KafkaTracingBuilder newBuilder(OpenTelemetry openTelemetry) { + return new KafkaTracingBuilder(openTelemetry); + } + + private static TextMapPropagator propagator() { + return GlobalOpenTelemetry.getPropagators().getTextMapPropagator(); + } + + void setProducerInstrumenter(Instrumenter, Void> producerInstrumenter) { + this.producerInstrumenter = Objects.requireNonNull(producerInstrumenter); + } + + void setConsumerReceiveInstrumenter(Instrumenter consumerInstrumenter) { + this.consumerReceiveInstrumenter = Objects.requireNonNull(consumerInstrumenter); + } + + void setConsumerProcessInstrumenter( + Instrumenter, Void> consumerInstrumenter) { + this.consumerProcessInstrumenter = Objects.requireNonNull(consumerInstrumenter); + } + + /** + * Build and inject span into record. Return Runnable handle to end the current span. + * + * @param record the producer record to inject span info. + * @return runnable to close the current span + */ + public Runnable buildAndInjectSpan(ProducerRecord record) { + if (!producerInstrumenter.shouldStart(Context.current(), record)) { + return () -> {}; + } + + Context current = producerInstrumenter.start(Context.current(), record); + try (Scope ignored = current.makeCurrent()) { + try { + propagator().inject(Context.current(), record.headers(), SETTER); + } catch (Throwable t) { + // it can happen if headers are read only (when record is sent second time) + logger.error("failed to inject span context. sending record second time?", t); + } + } + + return () -> producerInstrumenter.end(current, record, null, null); + } + + public void buildAndFinishSpan(ConsumerRecords records) { + ReceivedRecords receivedRecords = ReceivedRecords.create(records, Timer.start()); + + if (!consumerReceiveInstrumenter.shouldStart(Context.current(), receivedRecords)) { + return; + } + + Context context = consumerReceiveInstrumenter.start(Context.current(), receivedRecords); + try (Scope ignored = context.makeCurrent()) { + for (ConsumerRecord record : records) { + buildAndFinishChildSpan(record); + } + consumerReceiveInstrumenter.end(context, receivedRecords, null, null); + } catch (RuntimeException e) { + consumerReceiveInstrumenter.end(context, receivedRecords, null, e); + } + } + + private void buildAndFinishChildSpan(ConsumerRecord record) { + Context linkedContext = propagator().extract(Context.current(), record.headers(), GETTER); + Context.current().with(Span.fromContext(linkedContext)); + + if (!consumerProcessInstrumenter.shouldStart(Context.current(), record)) { + return; + } + + Context current = consumerProcessInstrumenter.start(Context.current(), record); + consumerProcessInstrumenter.end(current, record, null, null); + + // Inject created span context into record headers for extraction by client to continue span + // chain + propagator().inject(current, record.headers(), SETTER); // TODO -- OK? + } +} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java new file mode 100644 index 000000000000..4d764f2ff351 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java @@ -0,0 +1,65 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafkaclients; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.kafka.KafkaSingletons; +import io.opentelemetry.instrumentation.kafka.KafkaUtils; +import io.opentelemetry.instrumentation.kafka.ReceivedRecords; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.producer.ProducerRecord; + +public class KafkaTracingBuilder { + private final OpenTelemetry openTelemetry; + private final List, Void>> producerExtractors = + new ArrayList<>(); + private final List> consumerReceiveExtractors = + new ArrayList<>(); + private final List, Void>> consumerProcessExtractors = + new ArrayList<>(); + + KafkaTracingBuilder(OpenTelemetry openTelemetry) { + this.openTelemetry = Objects.requireNonNull(openTelemetry); + } + + public void addProducerExtractors(AttributesExtractor, Void> extractor) { + producerExtractors.add(extractor); + } + + public void addConsumerReceiveExtractors(AttributesExtractor extractor) { + consumerReceiveExtractors.add(extractor); + } + + public void addConsumerProcessExtractors( + AttributesExtractor, Void> extractor) { + consumerProcessExtractors.add(extractor); + } + + @SuppressWarnings("unchecked") + public KafkaTracing build() { + KafkaTracing tracing = new KafkaTracing(); + tracing.setProducerInstrumenter( + KafkaUtils.buildProducerInstrumenter( + KafkaSingletons.INSTRUMENTATION_NAME, + openTelemetry, + producerExtractors.toArray(new AttributesExtractor[0]))); + tracing.setConsumerReceiveInstrumenter( + KafkaUtils.buildConsumerReceiveInstrumenter( + KafkaSingletons.INSTRUMENTATION_NAME, + openTelemetry, + consumerReceiveExtractors.toArray(new AttributesExtractor[0]))); + tracing.setConsumerProcessInstrumenter( + KafkaUtils.buildConsumerProcessInstrumenter( + KafkaSingletons.INSTRUMENTATION_NAME, + openTelemetry, + consumerProcessExtractors.toArray(new AttributesExtractor[0]))); + return tracing; + } +} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java new file mode 100644 index 000000000000..83b60e101b22 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java @@ -0,0 +1,32 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafkaclients; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import java.util.Map; +import org.apache.kafka.clients.consumer.ConsumerInterceptor; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.OffsetAndMetadata; +import org.apache.kafka.common.TopicPartition; + +public class TracingConsumerInterceptor implements ConsumerInterceptor { + + @Override + public ConsumerRecords onConsume(ConsumerRecords records) { + KafkaTracing tracing = KafkaTracing.newBuilder(GlobalOpenTelemetry.get()).build(); + tracing.buildAndFinishSpan(records); + return records; + } + + @Override + public void onCommit(Map offsets) {} + + @Override + public void close() {} + + @Override + public void configure(Map configs) {} +} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java new file mode 100644 index 000000000000..971f95347b0b --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java @@ -0,0 +1,30 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafkaclients; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import java.util.Map; +import org.apache.kafka.clients.producer.ProducerInterceptor; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.clients.producer.RecordMetadata; + +public class TracingProducerInterceptor implements ProducerInterceptor { + @Override + public ProducerRecord onSend(ProducerRecord producerRecord) { + KafkaTracing tracing = KafkaTracing.newBuilder(GlobalOpenTelemetry.get()).build(); + tracing.buildAndInjectSpan(producerRecord).run(); + return producerRecord; + } + + @Override + public void onAcknowledgement(RecordMetadata recordMetadata, Exception e) {} + + @Override + public void close() {} + + @Override + public void configure(Map map) {} +} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy new file mode 100644 index 000000000000..acc900122a64 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy @@ -0,0 +1,117 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafkaclients + +import io.opentelemetry.instrumentation.test.LibraryTestTrait +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes +import org.apache.kafka.clients.consumer.ConsumerConfig +import org.apache.kafka.clients.producer.ProducerConfig +import org.apache.kafka.clients.producer.ProducerRecord +import spock.lang.Unroll + +import java.time.Duration + +import static io.opentelemetry.api.trace.SpanKind.CONSUMER +import static io.opentelemetry.api.trace.SpanKind.INTERNAL +import static io.opentelemetry.api.trace.SpanKind.PRODUCER + +class InterceptorsTest extends KafkaClientBaseTest implements LibraryTestTrait { + + @Override + Map producerProps() { + def props = super.producerProps() + props.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingProducerInterceptor.getName()) + return props + } + + @Override + Map consumerProps() { + def props = super.consumerProps() + props.put(ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingConsumerInterceptor.getName()) + return props + } + + @Unroll + def "test interceptors"() throws Exception { + when: + String greeting = "Hello Kafka!" + runWithSpan("parent") { + producer.send(new ProducerRecord(SHARED_TOPIC, greeting)) { meta, ex -> + if (ex == null) { + runWithSpan("producer callback") {} + } else { + runWithSpan("producer exception: " + ex) {} + } + } + } + + then: + awaitUntilConsumerIsReady() + // check that the message was received + def records = consumer.poll(Duration.ofSeconds(5).toMillis()) + for (record in records) { + assert record.value() == greeting + assert record.key() == null + } + + assertTraces(3) { + traces.sort(orderByRootSpanKind(INTERNAL, PRODUCER, CONSUMER)) + trace(0, 2) { + span(0) { + name "parent" + kind INTERNAL + hasNoParent() + } + span(1) { + name SHARED_TOPIC + " send" + kind PRODUCER + childOf span(0) + attributes { + "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" + "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC + "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" + } + } + } + trace(1, 1) { + span(0) { + name "producer callback" + kind INTERNAL + hasNoParent() + } + } + trace(2, 2) { + span(0) { + name SHARED_TOPIC + " receive" + kind CONSUMER + hasNoParent() + attributes { + "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" + "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC + "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" + "${SemanticAttributes.MESSAGING_OPERATION.key}" "receive" + } + } + span(1) { + name SHARED_TOPIC + " process" + kind CONSUMER + childOf span(0) + attributes { + "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" + "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC + "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" + "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" + "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long + "${SemanticAttributes.MESSAGING_KAFKA_PARTITION.key}" { it >= 0 } + "kafka.offset" Long + "kafka.record.queue_time_ms" { it >= 0 } + } + } + } + } + } +} + diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/resources/log4j.properties b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/resources/log4j.properties new file mode 100644 index 000000000000..1ea4751367ed --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/resources/log4j.properties @@ -0,0 +1,5 @@ +# Set root logger level to INFO and its only appender to C1. +log4j.rootLogger=INFO, A1 + +# C1 is set to be a ConsoleAppender. +log4j.appender.C1=org.apache.log4j.ConsoleAppender diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/testing/build.gradle.kts b/instrumentation/kafka-clients/kafka-clients-0.11/testing/build.gradle.kts new file mode 100644 index 000000000000..2e285b3e9191 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/testing/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + id("otel.java-conventions") +} + +dependencies { + api(project(":testing-common")) + + implementation("org.apache.kafka:kafka-clients:0.11.0.0") + + implementation(project(":instrumentation:kafka-clients:kafka-clients-common:library")) + + implementation("org.testcontainers:kafka") +} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientBaseTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientBaseTest.groovy similarity index 88% rename from instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientBaseTest.groovy rename to instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientBaseTest.groovy index 74e57e13a2f2..323bad629a15 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/KafkaClientBaseTest.groovy +++ b/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientBaseTest.groovy @@ -3,7 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification +package io.opentelemetry.instrumentation.kafkaclients + +import io.opentelemetry.instrumentation.test.InstrumentationSpecification import org.apache.kafka.clients.admin.AdminClient import org.apache.kafka.clients.admin.NewTopic import org.apache.kafka.clients.consumer.Consumer @@ -25,13 +27,10 @@ import java.time.Duration import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit -abstract class KafkaClientBaseTest extends AgentInstrumentationSpecification { +abstract class KafkaClientBaseTest extends InstrumentationSpecification { protected static final SHARED_TOPIC = "shared.topic" - private static final boolean propagationEnabled = Boolean.parseBoolean( - System.getProperty("otel.instrumentation.kafka.client-propagation.enabled", "true")) - @Shared static KafkaContainer kafka @Shared @@ -50,8 +49,25 @@ abstract class KafkaClientBaseTest extends AgentInstrumentationSpecification { admin.createTopics([new NewTopic(SHARED_TOPIC, 1, (short) 1)]).all().get(10, TimeUnit.SECONDS) } + producer = new KafkaProducer<>(producerProps()) + + consumer = new KafkaConsumer<>(consumerProps()) + + consumer.subscribe([SHARED_TOPIC], new ConsumerRebalanceListener() { + @Override + void onPartitionsRevoked(Collection collection) { + } + + @Override + void onPartitionsAssigned(Collection collection) { + consumerReady.countDown() + } + }) + } + + Map producerProps() { // values copied from spring's KafkaTestUtils - def producerProps = [ + return [ "bootstrap.servers": kafka.bootstrapServers, "retries" : 0, "batch.size" : "16384", @@ -60,9 +76,11 @@ abstract class KafkaClientBaseTest extends AgentInstrumentationSpecification { "key.serializer" : IntegerSerializer, "value.serializer" : StringSerializer ] - producer = new KafkaProducer<>(producerProps) + } - def consumerProps = [ + Map consumerProps() { + // values copied from spring's KafkaTestUtils + return [ "bootstrap.servers" : kafka.bootstrapServers, "group.id" : "test", "enable.auto.commit" : "true", @@ -71,18 +89,6 @@ abstract class KafkaClientBaseTest extends AgentInstrumentationSpecification { "key.deserializer" : IntegerDeserializer, "value.deserializer" : StringDeserializer ] - consumer = new KafkaConsumer<>(consumerProps) - - consumer.subscribe([SHARED_TOPIC], new ConsumerRebalanceListener() { - @Override - void onPartitionsRevoked(Collection collection) { - } - - @Override - void onPartitionsAssigned(Collection collection) { - consumerReady.countDown() - } - }) } def cleanupSpec() { diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy new file mode 100644 index 000000000000..2ae00736ed3d --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy @@ -0,0 +1,30 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafkaclients + +import io.opentelemetry.instrumentation.test.AgentTestTrait +import org.apache.kafka.clients.producer.ProducerRecord +import spock.lang.Unroll + +abstract class KafkaClientPropagationBaseTest extends KafkaClientBaseTest implements AgentTestTrait { + + private static final boolean propagationEnabled = Boolean.parseBoolean( + System.getProperty("otel.instrumentation.kafka.client-propagation.enabled", "true")) + + @Unroll + def "test kafka client header propagation manual config"() { + when: + String message = "Testing without headers" + producer.send(new ProducerRecord<>(SHARED_TOPIC, message)) + + then: + // check that the message was received + def records = records(1) + for (record in records) { + assert record.headers().iterator().hasNext() == propagationEnabled + } + } +} \ No newline at end of file diff --git a/instrumentation/kafka-clients/kafka-clients-common/javaagent/build.gradle.kts b/instrumentation/kafka-clients/kafka-clients-common/javaagent/build.gradle.kts deleted file mode 100644 index c27944c21943..000000000000 --- a/instrumentation/kafka-clients/kafka-clients-common/javaagent/build.gradle.kts +++ /dev/null @@ -1,7 +0,0 @@ -plugins { - id("otel.javaagent-instrumentation") -} - -dependencies { - compileOnly("org.apache.kafka:kafka-clients:0.11.0.0") -} diff --git a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaHeadersSetter.java b/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaHeadersSetter.java deleted file mode 100644 index 1da267e8e7fb..000000000000 --- a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaHeadersSetter.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafka; - -import io.opentelemetry.context.propagation.TextMapSetter; -import java.nio.charset.StandardCharsets; -import org.apache.kafka.clients.producer.ProducerRecord; - -public final class KafkaHeadersSetter implements TextMapSetter> { - - @Override - public void set(ProducerRecord carrier, String key, String value) { - carrier.headers().remove(key).add(key, value.getBytes(StandardCharsets.UTF_8)); - } -} diff --git a/instrumentation/kafka-clients/kafka-clients-common/library/build.gradle.kts b/instrumentation/kafka-clients/kafka-clients-common/library/build.gradle.kts new file mode 100644 index 000000000000..780051761e57 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-common/library/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("otel.library-instrumentation") +} + +dependencies { + compileOnly("org.apache.kafka:kafka-clients:0.11.0.0") + compileOnly("com.google.auto.value:auto-value-annotations") + annotationProcessor("com.google.auto.value:auto-value") +} diff --git a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerAdditionalAttributesExtractor.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerAdditionalAttributesExtractor.java similarity index 94% rename from instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerAdditionalAttributesExtractor.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerAdditionalAttributesExtractor.java index 9cbb7047cea4..5c53e13c40bb 100644 --- a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerAdditionalAttributesExtractor.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerAdditionalAttributesExtractor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafka; +package io.opentelemetry.instrumentation.kafka; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; diff --git a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerAttributesExtractor.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerAttributesExtractor.java similarity index 97% rename from instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerAttributesExtractor.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerAttributesExtractor.java index 5de1a1af9904..b2603a5cc8c0 100644 --- a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerAttributesExtractor.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerAttributesExtractor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafka; +package io.opentelemetry.instrumentation.kafka; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor; diff --git a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerExperimentalAttributesExtractor.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerExperimentalAttributesExtractor.java similarity index 97% rename from instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerExperimentalAttributesExtractor.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerExperimentalAttributesExtractor.java index a7c1b768e96c..13fe3eadb9f9 100644 --- a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerExperimentalAttributesExtractor.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerExperimentalAttributesExtractor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafka; +package io.opentelemetry.instrumentation.kafka; import static io.opentelemetry.api.common.AttributeKey.longKey; diff --git a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerIterableWrapper.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerIterableWrapper.java similarity index 88% rename from instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerIterableWrapper.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerIterableWrapper.java index 257922265216..f9bcb9ae8695 100644 --- a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerIterableWrapper.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerIterableWrapper.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafka; +package io.opentelemetry.instrumentation.kafka; import org.apache.kafka.clients.consumer.ConsumerRecord; diff --git a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerIteratorWrapper.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerIteratorWrapper.java similarity index 88% rename from instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerIteratorWrapper.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerIteratorWrapper.java index b0f1bbfd626e..cc61022d316c 100644 --- a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaConsumerIteratorWrapper.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerIteratorWrapper.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafka; +package io.opentelemetry.instrumentation.kafka; import java.util.Iterator; import org.apache.kafka.clients.consumer.ConsumerRecord; diff --git a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaHeadersGetter.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerRecordGetter.java similarity index 87% rename from instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaHeadersGetter.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerRecordGetter.java index b114a2671889..fd28fb8d856a 100644 --- a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaHeadersGetter.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaConsumerRecordGetter.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafka; +package io.opentelemetry.instrumentation.kafka; import io.opentelemetry.context.propagation.TextMapGetter; import java.nio.charset.StandardCharsets; @@ -13,8 +13,7 @@ import org.apache.kafka.common.header.Header; import org.checkerframework.checker.nullness.qual.Nullable; -public final class KafkaHeadersGetter implements TextMapGetter> { - +public final class KafkaConsumerRecordGetter implements TextMapGetter> { @Override public Iterable keys(ConsumerRecord carrier) { return StreamSupport.stream(carrier.headers().spliterator(), false) diff --git a/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaHeadersGetter.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaHeadersGetter.java new file mode 100644 index 000000000000..62244aaaafa4 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaHeadersGetter.java @@ -0,0 +1,37 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafka; + +import io.opentelemetry.context.propagation.TextMapGetter; +import java.nio.charset.StandardCharsets; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; +import org.apache.kafka.common.header.Header; +import org.apache.kafka.common.header.Headers; +import org.checkerframework.checker.nullness.qual.Nullable; + +public final class KafkaHeadersGetter implements TextMapGetter { + @Override + public Iterable keys(Headers carrier) { + return StreamSupport.stream(carrier.spliterator(), false) + .map(Header::key) + .collect(Collectors.toList()); + } + + @Nullable + @Override + public String get(@Nullable Headers carrier, String key) { + Header header = carrier.lastHeader(key); + if (header == null) { + return null; + } + byte[] value = header.value(); + if (value == null) { + return null; + } + return new String(value, StandardCharsets.UTF_8); + } +} diff --git a/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaHeadersSetter.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaHeadersSetter.java new file mode 100644 index 000000000000..f26c17d87f27 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaHeadersSetter.java @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafka; + +import io.opentelemetry.context.propagation.TextMapSetter; +import java.nio.charset.StandardCharsets; +import org.apache.kafka.common.header.Headers; + +public final class KafkaHeadersSetter implements TextMapSetter { + + @Override + public void set(Headers headers, String key, String value) { + headers.remove(key).add(key, value.getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerAdditionalAttributesExtractor.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaProducerAdditionalAttributesExtractor.java similarity index 94% rename from instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerAdditionalAttributesExtractor.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaProducerAdditionalAttributesExtractor.java index 1a83c7c862ee..fd91c8081b74 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerAdditionalAttributesExtractor.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaProducerAdditionalAttributesExtractor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafkaclients; +package io.opentelemetry.instrumentation.kafka; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerAttributesExtractor.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaProducerAttributesExtractor.java similarity index 96% rename from instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerAttributesExtractor.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaProducerAttributesExtractor.java index 3d3402cde666..bce52c377bee 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerAttributesExtractor.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaProducerAttributesExtractor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafkaclients; +package io.opentelemetry.instrumentation.kafka; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor; diff --git a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaPropagation.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaPropagation.java similarity index 92% rename from instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaPropagation.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaPropagation.java index 1037ca4a18f8..7e3e44afe826 100644 --- a/instrumentation/kafka-clients/kafka-clients-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafka/KafkaPropagation.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaPropagation.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafka; +package io.opentelemetry.instrumentation.kafka; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.context.Context; @@ -56,7 +56,9 @@ record = } private static void inject(Context context, ProducerRecord record) { - GlobalOpenTelemetry.getPropagators().getTextMapPropagator().inject(context, record, SETTER); + GlobalOpenTelemetry.getPropagators() + .getTextMapPropagator() + .inject(context, record.headers(), SETTER); } private KafkaPropagation() {} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaReceiveAttributesExtractor.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaReceiveAttributesExtractor.java similarity index 97% rename from instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaReceiveAttributesExtractor.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaReceiveAttributesExtractor.java index d22b8ca9df33..45a1b7b40664 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaReceiveAttributesExtractor.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaReceiveAttributesExtractor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafkaclients; +package io.opentelemetry.instrumentation.kafka; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor; diff --git a/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaSingletons.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaSingletons.java new file mode 100644 index 000000000000..b5863d8bc856 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaSingletons.java @@ -0,0 +1,39 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafka; + +import static io.opentelemetry.instrumentation.kafka.KafkaUtils.buildConsumerProcessInstrumenter; +import static io.opentelemetry.instrumentation.kafka.KafkaUtils.buildConsumerReceiveInstrumenter; +import static io.opentelemetry.instrumentation.kafka.KafkaUtils.buildProducerInstrumenter; + +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.producer.ProducerRecord; + +public final class KafkaSingletons { + public static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11"; + + private static final Instrumenter, Void> PRODUCER_INSTRUMENTER = + buildProducerInstrumenter(INSTRUMENTATION_NAME); + private static final Instrumenter CONSUMER_RECEIVE_INSTRUMENTER = + buildConsumerReceiveInstrumenter(INSTRUMENTATION_NAME); + private static final Instrumenter, Void> CONSUMER_PROCESS_INSTRUMENTER = + buildConsumerProcessInstrumenter(INSTRUMENTATION_NAME); + + public static Instrumenter, Void> producerInstrumenter() { + return PRODUCER_INSTRUMENTER; + } + + public static Instrumenter consumerReceiveInstrumenter() { + return CONSUMER_RECEIVE_INSTRUMENTER; + } + + public static Instrumenter, Void> consumerProcessInstrumenter() { + return CONSUMER_PROCESS_INSTRUMENTER; + } + + private KafkaSingletons() {} +} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaUtils.java similarity index 58% rename from instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaUtils.java index 7b40fad81d36..b1984dc25567 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaUtils.java @@ -3,10 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafkaclients; +package io.opentelemetry.instrumentation.kafka; import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.config.ExperimentalConfig; +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.SpanKindExtractor; @@ -14,50 +16,64 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingSpanNameExtractor; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaConsumerAdditionalAttributesExtractor; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaConsumerAttributesExtractor; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaConsumerExperimentalAttributesExtractor; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaHeadersGetter; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaPropagation; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.producer.ProducerRecord; -public final class KafkaSingletons { - private static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11"; +@SuppressWarnings("unchecked") +public final class KafkaUtils { - private static final Instrumenter, Void> PRODUCER_INSTRUMENTER = - buildProducerInstrumenter(); - private static final Instrumenter CONSUMER_RECEIVE_INSTRUMENTER = - buildConsumerReceiveInstrumenter(); - private static final Instrumenter, Void> CONSUMER_PROCESS_INSTRUMENTER = - buildConsumerProcessInstrumenter(); + static Instrumenter, Void> buildProducerInstrumenter( + String instrumentationName) { + return buildProducerInstrumenter(instrumentationName, GlobalOpenTelemetry.get()); + } - private static Instrumenter, Void> buildProducerInstrumenter() { + public static Instrumenter, Void> buildProducerInstrumenter( + String instrumentationName, + OpenTelemetry openTelemetry, + AttributesExtractor, Void>... extractors) { KafkaProducerAttributesExtractor attributesExtractor = new KafkaProducerAttributesExtractor(); SpanNameExtractor> spanNameExtractor = MessagingSpanNameExtractor.create(attributesExtractor); return Instrumenter., Void>newBuilder( - GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanNameExtractor) + openTelemetry, instrumentationName, spanNameExtractor) .addAttributesExtractor(attributesExtractor) + .addAttributesExtractors(extractors) .addAttributesExtractor(new KafkaProducerAdditionalAttributesExtractor()) .newInstrumenter(SpanKindExtractor.alwaysProducer()); } - private static Instrumenter buildConsumerReceiveInstrumenter() { + static Instrumenter buildConsumerReceiveInstrumenter( + String instrumentationName) { + return buildConsumerReceiveInstrumenter(instrumentationName, GlobalOpenTelemetry.get()); + } + + public static Instrumenter buildConsumerReceiveInstrumenter( + String instrumentationName, + OpenTelemetry openTelemetry, + AttributesExtractor... extractors) { KafkaReceiveAttributesExtractor attributesExtractor = new KafkaReceiveAttributesExtractor(); SpanNameExtractor spanNameExtractor = MessagingSpanNameExtractor.create(attributesExtractor); return Instrumenter.newBuilder( - GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanNameExtractor) + openTelemetry, instrumentationName, spanNameExtractor) .addAttributesExtractor(attributesExtractor) + .addAttributesExtractors(extractors) .setTimeExtractors(ReceivedRecords::startTime, (request, response, error) -> request.now()) .setDisabled(ExperimentalConfig.get().suppressMessagingReceiveSpans()) .newInstrumenter(SpanKindExtractor.alwaysConsumer()); } - private static Instrumenter, Void> buildConsumerProcessInstrumenter() { + static Instrumenter, Void> buildConsumerProcessInstrumenter( + String instrumentationName) { + return buildConsumerProcessInstrumenter(instrumentationName, GlobalOpenTelemetry.get()); + } + + public static Instrumenter, Void> buildConsumerProcessInstrumenter( + String instrumentationName, + OpenTelemetry openTelemetry, + AttributesExtractor, Void>... extractors) { KafkaConsumerAttributesExtractor attributesExtractor = new KafkaConsumerAttributesExtractor(MessageOperation.PROCESS); SpanNameExtractor> spanNameExtractor = @@ -65,9 +81,10 @@ private static Instrumenter buildConsumerReceiveInstrumen InstrumenterBuilder, Void> builder = Instrumenter., Void>newBuilder( - GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanNameExtractor) + openTelemetry, instrumentationName, spanNameExtractor) .addAttributesExtractor(attributesExtractor) - .addAttributesExtractor(new KafkaConsumerAdditionalAttributesExtractor()); + .addAttributesExtractor(new KafkaConsumerAdditionalAttributesExtractor()) + .addAttributesExtractors(extractors); if (KafkaConsumerExperimentalAttributesExtractor.isEnabled()) { builder.addAttributesExtractor(new KafkaConsumerExperimentalAttributesExtractor()); } @@ -75,26 +92,14 @@ private static Instrumenter buildConsumerReceiveInstrumen if (!KafkaPropagation.isPropagationEnabled()) { return builder.newInstrumenter(SpanKindExtractor.alwaysConsumer()); } else if (ExperimentalConfig.get().suppressMessagingReceiveSpans()) { - return builder.newConsumerInstrumenter(new KafkaHeadersGetter()); + return builder.newConsumerInstrumenter(new KafkaConsumerRecordGetter()); } else { builder.addSpanLinksExtractor( SpanLinksExtractor.fromUpstreamRequest( - GlobalOpenTelemetry.getPropagators(), new KafkaHeadersGetter())); + GlobalOpenTelemetry.getPropagators(), new KafkaConsumerRecordGetter())); return builder.newInstrumenter(SpanKindExtractor.alwaysConsumer()); } } - public static Instrumenter, Void> producerInstrumenter() { - return PRODUCER_INSTRUMENTER; - } - - public static Instrumenter consumerReceiveInstrumenter() { - return CONSUMER_RECEIVE_INSTRUMENTER; - } - - public static Instrumenter, Void> consumerProcessInstrumenter() { - return CONSUMER_PROCESS_INSTRUMENTER; - } - - private KafkaSingletons() {} + private KafkaUtils() {} } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ReceivedRecords.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/ReceivedRecords.java similarity index 90% rename from instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ReceivedRecords.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/ReceivedRecords.java index 260457c32d94..8ff29b32414d 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ReceivedRecords.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/ReceivedRecords.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafkaclients; +package io.opentelemetry.instrumentation.kafka; import com.google.auto.value.AutoValue; import java.time.Instant; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/Timer.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/Timer.java similarity index 90% rename from instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/Timer.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/Timer.java index 42b3bc819910..835bb3c65c00 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/Timer.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/Timer.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.kafkaclients; +package io.opentelemetry.instrumentation.kafka; import java.time.Instant; diff --git a/instrumentation/kafka-streams-0.11/javaagent/build.gradle.kts b/instrumentation/kafka-streams-0.11/javaagent/build.gradle.kts index d29de9126d96..0909c6e3ca27 100644 --- a/instrumentation/kafka-streams-0.11/javaagent/build.gradle.kts +++ b/instrumentation/kafka-streams-0.11/javaagent/build.gradle.kts @@ -12,7 +12,7 @@ muzzle { } dependencies { - implementation(project(":instrumentation:kafka-clients:kafka-clients-common:javaagent")) + implementation(project(":instrumentation:kafka-clients:kafka-clients-common:library")) library("org.apache.kafka:kafka-streams:0.11.0.0") diff --git a/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java b/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java index aa7845d9b760..3dad14fb4be1 100644 --- a/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java +++ b/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java @@ -14,11 +14,11 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingSpanNameExtractor; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaConsumerAdditionalAttributesExtractor; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaConsumerAttributesExtractor; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaConsumerExperimentalAttributesExtractor; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaHeadersGetter; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaPropagation; +import io.opentelemetry.instrumentation.kafka.KafkaConsumerAdditionalAttributesExtractor; +import io.opentelemetry.instrumentation.kafka.KafkaConsumerAttributesExtractor; +import io.opentelemetry.instrumentation.kafka.KafkaConsumerExperimentalAttributesExtractor; +import io.opentelemetry.instrumentation.kafka.KafkaConsumerRecordGetter; +import io.opentelemetry.instrumentation.kafka.KafkaPropagation; import org.apache.kafka.clients.consumer.ConsumerRecord; public final class KafkaStreamsSingletons { @@ -45,11 +45,11 @@ public final class KafkaStreamsSingletons { if (!KafkaPropagation.isPropagationEnabled()) { return builder.newInstrumenter(SpanKindExtractor.alwaysConsumer()); } else if (ExperimentalConfig.get().suppressMessagingReceiveSpans()) { - return builder.newConsumerInstrumenter(new KafkaHeadersGetter()); + return builder.newConsumerInstrumenter(new KafkaConsumerRecordGetter()); } else { builder.addSpanLinksExtractor( SpanLinksExtractor.fromUpstreamRequest( - GlobalOpenTelemetry.getPropagators(), new KafkaHeadersGetter())); + GlobalOpenTelemetry.getPropagators(), new KafkaConsumerRecordGetter())); return builder.newInstrumenter(SpanKindExtractor.alwaysConsumer()); } } diff --git a/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamTaskInstrumentation.java b/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamTaskInstrumentation.java index 840f9547baa5..96c9f7e7ba32 100644 --- a/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamTaskInstrumentation.java +++ b/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamTaskInstrumentation.java @@ -12,9 +12,9 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.kafka.KafkaConsumerIterableWrapper; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaConsumerIterableWrapper; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; diff --git a/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamThreadInstrumentation.java b/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamThreadInstrumentation.java index 44bbd64b5cfd..3970786fa71b 100644 --- a/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamThreadInstrumentation.java +++ b/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamThreadInstrumentation.java @@ -10,11 +10,11 @@ import static net.bytebuddy.matcher.ElementMatchers.returns; import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.instrumentation.kafka.KafkaConsumerIteratorWrapper; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import io.opentelemetry.javaagent.instrumentation.api.ContextStore; import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaConsumerIteratorWrapper; import java.util.Iterator; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; diff --git a/instrumentation/spring/spring-kafka-2.7/javaagent/build.gradle.kts b/instrumentation/spring/spring-kafka-2.7/javaagent/build.gradle.kts index 3ccceb4c6e44..07edbfb9a854 100644 --- a/instrumentation/spring/spring-kafka-2.7/javaagent/build.gradle.kts +++ b/instrumentation/spring/spring-kafka-2.7/javaagent/build.gradle.kts @@ -15,7 +15,7 @@ dependencies { compileOnly("com.google.auto.value:auto-value-annotations") annotationProcessor("com.google.auto.value:auto-value") - implementation(project(":instrumentation:kafka-clients:kafka-clients-common:javaagent")) + implementation(project(":instrumentation:kafka-clients:kafka-clients-common:library")) library("org.springframework.kafka:spring-kafka:2.7.0") diff --git a/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/KafkaBatchProcessSpanLinksExtractor.java b/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/KafkaBatchProcessSpanLinksExtractor.java index af560b86646a..3b49bc4ceb79 100644 --- a/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/KafkaBatchProcessSpanLinksExtractor.java +++ b/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/KafkaBatchProcessSpanLinksExtractor.java @@ -9,8 +9,8 @@ import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.instrumentation.api.instrumenter.SpanLinksBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaConsumerIteratorWrapper; -import io.opentelemetry.javaagent.instrumentation.kafka.KafkaHeadersGetter; +import io.opentelemetry.instrumentation.kafka.KafkaConsumerIteratorWrapper; +import io.opentelemetry.instrumentation.kafka.KafkaConsumerRecordGetter; import java.util.Iterator; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; @@ -22,7 +22,7 @@ public class KafkaBatchProcessSpanLinksExtractor public KafkaBatchProcessSpanLinksExtractor(ContextPropagators contextPropagators) { this.singleRecordLinkExtractor = - SpanLinksExtractor.fromUpstreamRequest(contextPropagators, new KafkaHeadersGetter()); + SpanLinksExtractor.fromUpstreamRequest(contextPropagators, new KafkaConsumerRecordGetter()); } @Override diff --git a/settings.gradle.kts b/settings.gradle.kts index d6d75e93feaf..035df2b71864 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -218,7 +218,10 @@ include(":instrumentation:jsf:mojarra-1.2:javaagent") include(":instrumentation:jsf:myfaces-1.2:javaagent") include(":instrumentation:jsp-2.3:javaagent") include(":instrumentation:kafka-clients:kafka-clients-0.11:javaagent") -include(":instrumentation:kafka-clients:kafka-clients-common:javaagent") +include(":instrumentation:kafka-clients:kafka-clients-0.11:library") +include(":instrumentation:kafka-clients:kafka-clients-0.11:testing") +include(":instrumentation:kafka-clients:kafka-clients-2.4.0-testing") +include(":instrumentation:kafka-clients:kafka-clients-common:library") include(":instrumentation:kafka-streams-0.11:javaagent") include(":instrumentation:kotlinx-coroutines:javaagent") include(":instrumentation:kubernetes-client-7.0:javaagent") From 673aca0a27e8bc2217a10041fffe67d595e078f5 Mon Sep 17 00:00:00 2001 From: Ales Justin Date: Wed, 22 Sep 2021 20:37:11 +0200 Subject: [PATCH 2/7] Apply feedback --- .../KafkaConsumerInstrumentation.java | 2 +- .../KafkaProducerInstrumentation.java | 2 +- .../kafkaclients}/KafkaSingletons.java | 16 ++-- .../kafkaclients/ProducerCallback.java | 2 +- .../kafkaclients/TracingIterator.java | 2 +- .../KafkaClientDefaultTest.groovy | 3 +- .../kafkaclients/KafkaTracing.java | 82 ++++++------------- .../kafkaclients/KafkaTracingBuilder.java | 28 ++----- .../kafkaclients/KafkaTracingHolder.java | 20 +++++ .../TracingConsumerInterceptor.java | 7 +- .../TracingProducerInterceptor.java | 7 +- .../kafkaclients/InterceptorsTest.groovy | 13 +-- .../kafkaclients/KafkaClientBaseTest.groovy | 22 +---- .../KafkaClientPropagationBaseTest.groovy | 5 +- .../instrumentation/kafka/KafkaUtils.java | 14 ++-- 15 files changed, 85 insertions(+), 140 deletions(-) rename instrumentation/kafka-clients/{kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka => kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients}/KafkaSingletons.java (66%) create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerInstrumentation.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerInstrumentation.java index 669e70d77068..d028f8701105 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerInstrumentation.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerInstrumentation.java @@ -5,9 +5,9 @@ package io.opentelemetry.javaagent.instrumentation.kafkaclients; -import static io.opentelemetry.instrumentation.kafka.KafkaSingletons.consumerReceiveInstrumenter; import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.spanFromContext; +import static io.opentelemetry.javaagent.instrumentation.kafkaclients.KafkaSingletons.consumerReceiveInstrumenter; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerInstrumentation.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerInstrumentation.java index c8582fed0945..01961075a306 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerInstrumentation.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerInstrumentation.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.kafkaclients; -import static io.opentelemetry.instrumentation.kafka.KafkaSingletons.producerInstrumenter; +import static io.opentelemetry.javaagent.instrumentation.kafkaclients.KafkaSingletons.producerInstrumenter; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; diff --git a/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaSingletons.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java similarity index 66% rename from instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaSingletons.java rename to instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java index b5863d8bc856..8fc22f5a203d 100644 --- a/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaSingletons.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java @@ -3,25 +3,23 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.kafka; - -import static io.opentelemetry.instrumentation.kafka.KafkaUtils.buildConsumerProcessInstrumenter; -import static io.opentelemetry.instrumentation.kafka.KafkaUtils.buildConsumerReceiveInstrumenter; -import static io.opentelemetry.instrumentation.kafka.KafkaUtils.buildProducerInstrumenter; +package io.opentelemetry.javaagent.instrumentation.kafkaclients; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.kafka.KafkaUtils; +import io.opentelemetry.instrumentation.kafka.ReceivedRecords; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.producer.ProducerRecord; public final class KafkaSingletons { - public static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11"; + public static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11.javaagent"; private static final Instrumenter, Void> PRODUCER_INSTRUMENTER = - buildProducerInstrumenter(INSTRUMENTATION_NAME); + KafkaUtils.buildProducerInstrumenter(INSTRUMENTATION_NAME); private static final Instrumenter CONSUMER_RECEIVE_INSTRUMENTER = - buildConsumerReceiveInstrumenter(INSTRUMENTATION_NAME); + KafkaUtils.buildConsumerReceiveInstrumenter(INSTRUMENTATION_NAME); private static final Instrumenter, Void> CONSUMER_PROCESS_INSTRUMENTER = - buildConsumerProcessInstrumenter(INSTRUMENTATION_NAME); + KafkaUtils.buildConsumerProcessInstrumenter(INSTRUMENTATION_NAME); public static Instrumenter, Void> producerInstrumenter() { return PRODUCER_INSTRUMENTER; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ProducerCallback.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ProducerCallback.java index 785ef08d4d90..a500724b8e6c 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ProducerCallback.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ProducerCallback.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.kafkaclients; -import static io.opentelemetry.instrumentation.kafka.KafkaSingletons.producerInstrumenter; +import static io.opentelemetry.javaagent.instrumentation.kafkaclients.KafkaSingletons.producerInstrumenter; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterator.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterator.java index b6f35835aae0..b7c812287c04 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterator.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterator.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.kafkaclients; -import static io.opentelemetry.instrumentation.kafka.KafkaSingletons.consumerProcessInstrumenter; +import static io.opentelemetry.javaagent.instrumentation.kafkaclients.KafkaSingletons.consumerProcessInstrumenter; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientDefaultTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientDefaultTest.groovy index ab4cae1a9091..bac2e8900c9b 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientDefaultTest.groovy +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientDefaultTest.groovy @@ -8,7 +8,6 @@ package io.opentelemetry.instrumentation.kafkaclients import io.opentelemetry.sdk.trace.data.SpanData import io.opentelemetry.semconv.trace.attributes.SemanticAttributes import org.apache.kafka.clients.producer.ProducerRecord -import org.apache.kafka.common.TopicPartition import java.time.Duration import java.util.concurrent.TimeUnit @@ -192,7 +191,7 @@ class KafkaClientDefaultTest extends KafkaClientPropagationBaseTest { when: "receive messages" awaitUntilConsumerIsReady() def consumerRecords = consumer.poll(Duration.ofSeconds(5).toMillis()) - def recordsInPartition = consumerRecords.records(new TopicPartition(SHARED_TOPIC, partition)) + def recordsInPartition = consumerRecords.records(topicPartition) recordsInPartition.size() == 1 // iterate over records to generate spans diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java index 80f7cc761704..ccdfbe794e43 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java @@ -16,10 +16,6 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.kafka.KafkaHeadersGetter; import io.opentelemetry.instrumentation.kafka.KafkaHeadersSetter; -import io.opentelemetry.instrumentation.kafka.KafkaSingletons; -import io.opentelemetry.instrumentation.kafka.ReceivedRecords; -import io.opentelemetry.instrumentation.kafka.Timer; -import java.util.Objects; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.clients.producer.ProducerRecord; @@ -28,6 +24,7 @@ import org.slf4j.LoggerFactory; public class KafkaTracing { + public static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11.library"; private static final Logger logger = LoggerFactory.getLogger(KafkaTracing.class); @@ -35,16 +32,17 @@ public class KafkaTracing { private static final TextMapSetter SETTER = new KafkaHeadersSetter(); - private Instrumenter, Void> producerInstrumenter = - KafkaSingletons.producerInstrumenter(); - private Instrumenter consumerReceiveInstrumenter = - KafkaSingletons.consumerReceiveInstrumenter(); - private Instrumenter, Void> consumerProcessInstrumenter = - KafkaSingletons.consumerProcessInstrumenter(); + private final Instrumenter, Void> producerInstrumenter; + private final Instrumenter, Void> consumerProcessInstrumenter; - KafkaTracing() {} + KafkaTracing( + Instrumenter, Void> producerInstrumenter, + Instrumenter, Void> consumerProcessInstrumenter) { + this.producerInstrumenter = producerInstrumenter; + this.consumerProcessInstrumenter = consumerProcessInstrumenter; + } - public static KafkaTracingBuilder newBuilder(OpenTelemetry openTelemetry) { + public static KafkaTracingBuilder create(OpenTelemetry openTelemetry) { return new KafkaTracingBuilder(openTelemetry); } @@ -52,34 +50,23 @@ private static TextMapPropagator propagator() { return GlobalOpenTelemetry.getPropagators().getTextMapPropagator(); } - void setProducerInstrumenter(Instrumenter, Void> producerInstrumenter) { - this.producerInstrumenter = Objects.requireNonNull(producerInstrumenter); - } - - void setConsumerReceiveInstrumenter(Instrumenter consumerInstrumenter) { - this.consumerReceiveInstrumenter = Objects.requireNonNull(consumerInstrumenter); - } - - void setConsumerProcessInstrumenter( - Instrumenter, Void> consumerInstrumenter) { - this.consumerProcessInstrumenter = Objects.requireNonNull(consumerInstrumenter); - } - /** * Build and inject span into record. Return Runnable handle to end the current span. * * @param record the producer record to inject span info. * @return runnable to close the current span */ - public Runnable buildAndInjectSpan(ProducerRecord record) { - if (!producerInstrumenter.shouldStart(Context.current(), record)) { + Runnable buildAndInjectSpan(ProducerRecord record) { + Context currentContext = Context.current(); + + if (!producerInstrumenter.shouldStart(currentContext, record)) { return () -> {}; } - Context current = producerInstrumenter.start(Context.current(), record); + Context current = producerInstrumenter.start(currentContext, record); try (Scope ignored = current.makeCurrent()) { try { - propagator().inject(Context.current(), record.headers(), SETTER); + propagator().inject(current, record.headers(), SETTER); } catch (Throwable t) { // it can happen if headers are read only (when record is sent second time) logger.error("failed to inject span context. sending record second time?", t); @@ -89,37 +76,18 @@ public Runnable buildAndInjectSpan(ProducerRecord record) { return () -> producerInstrumenter.end(current, record, null, null); } - public void buildAndFinishSpan(ConsumerRecords records) { - ReceivedRecords receivedRecords = ReceivedRecords.create(records, Timer.start()); + void buildAndFinishSpan(ConsumerRecords records) { + Context currentContext = Context.current(); + for (ConsumerRecord record : records) { + Context linkedContext = propagator().extract(currentContext, record.headers(), GETTER); + currentContext.with(Span.fromContext(linkedContext)); - if (!consumerReceiveInstrumenter.shouldStart(Context.current(), receivedRecords)) { - return; - } - - Context context = consumerReceiveInstrumenter.start(Context.current(), receivedRecords); - try (Scope ignored = context.makeCurrent()) { - for (ConsumerRecord record : records) { - buildAndFinishChildSpan(record); + if (!consumerProcessInstrumenter.shouldStart(currentContext, record)) { + continue; } - consumerReceiveInstrumenter.end(context, receivedRecords, null, null); - } catch (RuntimeException e) { - consumerReceiveInstrumenter.end(context, receivedRecords, null, e); - } - } - private void buildAndFinishChildSpan(ConsumerRecord record) { - Context linkedContext = propagator().extract(Context.current(), record.headers(), GETTER); - Context.current().with(Span.fromContext(linkedContext)); - - if (!consumerProcessInstrumenter.shouldStart(Context.current(), record)) { - return; + Context current = consumerProcessInstrumenter.start(currentContext, record); + consumerProcessInstrumenter.end(current, record, null, null); } - - Context current = consumerProcessInstrumenter.start(Context.current(), record); - consumerProcessInstrumenter.end(current, record, null, null); - - // Inject created span context into record headers for extraction by client to continue span - // chain - propagator().inject(current, record.headers(), SETTER); // TODO -- OK? } } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java index 4d764f2ff351..40ef7101e883 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java @@ -7,9 +7,8 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.kafka.KafkaSingletons; +import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.instrumentation.kafka.KafkaUtils; -import io.opentelemetry.instrumentation.kafka.ReceivedRecords; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -20,8 +19,6 @@ public class KafkaTracingBuilder { private final OpenTelemetry openTelemetry; private final List, Void>> producerExtractors = new ArrayList<>(); - private final List> consumerReceiveExtractors = - new ArrayList<>(); private final List, Void>> consumerProcessExtractors = new ArrayList<>(); @@ -33,10 +30,6 @@ public void addProducerExtractors(AttributesExtractor, Void producerExtractors.add(extractor); } - public void addConsumerReceiveExtractors(AttributesExtractor extractor) { - consumerReceiveExtractors.add(extractor); - } - public void addConsumerProcessExtractors( AttributesExtractor, Void> extractor) { consumerProcessExtractors.add(extractor); @@ -44,22 +37,15 @@ public void addConsumerProcessExtractors( @SuppressWarnings("unchecked") public KafkaTracing build() { - KafkaTracing tracing = new KafkaTracing(); - tracing.setProducerInstrumenter( + return new KafkaTracing( KafkaUtils.buildProducerInstrumenter( - KafkaSingletons.INSTRUMENTATION_NAME, - openTelemetry, - producerExtractors.toArray(new AttributesExtractor[0]))); - tracing.setConsumerReceiveInstrumenter( - KafkaUtils.buildConsumerReceiveInstrumenter( - KafkaSingletons.INSTRUMENTATION_NAME, + KafkaTracing.INSTRUMENTATION_NAME, openTelemetry, - consumerReceiveExtractors.toArray(new AttributesExtractor[0]))); - tracing.setConsumerProcessInstrumenter( - KafkaUtils.buildConsumerProcessInstrumenter( - KafkaSingletons.INSTRUMENTATION_NAME, + producerExtractors.toArray(new AttributesExtractor[0])), + KafkaUtils.buildConsumerOperationInstrumenter( + KafkaTracing.INSTRUMENTATION_NAME, openTelemetry, + MessageOperation.RECEIVE, consumerProcessExtractors.toArray(new AttributesExtractor[0]))); - return tracing; } } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java new file mode 100644 index 000000000000..6d75e1469592 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java @@ -0,0 +1,20 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafkaclients; + +import io.opentelemetry.api.GlobalOpenTelemetry; + +abstract class KafkaTracingHolder { + + private KafkaTracing tracing; + + public synchronized KafkaTracing getTracing() { + if (tracing == null) { + tracing = KafkaTracing.create(GlobalOpenTelemetry.get()).build(); + } + return tracing; + } +} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java index 83b60e101b22..05d3492a4298 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java @@ -5,19 +5,18 @@ package io.opentelemetry.instrumentation.kafkaclients; -import io.opentelemetry.api.GlobalOpenTelemetry; import java.util.Map; import org.apache.kafka.clients.consumer.ConsumerInterceptor; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.clients.consumer.OffsetAndMetadata; import org.apache.kafka.common.TopicPartition; -public class TracingConsumerInterceptor implements ConsumerInterceptor { +public class TracingConsumerInterceptor extends KafkaTracingHolder + implements ConsumerInterceptor { @Override public ConsumerRecords onConsume(ConsumerRecords records) { - KafkaTracing tracing = KafkaTracing.newBuilder(GlobalOpenTelemetry.get()).build(); - tracing.buildAndFinishSpan(records); + getTracing().buildAndFinishSpan(records); return records; } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java index 971f95347b0b..ea9b906d2d1a 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java @@ -5,17 +5,16 @@ package io.opentelemetry.instrumentation.kafkaclients; -import io.opentelemetry.api.GlobalOpenTelemetry; import java.util.Map; import org.apache.kafka.clients.producer.ProducerInterceptor; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.clients.producer.RecordMetadata; -public class TracingProducerInterceptor implements ProducerInterceptor { +public class TracingProducerInterceptor extends KafkaTracingHolder + implements ProducerInterceptor { @Override public ProducerRecord onSend(ProducerRecord producerRecord) { - KafkaTracing tracing = KafkaTracing.newBuilder(GlobalOpenTelemetry.get()).build(); - tracing.buildAndInjectSpan(producerRecord).run(); + getTracing().buildAndInjectSpan(producerRecord).run(); return producerRecord; } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy index acc900122a64..54ddd8d71b17 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy @@ -83,7 +83,7 @@ class InterceptorsTest extends KafkaClientBaseTest implements LibraryTestTrait { hasNoParent() } } - trace(2, 2) { + trace(2, 1) { span(0) { name SHARED_TOPIC + " receive" kind CONSUMER @@ -93,17 +93,6 @@ class InterceptorsTest extends KafkaClientBaseTest implements LibraryTestTrait { "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" "${SemanticAttributes.MESSAGING_OPERATION.key}" "receive" - } - } - span(1) { - name SHARED_TOPIC + " process" - kind CONSUMER - childOf span(0) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long "${SemanticAttributes.MESSAGING_KAFKA_PARTITION.key}" { it >= 0 } "kafka.offset" Long diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientBaseTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientBaseTest.groovy index 323bad629a15..d91a90883d72 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientBaseTest.groovy +++ b/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientBaseTest.groovy @@ -13,7 +13,6 @@ import org.apache.kafka.clients.consumer.ConsumerRebalanceListener import org.apache.kafka.clients.consumer.KafkaConsumer import org.apache.kafka.clients.producer.KafkaProducer import org.apache.kafka.clients.producer.Producer -import org.apache.kafka.clients.producer.ProducerRecord import org.apache.kafka.common.TopicPartition import org.apache.kafka.common.serialization.IntegerDeserializer import org.apache.kafka.common.serialization.IntegerSerializer @@ -21,9 +20,7 @@ import org.apache.kafka.common.serialization.StringDeserializer import org.apache.kafka.common.serialization.StringSerializer import org.testcontainers.containers.KafkaContainer import spock.lang.Shared -import spock.lang.Unroll -import java.time.Duration import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit @@ -40,6 +37,8 @@ abstract class KafkaClientBaseTest extends InstrumentationSpecification { @Shared static CountDownLatch consumerReady = new CountDownLatch(1) + static TopicPartition topicPartition = new TopicPartition(SHARED_TOPIC, 0) + def setupSpec() { kafka = new KafkaContainer() kafka.start() @@ -97,23 +96,6 @@ abstract class KafkaClientBaseTest extends InstrumentationSpecification { kafka.stop() } - @Unroll - def "test kafka client header propagation manual config"() { - when: - String message = "Testing without headers" - producer.send(new ProducerRecord<>(SHARED_TOPIC, message)) - .get(5, TimeUnit.SECONDS) - - then: - awaitUntilConsumerIsReady() - - def records = consumer.poll(Duration.ofSeconds(1).toMillis()) - records.count() == 1 - for (record in records) { - assert record.headers().iterator().hasNext() == propagationEnabled - } - } - // Kafka's eventual consistency behavior forces us to do a couple of empty poll() calls until it gets properly assigned a topic partition static void awaitUntilConsumerIsReady() { if (consumerReady.await(0, TimeUnit.SECONDS)) { diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy index 2ae00736ed3d..78e175e69f7c 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy +++ b/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy @@ -9,6 +9,8 @@ import io.opentelemetry.instrumentation.test.AgentTestTrait import org.apache.kafka.clients.producer.ProducerRecord import spock.lang.Unroll +import java.time.Duration + abstract class KafkaClientPropagationBaseTest extends KafkaClientBaseTest implements AgentTestTrait { private static final boolean propagationEnabled = Boolean.parseBoolean( @@ -21,8 +23,9 @@ abstract class KafkaClientPropagationBaseTest extends KafkaClientBaseTest implem producer.send(new ProducerRecord<>(SHARED_TOPIC, message)) then: + awaitUntilConsumerIsReady() // check that the message was received - def records = records(1) + def records = consumer.poll(Duration.ofSeconds(5).toMillis()) for (record in records) { assert record.headers().iterator().hasNext() == propagationEnabled } diff --git a/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaUtils.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaUtils.java index b1984dc25567..2555e7e791e1 100644 --- a/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaUtils.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaUtils.java @@ -22,7 +22,7 @@ @SuppressWarnings("unchecked") public final class KafkaUtils { - static Instrumenter, Void> buildProducerInstrumenter( + public static Instrumenter, Void> buildProducerInstrumenter( String instrumentationName) { return buildProducerInstrumenter(instrumentationName, GlobalOpenTelemetry.get()); } @@ -43,7 +43,7 @@ public final class KafkaUtils { .newInstrumenter(SpanKindExtractor.alwaysProducer()); } - static Instrumenter buildConsumerReceiveInstrumenter( + public static Instrumenter buildConsumerReceiveInstrumenter( String instrumentationName) { return buildConsumerReceiveInstrumenter(instrumentationName, GlobalOpenTelemetry.get()); } @@ -65,17 +65,19 @@ public static Instrumenter buildConsumerReceiveInstrument .newInstrumenter(SpanKindExtractor.alwaysConsumer()); } - static Instrumenter, Void> buildConsumerProcessInstrumenter( + public static Instrumenter, Void> buildConsumerProcessInstrumenter( String instrumentationName) { - return buildConsumerProcessInstrumenter(instrumentationName, GlobalOpenTelemetry.get()); + return buildConsumerOperationInstrumenter( + instrumentationName, GlobalOpenTelemetry.get(), MessageOperation.PROCESS); } - public static Instrumenter, Void> buildConsumerProcessInstrumenter( + public static Instrumenter, Void> buildConsumerOperationInstrumenter( String instrumentationName, OpenTelemetry openTelemetry, + MessageOperation operation, AttributesExtractor, Void>... extractors) { KafkaConsumerAttributesExtractor attributesExtractor = - new KafkaConsumerAttributesExtractor(MessageOperation.PROCESS); + new KafkaConsumerAttributesExtractor(operation); SpanNameExtractor> spanNameExtractor = MessagingSpanNameExtractor.create(attributesExtractor); From 13b963592c113b66b7d84ffd4f212d1c496e1767 Mon Sep 17 00:00:00 2001 From: Ales Justin Date: Tue, 28 Sep 2021 10:54:24 +0200 Subject: [PATCH 3/7] Apply feedback, #3. --- .../kafkaclients/KafkaSingletons.java | 2 +- .../kafkaclients/KafkaTracing.java | 10 +++-- .../kafkaclients/KafkaTracingBuilder.java | 25 ++++++------ .../kafkaclients/KafkaTracingHolder.java | 2 +- .../src/test/resources/log4j.properties | 5 --- .../kafkastreams/KafkaStreamsSingletons.java | 39 +------------------ 6 files changed, 25 insertions(+), 58 deletions(-) delete mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/resources/log4j.properties diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java index 8fc22f5a203d..4756a7e3727a 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java @@ -12,7 +12,7 @@ import org.apache.kafka.clients.producer.ProducerRecord; public final class KafkaSingletons { - public static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11.javaagent"; + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11"; private static final Instrumenter, Void> PRODUCER_INSTRUMENTER = KafkaUtils.buildProducerInstrumenter(INSTRUMENTATION_NAME); diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java index ccdfbe794e43..1f7ff44b36fd 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java @@ -24,8 +24,6 @@ import org.slf4j.LoggerFactory; public class KafkaTracing { - public static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11.library"; - private static final Logger logger = LoggerFactory.getLogger(KafkaTracing.class); private static final TextMapGetter GETTER = new KafkaHeadersGetter(); @@ -42,7 +40,13 @@ public class KafkaTracing { this.consumerProcessInstrumenter = consumerProcessInstrumenter; } - public static KafkaTracingBuilder create(OpenTelemetry openTelemetry) { + /** Returns a new {@link KafkaTracing} configured with the given {@link OpenTelemetry}. */ + public static KafkaTracing create(OpenTelemetry openTelemetry) { + return newBuilder(openTelemetry).build(); + } + + /** Returns a new {@link KafkaTracingBuilder} configured with the given {@link OpenTelemetry}. */ + public static KafkaTracingBuilder newBuilder(OpenTelemetry openTelemetry) { return new KafkaTracingBuilder(openTelemetry); } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java index 40ef7101e883..cc0d1882efbd 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java @@ -16,36 +16,39 @@ import org.apache.kafka.clients.producer.ProducerRecord; public class KafkaTracingBuilder { + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11"; + private final OpenTelemetry openTelemetry; - private final List, Void>> producerExtractors = - new ArrayList<>(); - private final List, Void>> consumerProcessExtractors = + private final List, Void>> producerAttributesExtractors = new ArrayList<>(); + private final List, Void>> + consumerProcessAttributesExtractors = new ArrayList<>(); KafkaTracingBuilder(OpenTelemetry openTelemetry) { this.openTelemetry = Objects.requireNonNull(openTelemetry); } - public void addProducerExtractors(AttributesExtractor, Void> extractor) { - producerExtractors.add(extractor); + public void addProducerAttributesExtractors( + AttributesExtractor, Void> extractor) { + producerAttributesExtractors.add(extractor); } - public void addConsumerProcessExtractors( + public void addConsumerAttributesProcessExtractors( AttributesExtractor, Void> extractor) { - consumerProcessExtractors.add(extractor); + consumerProcessAttributesExtractors.add(extractor); } @SuppressWarnings("unchecked") public KafkaTracing build() { return new KafkaTracing( KafkaUtils.buildProducerInstrumenter( - KafkaTracing.INSTRUMENTATION_NAME, + INSTRUMENTATION_NAME, openTelemetry, - producerExtractors.toArray(new AttributesExtractor[0])), + producerAttributesExtractors.toArray(new AttributesExtractor[0])), KafkaUtils.buildConsumerOperationInstrumenter( - KafkaTracing.INSTRUMENTATION_NAME, + INSTRUMENTATION_NAME, openTelemetry, MessageOperation.RECEIVE, - consumerProcessExtractors.toArray(new AttributesExtractor[0]))); + consumerProcessAttributesExtractors.toArray(new AttributesExtractor[0]))); } } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java index 6d75e1469592..ea45acd51af7 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java @@ -13,7 +13,7 @@ abstract class KafkaTracingHolder { public synchronized KafkaTracing getTracing() { if (tracing == null) { - tracing = KafkaTracing.create(GlobalOpenTelemetry.get()).build(); + tracing = KafkaTracing.create(GlobalOpenTelemetry.get()); } return tracing; } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/resources/log4j.properties b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/resources/log4j.properties deleted file mode 100644 index 1ea4751367ed..000000000000 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/resources/log4j.properties +++ /dev/null @@ -1,5 +0,0 @@ -# Set root logger level to INFO and its only appender to C1. -log4j.rootLogger=INFO, A1 - -# C1 is set to be a ConsoleAppender. -log4j.appender.C1=org.apache.log4j.ConsoleAppender diff --git a/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java b/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java index 3dad14fb4be1..d3563308e92d 100644 --- a/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java +++ b/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java @@ -5,20 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.kafkastreams; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.config.ExperimentalConfig; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; -import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingSpanNameExtractor; -import io.opentelemetry.instrumentation.kafka.KafkaConsumerAdditionalAttributesExtractor; -import io.opentelemetry.instrumentation.kafka.KafkaConsumerAttributesExtractor; -import io.opentelemetry.instrumentation.kafka.KafkaConsumerExperimentalAttributesExtractor; -import io.opentelemetry.instrumentation.kafka.KafkaConsumerRecordGetter; -import io.opentelemetry.instrumentation.kafka.KafkaPropagation; +import io.opentelemetry.instrumentation.kafka.KafkaUtils; import org.apache.kafka.clients.consumer.ConsumerRecord; public final class KafkaStreamsSingletons { @@ -28,30 +16,7 @@ public final class KafkaStreamsSingletons { private static final Instrumenter, Void> INSTRUMENTER = buildInstrumenter(); private static Instrumenter, Void> buildInstrumenter() { - KafkaConsumerAttributesExtractor attributesExtractor = - new KafkaConsumerAttributesExtractor(MessageOperation.PROCESS); - SpanNameExtractor> spanNameExtractor = - MessagingSpanNameExtractor.create(attributesExtractor); - - InstrumenterBuilder, Void> builder = - Instrumenter., Void>newBuilder( - GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanNameExtractor) - .addAttributesExtractor(attributesExtractor) - .addAttributesExtractor(new KafkaConsumerAdditionalAttributesExtractor()); - if (KafkaConsumerExperimentalAttributesExtractor.isEnabled()) { - builder.addAttributesExtractor(new KafkaConsumerExperimentalAttributesExtractor()); - } - - if (!KafkaPropagation.isPropagationEnabled()) { - return builder.newInstrumenter(SpanKindExtractor.alwaysConsumer()); - } else if (ExperimentalConfig.get().suppressMessagingReceiveSpans()) { - return builder.newConsumerInstrumenter(new KafkaConsumerRecordGetter()); - } else { - builder.addSpanLinksExtractor( - SpanLinksExtractor.fromUpstreamRequest( - GlobalOpenTelemetry.getPropagators(), new KafkaConsumerRecordGetter())); - return builder.newInstrumenter(SpanKindExtractor.alwaysConsumer()); - } + return KafkaUtils.buildConsumerProcessInstrumenter(INSTRUMENTATION_NAME); } public static Instrumenter, Void> instrumenter() { From d2cf033865bddf836aa4cd5da6395c591a91126c Mon Sep 17 00:00:00 2001 From: Ales Justin Date: Wed, 29 Sep 2021 11:15:37 +0200 Subject: [PATCH 4/7] Apply feedback, #4. --- .../kafkaclients/KafkaSingletons.java | 8 ++--- .../kafkaclients/KafkaTracing.java | 29 ++++++++++--------- .../kafkaclients/KafkaTracingBuilder.java | 22 +++++++------- .../kafkaclients/KafkaTracingHolder.java | 9 +----- .../TracingConsumerInterceptor.java | 2 +- .../TracingProducerInterceptor.java | 2 +- .../kafkaclients/InterceptorsTest.groovy | 26 ++++++++--------- .../KafkaClientPropagationBaseTest.groovy | 1 + ...ils.java => KafkaInstrumenterBuilder.java} | 23 +++++++++------ .../kafkastreams/KafkaStreamsSingletons.java | 4 +-- settings.gradle.kts | 1 - 11 files changed, 62 insertions(+), 65 deletions(-) rename instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/{KafkaUtils.java => KafkaInstrumenterBuilder.java} (86%) diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java index 4756a7e3727a..95d6413dc4f5 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaSingletons.java @@ -6,7 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.kafkaclients; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.kafka.KafkaUtils; +import io.opentelemetry.instrumentation.kafka.KafkaInstrumenterBuilder; import io.opentelemetry.instrumentation.kafka.ReceivedRecords; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.producer.ProducerRecord; @@ -15,11 +15,11 @@ public final class KafkaSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11"; private static final Instrumenter, Void> PRODUCER_INSTRUMENTER = - KafkaUtils.buildProducerInstrumenter(INSTRUMENTATION_NAME); + KafkaInstrumenterBuilder.buildProducerInstrumenter(INSTRUMENTATION_NAME); private static final Instrumenter CONSUMER_RECEIVE_INSTRUMENTER = - KafkaUtils.buildConsumerReceiveInstrumenter(INSTRUMENTATION_NAME); + KafkaInstrumenterBuilder.buildConsumerReceiveInstrumenter(INSTRUMENTATION_NAME); private static final Instrumenter, Void> CONSUMER_PROCESS_INSTRUMENTER = - KafkaUtils.buildConsumerProcessInstrumenter(INSTRUMENTATION_NAME); + KafkaInstrumenterBuilder.buildConsumerProcessInstrumenter(INSTRUMENTATION_NAME); public static Instrumenter, Void> producerInstrumenter() { return PRODUCER_INSTRUMENTER; diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java index 1f7ff44b36fd..7514aeafecd9 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java @@ -5,7 +5,6 @@ package io.opentelemetry.instrumentation.kafkaclients; -import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; @@ -14,7 +13,7 @@ import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.context.propagation.TextMapSetter; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.kafka.KafkaHeadersGetter; +import io.opentelemetry.instrumentation.kafka.KafkaConsumerRecordGetter; import io.opentelemetry.instrumentation.kafka.KafkaHeadersSetter; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; @@ -23,19 +22,22 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class KafkaTracing { +public final class KafkaTracing { private static final Logger logger = LoggerFactory.getLogger(KafkaTracing.class); - private static final TextMapGetter GETTER = new KafkaHeadersGetter(); + private static final TextMapGetter> GETTER = new KafkaConsumerRecordGetter(); private static final TextMapSetter SETTER = new KafkaHeadersSetter(); + private final OpenTelemetry openTelemetry; private final Instrumenter, Void> producerInstrumenter; private final Instrumenter, Void> consumerProcessInstrumenter; KafkaTracing( + OpenTelemetry openTelemetry, Instrumenter, Void> producerInstrumenter, Instrumenter, Void> consumerProcessInstrumenter) { + this.openTelemetry = openTelemetry; this.producerInstrumenter = producerInstrumenter; this.consumerProcessInstrumenter = consumerProcessInstrumenter; } @@ -50,21 +52,20 @@ public static KafkaTracingBuilder newBuilder(OpenTelemetry openTelemetry) { return new KafkaTracingBuilder(openTelemetry); } - private static TextMapPropagator propagator() { - return GlobalOpenTelemetry.getPropagators().getTextMapPropagator(); + private TextMapPropagator propagator() { + return openTelemetry.getPropagators().getTextMapPropagator(); } /** * Build and inject span into record. Return Runnable handle to end the current span. * * @param record the producer record to inject span info. - * @return runnable to close the current span */ - Runnable buildAndInjectSpan(ProducerRecord record) { + void buildAndInjectSpan(ProducerRecord record) { Context currentContext = Context.current(); if (!producerInstrumenter.shouldStart(currentContext, record)) { - return () -> {}; + return; } Context current = producerInstrumenter.start(currentContext, record); @@ -77,20 +78,20 @@ Runnable buildAndInjectSpan(ProducerRecord record) { } } - return () -> producerInstrumenter.end(current, record, null, null); + producerInstrumenter.end(current, record, null, null); } void buildAndFinishSpan(ConsumerRecords records) { Context currentContext = Context.current(); for (ConsumerRecord record : records) { - Context linkedContext = propagator().extract(currentContext, record.headers(), GETTER); - currentContext.with(Span.fromContext(linkedContext)); + Context linkedContext = propagator().extract(currentContext, record, GETTER); + Context newContext = currentContext.with(Span.fromContext(linkedContext)); - if (!consumerProcessInstrumenter.shouldStart(currentContext, record)) { + if (!consumerProcessInstrumenter.shouldStart(newContext, record)) { continue; } - Context current = consumerProcessInstrumenter.start(currentContext, record); + Context current = consumerProcessInstrumenter.start(newContext, record); consumerProcessInstrumenter.end(current, record, null, null); } } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java index cc0d1882efbd..7beaedbc78ac 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java @@ -8,7 +8,7 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; -import io.opentelemetry.instrumentation.kafka.KafkaUtils; +import io.opentelemetry.instrumentation.kafka.KafkaInstrumenterBuilder; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -21,8 +21,8 @@ public class KafkaTracingBuilder { private final OpenTelemetry openTelemetry; private final List, Void>> producerAttributesExtractors = new ArrayList<>(); - private final List, Void>> - consumerProcessAttributesExtractors = new ArrayList<>(); + private final List, Void>> consumerAttributesExtractors = + new ArrayList<>(); KafkaTracingBuilder(OpenTelemetry openTelemetry) { this.openTelemetry = Objects.requireNonNull(openTelemetry); @@ -33,22 +33,20 @@ public void addProducerAttributesExtractors( producerAttributesExtractors.add(extractor); } - public void addConsumerAttributesProcessExtractors( + public void addConsumerAttributesExtractors( AttributesExtractor, Void> extractor) { - consumerProcessAttributesExtractors.add(extractor); + consumerAttributesExtractors.add(extractor); } - @SuppressWarnings("unchecked") public KafkaTracing build() { return new KafkaTracing( - KafkaUtils.buildProducerInstrumenter( - INSTRUMENTATION_NAME, - openTelemetry, - producerAttributesExtractors.toArray(new AttributesExtractor[0])), - KafkaUtils.buildConsumerOperationInstrumenter( + openTelemetry, + KafkaInstrumenterBuilder.buildProducerInstrumenter( + INSTRUMENTATION_NAME, openTelemetry, producerAttributesExtractors), + KafkaInstrumenterBuilder.buildConsumerOperationInstrumenter( INSTRUMENTATION_NAME, openTelemetry, MessageOperation.RECEIVE, - consumerProcessAttributesExtractors.toArray(new AttributesExtractor[0]))); + consumerAttributesExtractors)); } } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java index ea45acd51af7..30b6bef9fac5 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java @@ -9,12 +9,5 @@ abstract class KafkaTracingHolder { - private KafkaTracing tracing; - - public synchronized KafkaTracing getTracing() { - if (tracing == null) { - tracing = KafkaTracing.create(GlobalOpenTelemetry.get()); - } - return tracing; - } + static final KafkaTracing tracing = KafkaTracing.create(GlobalOpenTelemetry.get()); } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java index 05d3492a4298..1e9285ecfebf 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java @@ -16,7 +16,7 @@ public class TracingConsumerInterceptor extends KafkaTracingHolder @Override public ConsumerRecords onConsume(ConsumerRecords records) { - getTracing().buildAndFinishSpan(records); + tracing.buildAndFinishSpan(records); return records; } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java index ea9b906d2d1a..af9029cd3083 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java @@ -14,7 +14,7 @@ public class TracingProducerInterceptor extends KafkaTracingHolder implements ProducerInterceptor { @Override public ProducerRecord onSend(ProducerRecord producerRecord) { - getTracing().buildAndInjectSpan(producerRecord).run(); + tracing.buildAndInjectSpan(producerRecord); return producerRecord; } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy index 54ddd8d71b17..3b0de1611fac 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy @@ -52,14 +52,15 @@ class InterceptorsTest extends KafkaClientBaseTest implements LibraryTestTrait { awaitUntilConsumerIsReady() // check that the message was received def records = consumer.poll(Duration.ofSeconds(5).toMillis()) + records.count() == 1 for (record in records) { assert record.value() == greeting assert record.key() == null } - assertTraces(3) { + assertTraces(2) { traces.sort(orderByRootSpanKind(INTERNAL, PRODUCER, CONSUMER)) - trace(0, 2) { + trace(0, 3) { span(0) { name "parent" kind INTERNAL @@ -75,19 +76,11 @@ class InterceptorsTest extends KafkaClientBaseTest implements LibraryTestTrait { "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" } } - } - trace(1, 1) { - span(0) { - name "producer callback" - kind INTERNAL - hasNoParent() - } - } - trace(2, 1) { - span(0) { + span(2) { name SHARED_TOPIC + " receive" kind CONSUMER - hasNoParent() + childOf span(1) + hasLink(span(1)) attributes { "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC @@ -100,6 +93,13 @@ class InterceptorsTest extends KafkaClientBaseTest implements LibraryTestTrait { } } } + trace(1, 1) { + span(0) { + name "producer callback" + kind INTERNAL + hasNoParent() + } + } } } } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy index 78e175e69f7c..b927f375affd 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy +++ b/instrumentation/kafka-clients/kafka-clients-0.11/testing/src/main/groovy/io/opentelemetry/instrumentation/kafkaclients/KafkaClientPropagationBaseTest.groovy @@ -26,6 +26,7 @@ abstract class KafkaClientPropagationBaseTest extends KafkaClientBaseTest implem awaitUntilConsumerIsReady() // check that the message was received def records = consumer.poll(Duration.ofSeconds(5).toMillis()) + records.count() == 1 for (record in records) { assert record.headers().iterator().hasNext() == propagationEnabled } diff --git a/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaUtils.java b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaInstrumenterBuilder.java similarity index 86% rename from instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaUtils.java rename to instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaInstrumenterBuilder.java index 2555e7e791e1..5c88d3e52345 100644 --- a/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaUtils.java +++ b/instrumentation/kafka-clients/kafka-clients-common/library/src/main/java/io/opentelemetry/instrumentation/kafka/KafkaInstrumenterBuilder.java @@ -16,21 +16,22 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingSpanNameExtractor; +import java.util.Collections; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.producer.ProducerRecord; -@SuppressWarnings("unchecked") -public final class KafkaUtils { +public final class KafkaInstrumenterBuilder { public static Instrumenter, Void> buildProducerInstrumenter( String instrumentationName) { - return buildProducerInstrumenter(instrumentationName, GlobalOpenTelemetry.get()); + return buildProducerInstrumenter( + instrumentationName, GlobalOpenTelemetry.get(), Collections.emptyList()); } public static Instrumenter, Void> buildProducerInstrumenter( String instrumentationName, OpenTelemetry openTelemetry, - AttributesExtractor, Void>... extractors) { + Iterable, Void>> extractors) { KafkaProducerAttributesExtractor attributesExtractor = new KafkaProducerAttributesExtractor(); SpanNameExtractor> spanNameExtractor = MessagingSpanNameExtractor.create(attributesExtractor); @@ -45,13 +46,14 @@ public final class KafkaUtils { public static Instrumenter buildConsumerReceiveInstrumenter( String instrumentationName) { - return buildConsumerReceiveInstrumenter(instrumentationName, GlobalOpenTelemetry.get()); + return buildConsumerReceiveInstrumenter( + instrumentationName, GlobalOpenTelemetry.get(), Collections.emptyList()); } public static Instrumenter buildConsumerReceiveInstrumenter( String instrumentationName, OpenTelemetry openTelemetry, - AttributesExtractor... extractors) { + Iterable> extractors) { KafkaReceiveAttributesExtractor attributesExtractor = new KafkaReceiveAttributesExtractor(); SpanNameExtractor spanNameExtractor = MessagingSpanNameExtractor.create(attributesExtractor); @@ -68,14 +70,17 @@ public static Instrumenter buildConsumerReceiveInstrument public static Instrumenter, Void> buildConsumerProcessInstrumenter( String instrumentationName) { return buildConsumerOperationInstrumenter( - instrumentationName, GlobalOpenTelemetry.get(), MessageOperation.PROCESS); + instrumentationName, + GlobalOpenTelemetry.get(), + MessageOperation.PROCESS, + Collections.emptyList()); } public static Instrumenter, Void> buildConsumerOperationInstrumenter( String instrumentationName, OpenTelemetry openTelemetry, MessageOperation operation, - AttributesExtractor, Void>... extractors) { + Iterable, Void>> extractors) { KafkaConsumerAttributesExtractor attributesExtractor = new KafkaConsumerAttributesExtractor(operation); SpanNameExtractor> spanNameExtractor = @@ -103,5 +108,5 @@ public static Instrumenter buildConsumerReceiveInstrument } } - private KafkaUtils() {} + private KafkaInstrumenterBuilder() {} } diff --git a/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java b/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java index d3563308e92d..a0761dfe677d 100644 --- a/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java +++ b/instrumentation/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java @@ -6,7 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.kafkastreams; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.kafka.KafkaUtils; +import io.opentelemetry.instrumentation.kafka.KafkaInstrumenterBuilder; import org.apache.kafka.clients.consumer.ConsumerRecord; public final class KafkaStreamsSingletons { @@ -16,7 +16,7 @@ public final class KafkaStreamsSingletons { private static final Instrumenter, Void> INSTRUMENTER = buildInstrumenter(); private static Instrumenter, Void> buildInstrumenter() { - return KafkaUtils.buildConsumerProcessInstrumenter(INSTRUMENTATION_NAME); + return KafkaInstrumenterBuilder.buildConsumerProcessInstrumenter(INSTRUMENTATION_NAME); } public static Instrumenter, Void> instrumenter() { diff --git a/settings.gradle.kts b/settings.gradle.kts index 035df2b71864..7d4861081dd4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -220,7 +220,6 @@ include(":instrumentation:jsp-2.3:javaagent") include(":instrumentation:kafka-clients:kafka-clients-0.11:javaagent") include(":instrumentation:kafka-clients:kafka-clients-0.11:library") include(":instrumentation:kafka-clients:kafka-clients-0.11:testing") -include(":instrumentation:kafka-clients:kafka-clients-2.4.0-testing") include(":instrumentation:kafka-clients:kafka-clients-common:library") include(":instrumentation:kafka-streams-0.11:javaagent") include(":instrumentation:kotlinx-coroutines:javaagent") From c697ba6c254d91ff0a54afaed49f3785f3d48c46 Mon Sep 17 00:00:00 2001 From: Ales Justin Date: Wed, 29 Sep 2021 17:40:04 +0200 Subject: [PATCH 5/7] Add producer / consumer wrappers. --- .../library/build.gradle.kts | 2 +- .../kafkaclients/KafkaTracing.java | 66 ++++- .../kafkaclients/TracingConsumer.java | 280 ++++++++++++++++++ .../kafkaclients/TracingProducer.java | 98 ++++++ .../kafkaclients/WrappersTest.groovy | 92 ++++++ 5 files changed, 536 insertions(+), 2 deletions(-) create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java create mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/WrappersTest.groovy diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/build.gradle.kts b/instrumentation/kafka-clients/kafka-clients-0.11/library/build.gradle.kts index 5d5eb9cbfc9b..87be41bff381 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/build.gradle.kts +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/build.gradle.kts @@ -6,7 +6,7 @@ val versions: Map by project dependencies { implementation(project(":instrumentation:kafka-clients:kafka-clients-common:library")) - library("org.apache.kafka:kafka-clients:0.11.0.0") + library("org.apache.kafka:kafka-clients:2.8.1") testImplementation(project(":instrumentation:kafka-clients:kafka-clients-0.11:testing")) diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java index 7514aeafecd9..349c149e4d7a 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java @@ -15,9 +15,15 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.kafka.KafkaConsumerRecordGetter; import io.opentelemetry.instrumentation.kafka.KafkaHeadersSetter; +import java.util.concurrent.Future; +import java.util.function.BiFunction; +import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.producer.Callback; +import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.clients.producer.RecordMetadata; import org.apache.kafka.common.header.Headers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,8 +62,16 @@ private TextMapPropagator propagator() { return openTelemetry.getPropagators().getTextMapPropagator(); } + public Producer wrap(Producer producer) { + return new TracingProducer<>(producer, this); + } + + public Consumer wrap(Consumer consumer) { + return new TracingConsumer<>(consumer, this); + } + /** - * Build and inject span into record. Return Runnable handle to end the current span. + * Build and inject span into record. * * @param record the producer record to inject span info. */ @@ -81,6 +95,30 @@ void buildAndInjectSpan(ProducerRecord record) { producerInstrumenter.end(current, record, null, null); } + /** + * Build and inject span into record. + * + * @param record the producer record to inject span info. + * @param callback the producer send callback + * @return send function's result + */ + Future buildAndInjectSpan( + ProducerRecord record, + Callback callback, + BiFunction, Callback, Future> sendFn) { + Context parentContext = Context.current(); + if (!producerInstrumenter.shouldStart(parentContext, record)) { + return sendFn.apply(record, callback); + } + + Context context = producerInstrumenter.start(parentContext, record); + try (Scope ignored = context.makeCurrent()) { + propagator().inject(context, record.headers(), SETTER); + callback = new ProducerCallback(callback, parentContext, context, record); + return sendFn.apply(record, callback); + } + } + void buildAndFinishSpan(ConsumerRecords records) { Context currentContext = Context.current(); for (ConsumerRecord record : records) { @@ -95,4 +133,30 @@ void buildAndFinishSpan(ConsumerRecords records) { consumerProcessInstrumenter.end(current, record, null, null); } } + + private class ProducerCallback implements Callback { + private final Callback callback; + private final Context parentContext; + private final Context context; + private final ProducerRecord request; + + public ProducerCallback( + Callback callback, Context parentContext, Context context, ProducerRecord request) { + this.callback = callback; + this.parentContext = parentContext; + this.context = context; + this.request = request; + } + + @Override + public void onCompletion(RecordMetadata metadata, Exception exception) { + producerInstrumenter.end(context, request, null, exception); + + if (callback != null) { + try (Scope ignored = parentContext.makeCurrent()) { + callback.onCompletion(metadata, exception); + } + } + } + } } diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java new file mode 100644 index 000000000000..98416617548a --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java @@ -0,0 +1,280 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafkaclients; + +import java.time.Duration; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.consumer.ConsumerGroupMetadata; +import org.apache.kafka.clients.consumer.ConsumerRebalanceListener; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.OffsetAndMetadata; +import org.apache.kafka.clients.consumer.OffsetAndTimestamp; +import org.apache.kafka.clients.consumer.OffsetCommitCallback; +import org.apache.kafka.common.Metric; +import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.PartitionInfo; +import org.apache.kafka.common.TopicPartition; + +public class TracingConsumer implements Consumer { + private final Consumer consumer; + private final KafkaTracing tracing; + + TracingConsumer(Consumer consumer, KafkaTracing tracing) { + this.consumer = consumer; + this.tracing = tracing; + } + + @Override + public Set assignment() { + return consumer.assignment(); + } + + @Override + public Set subscription() { + return consumer.subscription(); + } + + @Override + public void subscribe(Collection topics, ConsumerRebalanceListener listener) { + consumer.subscribe(topics, listener); + } + + @Override + public void subscribe(Collection topics) { + consumer.subscribe(topics); + } + + @Override + public void subscribe(Pattern pattern, ConsumerRebalanceListener listener) { + consumer.subscribe(pattern, listener); + } + + @Override + public void subscribe(Pattern pattern) { + consumer.subscribe(pattern); + } + + @Override + public void unsubscribe() { + consumer.unsubscribe(); + } + + @Override + public void assign(Collection partitions) { + consumer.assign(partitions); + } + + @Override + @Deprecated + public ConsumerRecords poll(long timeout) { + return poll(Duration.ofMillis(timeout)); + } + + @Override + public ConsumerRecords poll(Duration duration) { + ConsumerRecords records = consumer.poll(duration); + tracing.buildAndFinishSpan(records); + return records; + } + + @Override + public void commitSync() { + consumer.commitSync(); + } + + @Override + public void commitSync(Duration duration) { + consumer.commitSync(duration); + } + + @Override + public void commitSync(Map offsets) { + consumer.commitSync(offsets); + } + + @Override + public void commitSync(Map map, Duration duration) { + consumer.commitSync(map, duration); + } + + @Override + public void commitAsync() { + consumer.commitAsync(); + } + + @Override + public void commitAsync(OffsetCommitCallback callback) { + consumer.commitAsync(callback); + } + + @Override + public void commitAsync( + Map offsets, OffsetCommitCallback callback) { + consumer.commitAsync(offsets, callback); + } + + @Override + public void seek(TopicPartition partition, long offset) { + consumer.seek(partition, offset); + } + + @Override + public void seek(TopicPartition partition, OffsetAndMetadata offsetAndMetadata) { + consumer.seek(partition, offsetAndMetadata); + } + + @Override + public void seekToBeginning(Collection partitions) { + consumer.seekToBeginning(partitions); + } + + @Override + public void seekToEnd(Collection partitions) { + consumer.seekToEnd(partitions); + } + + @Override + public long position(TopicPartition partition) { + return consumer.position(partition); + } + + @Override + public long position(TopicPartition topicPartition, Duration duration) { + return consumer.position(topicPartition, duration); + } + + @Override + public OffsetAndMetadata committed(TopicPartition partition) { + return consumer.committed(partition); + } + + @Override + public OffsetAndMetadata committed(TopicPartition topicPartition, Duration duration) { + return consumer.committed(topicPartition, duration); + } + + @Override + public Map committed(Set partitions) { + return consumer.committed(partitions); + } + + @Override + public Map committed( + Set partitions, final Duration timeout) { + return consumer.committed(partitions, timeout); + } + + @Override + public Map metrics() { + return consumer.metrics(); + } + + @Override + public List partitionsFor(String topic) { + return consumer.partitionsFor(topic); + } + + @Override + public List partitionsFor(String s, Duration duration) { + return consumer.partitionsFor(s, duration); + } + + @Override + public Map> listTopics() { + return consumer.listTopics(); + } + + @Override + public Map> listTopics(Duration duration) { + return consumer.listTopics(duration); + } + + @Override + public void pause(Collection partitions) { + consumer.pause(partitions); + } + + @Override + public void resume(Collection partitions) { + consumer.resume(partitions); + } + + @Override + public Set paused() { + return consumer.paused(); + } + + @Override + public Map offsetsForTimes( + Map timestampsToSearch) { + return consumer.offsetsForTimes(timestampsToSearch); + } + + @Override + public Map offsetsForTimes( + Map map, Duration duration) { + return consumer.offsetsForTimes(map, duration); + } + + @Override + public Map beginningOffsets(Collection partitions) { + return consumer.beginningOffsets(partitions); + } + + @Override + public Map beginningOffsets( + Collection collection, Duration duration) { + return consumer.beginningOffsets(collection, duration); + } + + @Override + public Map endOffsets(Collection partitions) { + return consumer.endOffsets(partitions); + } + + @Override + public Map endOffsets( + Collection collection, Duration duration) { + return consumer.endOffsets(collection, duration); + } + + @Override + public ConsumerGroupMetadata groupMetadata() { + return consumer.groupMetadata(); + } + + @Override + public void enforceRebalance() { + consumer.enforceRebalance(); + } + + @Override + public void close() { + consumer.close(); + } + + @Override + @Deprecated + public void close(long l, TimeUnit timeUnit) { + consumer.close(l, timeUnit); + } + + @Override + public void close(Duration duration) { + consumer.close(duration); + } + + @Override + public void wakeup() { + consumer.wakeup(); + } +} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java new file mode 100644 index 000000000000..c3c240ed7fe0 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java @@ -0,0 +1,98 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafkaclients; + +import java.time.Duration; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Future; +import org.apache.kafka.clients.consumer.ConsumerGroupMetadata; +import org.apache.kafka.clients.consumer.OffsetAndMetadata; +import org.apache.kafka.clients.producer.Callback; +import org.apache.kafka.clients.producer.Producer; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.clients.producer.RecordMetadata; +import org.apache.kafka.common.Metric; +import org.apache.kafka.common.MetricName; +import org.apache.kafka.common.PartitionInfo; +import org.apache.kafka.common.TopicPartition; + +public class TracingProducer implements Producer { + private final Producer producer; + private final KafkaTracing tracing; + + TracingProducer(Producer producer, KafkaTracing tracing) { + this.producer = producer; + this.tracing = tracing; + } + + @Override + public void initTransactions() { + producer.initTransactions(); + } + + @Override + public void beginTransaction() { + producer.beginTransaction(); + } + + @Override + public void sendOffsetsToTransaction( + Map offsets, String consumerGroupId) { + producer.sendOffsetsToTransaction(offsets, consumerGroupId); + } + + @Override + public void sendOffsetsToTransaction( + Map offsets, ConsumerGroupMetadata groupMetadata) { + producer.sendOffsetsToTransaction(offsets, groupMetadata); + } + + @Override + public void commitTransaction() { + producer.commitTransaction(); + } + + @Override + public void abortTransaction() { + producer.abortTransaction(); + } + + @Override + public Future send(ProducerRecord record) { + return send(record, null); + } + + @Override + public Future send(ProducerRecord record, Callback callback) { + return tracing.buildAndInjectSpan(record, callback, producer::send); + } + + @Override + public void flush() { + producer.flush(); + } + + @Override + public List partitionsFor(String topic) { + return producer.partitionsFor(topic); + } + + @Override + public Map metrics() { + return producer.metrics(); + } + + @Override + public void close() { + producer.close(); + } + + @Override + public void close(Duration duration) { + producer.close(duration); + } +} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/WrappersTest.groovy b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/WrappersTest.groovy new file mode 100644 index 000000000000..038191bd33a2 --- /dev/null +++ b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/WrappersTest.groovy @@ -0,0 +1,92 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.kafkaclients + +import io.opentelemetry.instrumentation.test.LibraryTestTrait +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes +import org.apache.kafka.clients.producer.ProducerRecord +import spock.lang.Unroll + +import java.time.Duration + +import static io.opentelemetry.api.trace.SpanKind.CONSUMER +import static io.opentelemetry.api.trace.SpanKind.INTERNAL +import static io.opentelemetry.api.trace.SpanKind.PRODUCER + +class WrappersTest extends KafkaClientBaseTest implements LibraryTestTrait { + + @Unroll + def "test wrappers"() throws Exception { + KafkaTracing tracing = KafkaTracing.create(getOpenTelemetry()) + + when: + String greeting = "Hello Kafka!" + def wrappedProducer = tracing.wrap(producer) + runWithSpan("parent") { + wrappedProducer.send(new ProducerRecord(SHARED_TOPIC, greeting)) { meta, ex -> + if (ex == null) { + runWithSpan("producer callback") {} + } else { + runWithSpan("producer exception: " + ex) {} + } + } + } + + then: + awaitUntilConsumerIsReady() + // check that the message was received + def wrappedConsumer = tracing.wrap(consumer) + def records = wrappedConsumer.poll(Duration.ofSeconds(5).toMillis()) + records.count() == 1 + for (record in records) { + assert record.value() == greeting + assert record.key() == null + } + + assertTraces(1) { + traces.sort(orderByRootSpanKind(INTERNAL, PRODUCER, CONSUMER)) + trace(0, 4) { + span(0) { + name "parent" + kind INTERNAL + hasNoParent() + } + span(1) { + name SHARED_TOPIC + " send" + kind PRODUCER + childOf span(0) + attributes { + "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" + "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC + "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" + } + } + span(2) { + name SHARED_TOPIC + " receive" + kind CONSUMER + childOf span(1) + hasLink(span(1)) + attributes { + "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" + "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC + "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" + "${SemanticAttributes.MESSAGING_OPERATION.key}" "receive" + "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long + "${SemanticAttributes.MESSAGING_KAFKA_PARTITION.key}" { it >= 0 } + "kafka.offset" Long + "kafka.record.queue_time_ms" { it >= 0 } + } + } + span(3) { + name "producer callback" + kind INTERNAL + childOf span(0) + } + } + } + } +} + From 0912ff32baf02a340f3c9da703629f118a44415d Mon Sep 17 00:00:00 2001 From: Ales Justin Date: Thu, 30 Sep 2021 12:24:56 +0200 Subject: [PATCH 6/7] Move to kafka-clients-2.6. --- .../kafkaclients/KafkaTracingHolder.java | 13 ------------- .../library/build.gradle.kts | 6 ++---- .../instrumentation/kafkaclients/KafkaTracing.java | 0 .../kafkaclients/KafkaTracingBuilder.java | 0 .../kafkaclients/TracingConsumer.java | 0 .../kafkaclients/TracingConsumerInterceptor.java | 11 +++++++++-- .../kafkaclients/TracingProducer.java | 0 .../kafkaclients/TracingProducerInterceptor.java | 12 ++++++++++-- .../kafkaclients/InterceptorsTest.groovy | 0 .../kafkaclients/WrappersTest.groovy | 0 settings.gradle.kts | 2 +- 11 files changed, 22 insertions(+), 22 deletions(-) delete mode 100644 instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java rename instrumentation/kafka-clients/{kafka-clients-0.11 => kafka-clients-2.6}/library/build.gradle.kts (75%) rename instrumentation/kafka-clients/{kafka-clients-0.11 => kafka-clients-2.6}/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java (100%) rename instrumentation/kafka-clients/{kafka-clients-0.11 => kafka-clients-2.6}/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java (100%) rename instrumentation/kafka-clients/{kafka-clients-0.11 => kafka-clients-2.6}/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java (100%) rename instrumentation/kafka-clients/{kafka-clients-0.11 => kafka-clients-2.6}/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java (58%) rename instrumentation/kafka-clients/{kafka-clients-0.11 => kafka-clients-2.6}/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java (100%) rename instrumentation/kafka-clients/{kafka-clients-0.11 => kafka-clients-2.6}/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java (57%) rename instrumentation/kafka-clients/{kafka-clients-0.11 => kafka-clients-2.6}/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy (100%) rename instrumentation/kafka-clients/{kafka-clients-0.11 => kafka-clients-2.6}/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/WrappersTest.groovy (100%) diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java b/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java deleted file mode 100644 index 30b6bef9fac5..000000000000 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingHolder.java +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.kafkaclients; - -import io.opentelemetry.api.GlobalOpenTelemetry; - -abstract class KafkaTracingHolder { - - static final KafkaTracing tracing = KafkaTracing.create(GlobalOpenTelemetry.get()); -} diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/build.gradle.kts b/instrumentation/kafka-clients/kafka-clients-2.6/library/build.gradle.kts similarity index 75% rename from instrumentation/kafka-clients/kafka-clients-0.11/library/build.gradle.kts rename to instrumentation/kafka-clients/kafka-clients-2.6/library/build.gradle.kts index 87be41bff381..c70d9b1f0b75 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/build.gradle.kts +++ b/instrumentation/kafka-clients/kafka-clients-2.6/library/build.gradle.kts @@ -2,15 +2,13 @@ plugins { id("otel.library-instrumentation") } -val versions: Map by project - dependencies { implementation(project(":instrumentation:kafka-clients:kafka-clients-common:library")) - library("org.apache.kafka:kafka-clients:2.8.1") + library("org.apache.kafka:kafka-clients:2.6.0") testImplementation(project(":instrumentation:kafka-clients:kafka-clients-0.11:testing")) - testImplementation("org.testcontainers:kafka:${versions["org.testcontainers"]}") + testImplementation("org.testcontainers:kafka") } tasks { diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java similarity index 100% rename from instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java rename to instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java similarity index 100% rename from instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java rename to instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java similarity index 100% rename from instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java rename to instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java similarity index 58% rename from instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java rename to instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java index 1e9285ecfebf..4620befd8972 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java +++ b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumerInterceptor.java @@ -5,14 +5,21 @@ package io.opentelemetry.instrumentation.kafkaclients; +import io.opentelemetry.api.GlobalOpenTelemetry; import java.util.Map; import org.apache.kafka.clients.consumer.ConsumerInterceptor; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.clients.consumer.OffsetAndMetadata; import org.apache.kafka.common.TopicPartition; -public class TracingConsumerInterceptor extends KafkaTracingHolder - implements ConsumerInterceptor { +/** + * A ConsumerInterceptor that adds tracing capability. Add this interceptor's class name or class + * via ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG property to your Consumer's properties to get it + * instantiated and used. See more details on ConsumerInterceptor usage in its Javadoc. + */ +public class TracingConsumerInterceptor implements ConsumerInterceptor { + + private static final KafkaTracing tracing = KafkaTracing.create(GlobalOpenTelemetry.get()); @Override public ConsumerRecords onConsume(ConsumerRecords records) { diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java similarity index 100% rename from instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java rename to instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java similarity index 57% rename from instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java rename to instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java index af9029cd3083..c016f4842b73 100644 --- a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java +++ b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducerInterceptor.java @@ -5,13 +5,21 @@ package io.opentelemetry.instrumentation.kafkaclients; +import io.opentelemetry.api.GlobalOpenTelemetry; import java.util.Map; import org.apache.kafka.clients.producer.ProducerInterceptor; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.clients.producer.RecordMetadata; -public class TracingProducerInterceptor extends KafkaTracingHolder - implements ProducerInterceptor { +/** + * A ProducerInterceptor that adds tracing capability. Add this interceptor's class name or class + * via ProducerConfig.INTERCEPTOR_CLASSES_CONFIG property to your Producer's properties to get it + * instantiated and used. See more details on ProducerInterceptor usage in its Javadoc. + */ +public class TracingProducerInterceptor implements ProducerInterceptor { + + private static final KafkaTracing tracing = KafkaTracing.create(GlobalOpenTelemetry.get()); + @Override public ProducerRecord onSend(ProducerRecord producerRecord) { tracing.buildAndInjectSpan(producerRecord); diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy similarity index 100% rename from instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy rename to instrumentation/kafka-clients/kafka-clients-2.6/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/InterceptorsTest.groovy diff --git a/instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/WrappersTest.groovy b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/WrappersTest.groovy similarity index 100% rename from instrumentation/kafka-clients/kafka-clients-0.11/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/WrappersTest.groovy rename to instrumentation/kafka-clients/kafka-clients-2.6/library/src/test/groovy/io/opentelemetry/instrumentation/kafkaclients/WrappersTest.groovy diff --git a/settings.gradle.kts b/settings.gradle.kts index 7d4861081dd4..cccd012a9284 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -218,8 +218,8 @@ include(":instrumentation:jsf:mojarra-1.2:javaagent") include(":instrumentation:jsf:myfaces-1.2:javaagent") include(":instrumentation:jsp-2.3:javaagent") include(":instrumentation:kafka-clients:kafka-clients-0.11:javaagent") -include(":instrumentation:kafka-clients:kafka-clients-0.11:library") include(":instrumentation:kafka-clients:kafka-clients-0.11:testing") +include(":instrumentation:kafka-clients:kafka-clients-2.6:library") include(":instrumentation:kafka-clients:kafka-clients-common:library") include(":instrumentation:kafka-streams-0.11:javaagent") include(":instrumentation:kotlinx-coroutines:javaagent") From bd8a5d5e6d208c0ee27510e5bc419936423b910b Mon Sep 17 00:00:00 2001 From: Ales Justin Date: Thu, 30 Sep 2021 14:58:34 +0200 Subject: [PATCH 7/7] Apply feedback #5. --- .../kafka-clients-2.6/library/build.gradle.kts | 1 + .../instrumentation/kafkaclients/KafkaTracing.java | 2 ++ .../instrumentation/kafkaclients/KafkaTracingBuilder.java | 8 +++++--- .../instrumentation/kafkaclients/TracingConsumer.java | 2 +- .../instrumentation/kafkaclients/TracingProducer.java | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/instrumentation/kafka-clients/kafka-clients-2.6/library/build.gradle.kts b/instrumentation/kafka-clients/kafka-clients-2.6/library/build.gradle.kts index c70d9b1f0b75..af835920e583 100644 --- a/instrumentation/kafka-clients/kafka-clients-2.6/library/build.gradle.kts +++ b/instrumentation/kafka-clients/kafka-clients-2.6/library/build.gradle.kts @@ -7,6 +7,7 @@ dependencies { library("org.apache.kafka:kafka-clients:2.6.0") testImplementation(project(":instrumentation:kafka-clients:kafka-clients-0.11:testing")) + testImplementation("com.fasterxml.jackson.core:jackson-databind:2.10.2") testImplementation("org.testcontainers:kafka") } diff --git a/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java index 349c149e4d7a..9c19d0739a59 100644 --- a/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java +++ b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracing.java @@ -62,10 +62,12 @@ private TextMapPropagator propagator() { return openTelemetry.getPropagators().getTextMapPropagator(); } + /** Returns a decorated {@link Producer} that emits spans for each sent message. */ public Producer wrap(Producer producer) { return new TracingProducer<>(producer, this); } + /** Returns a decorated {@link Consumer} that consumes spans for each received message. */ public Consumer wrap(Consumer consumer) { return new TracingConsumer<>(consumer, this); } diff --git a/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java index 7beaedbc78ac..76769ebb25e6 100644 --- a/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java +++ b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/KafkaTracingBuilder.java @@ -15,7 +15,7 @@ import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.producer.ProducerRecord; -public class KafkaTracingBuilder { +public final class KafkaTracingBuilder { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11"; private final OpenTelemetry openTelemetry; @@ -28,14 +28,16 @@ public class KafkaTracingBuilder { this.openTelemetry = Objects.requireNonNull(openTelemetry); } - public void addProducerAttributesExtractors( + public KafkaTracingBuilder addProducerAttributesExtractors( AttributesExtractor, Void> extractor) { producerAttributesExtractors.add(extractor); + return this; } - public void addConsumerAttributesExtractors( + public KafkaTracingBuilder addConsumerAttributesExtractors( AttributesExtractor, Void> extractor) { consumerAttributesExtractors.add(extractor); + return this; } public KafkaTracing build() { diff --git a/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java index 98416617548a..d8be2f4e09e4 100644 --- a/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java +++ b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingConsumer.java @@ -24,7 +24,7 @@ import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; -public class TracingConsumer implements Consumer { +class TracingConsumer implements Consumer { private final Consumer consumer; private final KafkaTracing tracing; diff --git a/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java index c3c240ed7fe0..951b295ce4b9 100644 --- a/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java +++ b/instrumentation/kafka-clients/kafka-clients-2.6/library/src/main/java/io/opentelemetry/instrumentation/kafkaclients/TracingProducer.java @@ -20,7 +20,7 @@ import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; -public class TracingProducer implements Producer { +class TracingProducer implements Producer { private final Producer producer; private final KafkaTracing tracing;