Search in sources :

Example 6 with TracingMetadata

use of io.smallrye.reactive.messaging.TracingMetadata in project smallrye-reactive-messaging by smallrye.

the class BatchTracingPropagationTest method testFromKafkaToAppWithNoParent.

@Test
public void testFromKafkaToAppWithNoParent() {
    MyAppReceivingData bean = runApplication(getKafkaSinkConfigForMyAppReceivingData(topic), MyAppReceivingData.class);
    companion.produceIntegers().usingGenerator(i -> new ProducerRecord<>(topic, null, null, "a-key", i), 10);
    await().until(() -> bean.list().size() >= 10);
    assertThat(bean.list()).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    assertThat(bean.tracing()).hasSizeGreaterThanOrEqualTo(10);
    assertThat(bean.tracing()).doesNotContainNull().doesNotHaveDuplicates();
    List<String> spanIds = new ArrayList<>();
    for (TracingMetadata tracing : bean.tracing()) {
        spanIds.add(Span.fromContext(tracing.getCurrentContext()).getSpanContext().getSpanId());
        assertThat(Span.fromContextOrNull(tracing.getPreviousContext())).isNull();
    }
    assertThat(spanIds).doesNotContainNull().doesNotHaveDuplicates().hasSizeGreaterThanOrEqualTo(10);
    for (SpanData data : testExporter.getFinishedSpanItems()) {
        assertThat(data.getSpanId()).isIn(spanIds);
        assertThat(data.getSpanId()).isNotEqualTo(data.getParentSpanId());
        assertThat(data.getKind()).isEqualByComparingTo(SpanKind.CONSUMER);
    }
}
Also used : SpanData(io.opentelemetry.sdk.trace.data.SpanData) TracingMetadata(io.smallrye.reactive.messaging.TracingMetadata) ArrayList(java.util.ArrayList) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) Test(org.junit.jupiter.api.Test)

Example 7 with TracingMetadata

use of io.smallrye.reactive.messaging.TracingMetadata in project smallrye-reactive-messaging by smallrye.

the class TracingUtils method createOutgoingTrace.

/**
 * Creates a new outgoing message span message, and ensures span metadata is added to the
 * message headers.
 *
 * @param message the source message
 * @param headers the outgoing headers, must be mutable
 * @param exchange the target exchange
 * @param routingKey the routing key
 * @param attributeHeaders a list (possibly empty) of header names whose values (if present)
 *        should be used as span attributes
 */
public static void createOutgoingTrace(final Message<?> message, final Map<String, Object> headers, final String exchange, final String routingKey, final List<String> attributeHeaders) {
    // Extract tracing metadata from the source message itself
    final TracingMetadata tracingMetadata = TracingMetadata.fromMessage(message).orElse(null);
    final SpanBuilder spanBuilder = tracer.spanBuilder(exchange + " send").setSpanKind(SpanKind.PRODUCER);
    if (tracingMetadata != null) {
        // Handle possible parent span
        final Context parentSpanContext = tracingMetadata.getPreviousContext();
        if (parentSpanContext != null) {
            spanBuilder.setParent(parentSpanContext);
        } else {
            spanBuilder.setNoParent();
        }
    } else {
        spanBuilder.setNoParent();
    }
    final Span span = spanBuilder.startSpan();
    final Context sendingContext = Context.current().with(span);
    // Filter the outgoing message headers to just those that should map to span tags
    final Map<String, Object> headerValues = message.getMetadata(OutgoingRabbitMQMetadata.class).map(md -> md.getHeaders().entrySet().stream().filter(e -> attributeHeaders.contains(e.getKey())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))).orElse(Collections.emptyMap());
    setOutgoingSpanAttributes(span, exchange, routingKey, headerValues);
    // Set span onto outgoing headers
    GlobalOpenTelemetry.getPropagators().getTextMapPropagator().inject(sendingContext, headers, HeadersMapInjectAdapter.SETTER);
    span.end();
}
Also used : Context(io.opentelemetry.context.Context) Context(io.opentelemetry.context.Context) IncomingRabbitMQMessage(io.smallrye.reactive.messaging.rabbitmq.IncomingRabbitMQMessage) Span(io.opentelemetry.api.trace.Span) SemanticAttributes(io.opentelemetry.semconv.trace.attributes.SemanticAttributes) TracingMetadata(io.smallrye.reactive.messaging.TracingMetadata) Tracer(io.opentelemetry.api.trace.Tracer) Collectors(java.util.stream.Collectors) SpanKind(io.opentelemetry.api.trace.SpanKind) OutgoingRabbitMQMetadata(io.smallrye.reactive.messaging.rabbitmq.OutgoingRabbitMQMetadata) GlobalOpenTelemetry(io.opentelemetry.api.GlobalOpenTelemetry) List(java.util.List) Message(org.eclipse.microprofile.reactive.messaging.Message) Envelope(com.rabbitmq.client.Envelope) Map(java.util.Map) SpanBuilder(io.opentelemetry.api.trace.SpanBuilder) Collections(java.util.Collections) SpanBuilder(io.opentelemetry.api.trace.SpanBuilder) TracingMetadata(io.smallrye.reactive.messaging.TracingMetadata) Span(io.opentelemetry.api.trace.Span) Map(java.util.Map)

Example 8 with TracingMetadata

use of io.smallrye.reactive.messaging.TracingMetadata in project smallrye-reactive-messaging by smallrye.

the class TracingUtils method getTracingMetaData.

/**
 * Extract tracing metadata from a received RabbitMQ message and return
 * it as {@link TracingMetadata}.
 *
 * @param msg the incoming RabbitMQ message
 * @return a {@link TracingMetadata} instance, possibly empty but never null
 */
public static TracingMetadata getTracingMetaData(final io.vertx.rabbitmq.RabbitMQMessage msg) {
    // Default
    TracingMetadata tracingMetadata = TracingMetadata.empty();
    if (msg.properties().getHeaders() != null) {
        // Extract the tracing headers from the incoming RabbitMQ message into a tracing context
        final Context context = GlobalOpenTelemetry.getPropagators().getTextMapPropagator().extract(io.opentelemetry.context.Context.root(), msg.properties().getHeaders(), HeadersMapExtractAdapter.GETTER);
        // create tracing metadata based on that tracing context
        tracingMetadata = TracingMetadata.withPrevious(context);
    }
    return tracingMetadata;
}
Also used : Context(io.opentelemetry.context.Context) TracingMetadata(io.smallrye.reactive.messaging.TracingMetadata)

Example 9 with TracingMetadata

use of io.smallrye.reactive.messaging.TracingMetadata in project smallrye-reactive-messaging by smallrye.

the class TracingUtils method addIncomingTrace.

/**
 * Creates a span based on any tracing metadata in the incoming message.
 *
 * @param msg the incoming message
 * @param attributeHeaders a list (possibly empty) of header names whose values (if present)
 *        should be used as span attributes
 * @param <T> the message body type
 * @return the message, with injected tracing metadata
 */
public static <T> Message<T> addIncomingTrace(final IncomingRabbitMQMessage<T> msg, final String queue, final List<String> attributeHeaders) {
    final TracingMetadata tracingMetadata = TracingMetadata.fromMessage(msg).orElse(TracingMetadata.empty());
    final Envelope envelope = msg.getRabbitMQMessage().envelope();
    final SpanBuilder spanBuilder = tracer.spanBuilder(envelope.getExchange() + " receive").setSpanKind(SpanKind.CONSUMER);
    // Handle possible parent span
    final Context parentSpanContext = tracingMetadata.getPreviousContext();
    if (parentSpanContext != null) {
        spanBuilder.setParent(parentSpanContext);
    } else {
        spanBuilder.setNoParent();
    }
    final Span span = spanBuilder.startSpan();
    // Filter the incoming message headers to just those that should map to span tags
    final Map<String, Object> headerValues = msg.getHeaders().entrySet().stream().filter(e -> attributeHeaders.contains(e.getKey())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    try {
        setIncomingSpanAttributes(span, queue, envelope.getRoutingKey(), headerValues);
        // Make available as parent for subsequent spans inside message processing
        span.makeCurrent();
        msg.injectTracingMetadata(tracingMetadata.withSpan(span));
    } finally {
        span.end();
    }
    return msg;
}
Also used : Context(io.opentelemetry.context.Context) Context(io.opentelemetry.context.Context) IncomingRabbitMQMessage(io.smallrye.reactive.messaging.rabbitmq.IncomingRabbitMQMessage) Span(io.opentelemetry.api.trace.Span) SemanticAttributes(io.opentelemetry.semconv.trace.attributes.SemanticAttributes) TracingMetadata(io.smallrye.reactive.messaging.TracingMetadata) Tracer(io.opentelemetry.api.trace.Tracer) Collectors(java.util.stream.Collectors) SpanKind(io.opentelemetry.api.trace.SpanKind) OutgoingRabbitMQMetadata(io.smallrye.reactive.messaging.rabbitmq.OutgoingRabbitMQMetadata) GlobalOpenTelemetry(io.opentelemetry.api.GlobalOpenTelemetry) List(java.util.List) Message(org.eclipse.microprofile.reactive.messaging.Message) Envelope(com.rabbitmq.client.Envelope) Map(java.util.Map) SpanBuilder(io.opentelemetry.api.trace.SpanBuilder) Collections(java.util.Collections) SpanBuilder(io.opentelemetry.api.trace.SpanBuilder) TracingMetadata(io.smallrye.reactive.messaging.TracingMetadata) Envelope(com.rabbitmq.client.Envelope) Span(io.opentelemetry.api.trace.Span) Map(java.util.Map)

Example 10 with TracingMetadata

use of io.smallrye.reactive.messaging.TracingMetadata in project smallrye-reactive-messaging by smallrye.

the class BatchTracingPropagationTest method testFromKafkaToAppWithParentSpan.

@Test
public void testFromKafkaToAppWithParentSpan() {
    String parentTopic = topic + "-parent";
    String stuffTopic = topic + "-stuff";
    MyAppReceivingData bean = runApplication(getKafkaSinkConfigForMyAppReceivingData(parentTopic), MyAppReceivingData.class);
    List<SpanContext> producedSpanContexts = new CopyOnWriteArrayList<>();
    companion.produceIntegers().usingGenerator(i -> new ProducerRecord<>(parentTopic, null, null, "a-key", i, createTracingSpan(producedSpanContexts, stuffTopic)), 10);
    await().until(() -> bean.list().size() >= 10);
    assertThat(bean.list()).containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    List<String> producedTraceIds = producedSpanContexts.stream().map(SpanContext::getTraceId).collect(Collectors.toList());
    assertThat(producedTraceIds).hasSize(10);
    assertThat(bean.tracing()).hasSizeGreaterThanOrEqualTo(10);
    assertThat(bean.tracing()).doesNotContainNull().doesNotHaveDuplicates();
    List<String> receivedTraceIds = bean.tracing().stream().map(tracingMetadata -> Span.fromContext(tracingMetadata.getCurrentContext()).getSpanContext().getTraceId()).collect(Collectors.toList());
    assertThat(receivedTraceIds).doesNotContainNull().doesNotHaveDuplicates().hasSize(10);
    assertThat(receivedTraceIds).containsExactlyInAnyOrderElementsOf(producedTraceIds);
    List<String> spanIds = new ArrayList<>();
    for (TracingMetadata tracing : bean.tracing()) {
        spanIds.add(Span.fromContext(tracing.getCurrentContext()).getSpanContext().getSpanId());
        assertThat(tracing.getPreviousContext()).isNotNull();
        Span previousSpan = Span.fromContextOrNull(tracing.getPreviousContext());
        assertThat(previousSpan).isNotNull();
        assertThat(previousSpan.getSpanContext().getTraceId()).isEqualTo(Span.fromContext(tracing.getCurrentContext()).getSpanContext().getTraceId());
        assertThat(previousSpan.getSpanContext().getSpanId()).isNotEqualTo(Span.fromContext(tracing.getCurrentContext()).getSpanContext().getSpanId());
    }
    assertThat(spanIds).doesNotContainNull().doesNotHaveDuplicates().hasSizeGreaterThanOrEqualTo(10);
    List<String> parentIds = bean.tracing().stream().map(tracingMetadata -> Span.fromContextOrNull(tracingMetadata.getPreviousContext()).getSpanContext().getSpanId()).collect(Collectors.toList());
    assertThat(producedSpanContexts.stream().map(SpanContext::getSpanId)).containsExactlyElementsOf(parentIds);
    for (SpanData data : testExporter.getFinishedSpanItems()) {
        assertThat(data.getSpanId()).isIn(spanIds);
        assertThat(data.getSpanId()).isNotEqualTo(data.getParentSpanId());
        assertThat(data.getKind()).isEqualByComparingTo(SpanKind.CONSUMER);
        assertThat(data.getParentSpanId()).isNotNull();
        assertThat(data.getParentSpanId()).isIn(parentIds);
    }
}
Also used : Sampler(io.opentelemetry.sdk.trace.samplers.Sampler) BeforeEach(org.junit.jupiter.api.BeforeEach) ProducerRecord(org.apache.kafka.clients.producer.ProducerRecord) Outgoing(org.eclipse.microprofile.reactive.messaging.Outgoing) KafkaCompanionTestBase(io.smallrye.reactive.messaging.kafka.base.KafkaCompanionTestBase) W3CTraceContextPropagator(io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator) OpenTelemetrySdk(io.opentelemetry.sdk.OpenTelemetrySdk) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) Multi(io.smallrye.mutiny.Multi) ArrayList(java.util.ArrayList) AfterAll(org.junit.jupiter.api.AfterAll) RecordHeaders(org.apache.kafka.common.header.internals.RecordHeaders) ConsumerTask(io.smallrye.reactive.messaging.kafka.companion.ConsumerTask) StringDeserializer(org.apache.kafka.common.serialization.StringDeserializer) SimpleSpanProcessor(io.opentelemetry.sdk.trace.export.SimpleSpanProcessor) ContextPropagators(io.opentelemetry.context.propagation.ContextPropagators) Duration(java.time.Duration) IntegerSerializer(org.apache.kafka.common.serialization.IntegerSerializer) KafkaConnector(io.smallrye.reactive.messaging.kafka.KafkaConnector) Context(io.opentelemetry.context.Context) Awaitility.await(org.awaitility.Awaitility.await) Span(io.opentelemetry.api.trace.Span) SpanContext(io.opentelemetry.api.trace.SpanContext) Publisher(org.reactivestreams.Publisher) TracingMetadata(io.smallrye.reactive.messaging.TracingMetadata) RecordQualifiers.until(io.smallrye.reactive.messaging.kafka.companion.RecordQualifiers.until) KafkaMapBasedConfig(io.smallrye.reactive.messaging.kafka.base.KafkaMapBasedConfig) Collectors(java.util.stream.Collectors) SpanKind(io.opentelemetry.api.trace.SpanKind) StandardCharsets(java.nio.charset.StandardCharsets) SdkTracerProvider(io.opentelemetry.sdk.trace.SdkTracerProvider) GlobalOpenTelemetry(io.opentelemetry.api.GlobalOpenTelemetry) Test(org.junit.jupiter.api.Test) List(java.util.List) AfterEach(org.junit.jupiter.api.AfterEach) CompletionStage(java.util.concurrent.CompletionStage) InMemorySpanExporter(io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter) KafkaRecord(io.smallrye.reactive.messaging.kafka.KafkaRecord) Header(org.apache.kafka.common.header.Header) KafkaRecordBatch(io.smallrye.reactive.messaging.kafka.KafkaRecordBatch) IntegerDeserializer(org.apache.kafka.common.serialization.IntegerDeserializer) ApplicationScoped(javax.enterprise.context.ApplicationScoped) SpanData(io.opentelemetry.sdk.trace.data.SpanData) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) Incoming(org.eclipse.microprofile.reactive.messaging.Incoming) SpanProcessor(io.opentelemetry.sdk.trace.SpanProcessor) SpanContext(io.opentelemetry.api.trace.SpanContext) SpanData(io.opentelemetry.sdk.trace.data.SpanData) TracingMetadata(io.smallrye.reactive.messaging.TracingMetadata) ArrayList(java.util.ArrayList) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) Span(io.opentelemetry.api.trace.Span) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) Test(org.junit.jupiter.api.Test)

Aggregations

TracingMetadata (io.smallrye.reactive.messaging.TracingMetadata)15 Context (io.opentelemetry.context.Context)12 Span (io.opentelemetry.api.trace.Span)11 SpanData (io.opentelemetry.sdk.trace.data.SpanData)8 ArrayList (java.util.ArrayList)8 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)8 GlobalOpenTelemetry (io.opentelemetry.api.GlobalOpenTelemetry)7 SpanKind (io.opentelemetry.api.trace.SpanKind)7 List (java.util.List)7 Collectors (java.util.stream.Collectors)7 Test (org.junit.jupiter.api.Test)7 SpanBuilder (io.opentelemetry.api.trace.SpanBuilder)6 Message (org.eclipse.microprofile.reactive.messaging.Message)6 SpanContext (io.opentelemetry.api.trace.SpanContext)5 W3CTraceContextPropagator (io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator)5 ContextPropagators (io.opentelemetry.context.propagation.ContextPropagators)5 OpenTelemetrySdk (io.opentelemetry.sdk.OpenTelemetrySdk)5 InMemorySpanExporter (io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter)5 SdkTracerProvider (io.opentelemetry.sdk.trace.SdkTracerProvider)5 SpanProcessor (io.opentelemetry.sdk.trace.SpanProcessor)5