Search in sources :

Example 6 with CONSUMER

use of zipkin2.Span.Kind.CONSUMER in project zipkin by openzipkin.

the class ITActiveMQCollector method skipsOnSpanStorageException.

/**
 * Guards against errors that leak from storage, such as InvalidQueryException
 */
@Test
public void skipsOnSpanStorageException() throws Exception {
    collector.close();
    AtomicInteger counter = new AtomicInteger();
    consumer = (input) -> new Call.Base<Void>() {

        @Override
        protected Void doExecute() {
            throw new AssertionError();
        }

        @Override
        protected void doEnqueue(Callback<Void> callback) {
            if (counter.getAndIncrement() == 1) {
                callback.onError(new RuntimeException("storage fell over"));
            } else {
                receivedSpans.add(spans);
                callback.onSuccess(null);
            }
        }

        @Override
        public Call<Void> clone() {
            throw new AssertionError();
        }
    };
    activemq.pushMessage(collector.queue, PROTO3.encodeList(spans));
    // tossed on error
    activemq.pushMessage(collector.queue, PROTO3.encodeList(spans));
    activemq.pushMessage(collector.queue, PROTO3.encodeList(spans));
    collector = builder().storage(buildStorage(consumer)).build().start();
    assertThat(receivedSpans.take()).containsExactlyElementsOf(spans);
    // the only way we could read this, is if the malformed span was skipped.
    assertThat(receivedSpans.take()).containsExactlyElementsOf(spans);
    assertThat(activemqMetrics.messages()).isEqualTo(3);
    // storage failure not message failure
    assertThat(activemqMetrics.messagesDropped()).isZero();
    assertThat(activemqMetrics.bytes()).isEqualTo(PROTO3.encodeList(spans).length * 3);
    assertThat(activemqMetrics.spans()).isEqualTo(spans.size() * 3);
    // only one dropped
    assertThat(activemqMetrics.spansDropped()).isEqualTo(spans.size());
}
Also used : Call(zipkin2.Call) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Test(org.junit.Test)

Example 7 with CONSUMER

use of zipkin2.Span.Kind.CONSUMER in project zipkin by openzipkin.

the class KafkaCollectorWorker method run.

@Override
public void run() {
    try (KafkaConsumer<byte[], byte[]> kafkaConsumer = new KafkaConsumer<>(properties)) {
        kafkaConsumer.subscribe(topics, // added for integration tests only, see ITKafkaCollector
        new ConsumerRebalanceListener() {

            @Override
            public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
                // technically we should remove only the revoked partitions but for test purposes it
                // does not matter
                assignedPartitions.set(Collections.emptyList());
            }

            @Override
            public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
                assignedPartitions.set(Collections.unmodifiableList(new ArrayList<>(partitions)));
            }
        });
        LOG.debug("Kafka consumer starting polling loop.");
        while (running.get()) {
            final ConsumerRecords<byte[], byte[]> consumerRecords = kafkaConsumer.poll(Duration.of(1000, ChronoUnit.MILLIS));
            LOG.debug("Kafka polling returned batch of {} messages.", consumerRecords.count());
            for (ConsumerRecord<byte[], byte[]> record : consumerRecords) {
                final byte[] bytes = record.value();
                metrics.incrementMessages();
                metrics.incrementBytes(bytes.length);
                // lenient on empty messages
                if (bytes.length == 0)
                    continue;
                if (bytes.length < 2) {
                    // need two bytes to check if protobuf
                    metrics.incrementMessagesDropped();
                } else {
                    // If we received legacy single-span encoding, decode it into a singleton list
                    if (!protobuf3(bytes) && bytes[0] <= 16 && bytes[0] != 12) /* thrift, but not list */
                    {
                        Span span;
                        try {
                            span = SpanBytesDecoder.THRIFT.decodeOne(bytes);
                        } catch (RuntimeException e) {
                            metrics.incrementMessagesDropped();
                            continue;
                        }
                        collector.accept(Collections.singletonList(span), NOOP);
                    } else {
                        collector.acceptSpans(bytes, NOOP);
                    }
                }
            }
        }
    } catch (RuntimeException | Error e) {
        LOG.warn("Unexpected error in polling loop spans", e);
        throw e;
    } finally {
        LOG.debug("Kafka consumer polling loop stopped. Kafka consumer closed.");
    }
}
Also used : KafkaConsumer(org.apache.kafka.clients.consumer.KafkaConsumer) ConsumerRebalanceListener(org.apache.kafka.clients.consumer.ConsumerRebalanceListener) Span(zipkin2.Span) TopicPartition(org.apache.kafka.common.TopicPartition)

Example 8 with CONSUMER

use of zipkin2.Span.Kind.CONSUMER in project zipkin by openzipkin.

the class ITRabbitMQCollector method skipsOnSpanStorageException.

/**
 * Guards against errors that leak from storage, such as InvalidQueryException
 */
@Test
void skipsOnSpanStorageException() throws Exception {
    AtomicInteger counter = new AtomicInteger();
    consumer = (input) -> new Call.Base<Void>() {

        @Override
        protected Void doExecute() {
            throw new AssertionError();
        }

        @Override
        protected void doEnqueue(Callback<Void> callback) {
            if (counter.getAndIncrement() == 1) {
                callback.onError(new RuntimeException("storage fell over"));
            } else {
                receivedSpans.add(spans);
                callback.onSuccess(null);
            }
        }

        @Override
        public Call<Void> clone() {
            throw new AssertionError();
        }
    };
    final StorageComponent storage = buildStorage(consumer);
    RabbitMQCollector.Builder builder = builder("storage_exception").storage(storage);
    produceSpans(THRIFT.encodeList(spans), builder.queue);
    // tossed on error
    produceSpans(THRIFT.encodeList(spans), builder.queue);
    produceSpans(THRIFT.encodeList(spans), builder.queue);
    try (RabbitMQCollector collector = builder.build()) {
        collector.start();
        assertThat(receivedSpans.take()).containsExactlyElementsOf(spans);
        // the only way we could read this, is if the malformed span was skipped.
        assertThat(receivedSpans.take()).containsExactlyElementsOf(spans);
    }
    assertThat(rabbitmqMetrics.messages()).isEqualTo(3);
    // storage failure isn't a message failure
    assertThat(rabbitmqMetrics.messagesDropped()).isZero();
    assertThat(rabbitmqMetrics.bytes()).isEqualTo(THRIFT.encodeList(spans).length * 3);
    assertThat(rabbitmqMetrics.spans()).isEqualTo(spans.size() * 3);
    // only one dropped
    assertThat(rabbitmqMetrics.spansDropped()).isEqualTo(spans.size());
}
Also used : Call(zipkin2.Call) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) StorageComponent(zipkin2.storage.StorageComponent) ForwardingStorageComponent(zipkin2.storage.ForwardingStorageComponent) Test(org.junit.jupiter.api.Test)

Example 9 with CONSUMER

use of zipkin2.Span.Kind.CONSUMER in project zipkin by openzipkin.

the class V1SpanConverter method processAnnotations.

void processAnnotations(V1Span source) {
    for (int i = 0, length = source.annotations.size(); i < length; i++) {
        V1Annotation a = source.annotations.get(i);
        Span.Builder currentSpan = forEndpoint(source, a.endpoint);
        // core annotations require an endpoint. Don't give special treatment when that's missing
        if (a.value.length() == 2 && a.endpoint != null) {
            if (a.value.equals("cs")) {
                currentSpan.kind(Kind.CLIENT);
                cs = a;
            } else if (a.value.equals("sr")) {
                currentSpan.kind(Kind.SERVER);
                sr = a;
            } else if (a.value.equals("ss")) {
                currentSpan.kind(Kind.SERVER);
                ss = a;
            } else if (a.value.equals("cr")) {
                currentSpan.kind(Kind.CLIENT);
                cr = a;
            } else if (a.value.equals("ms")) {
                currentSpan.kind(Kind.PRODUCER);
                ms = a;
            } else if (a.value.equals("mr")) {
                currentSpan.kind(Kind.CONSUMER);
                mr = a;
            } else if (a.value.equals("ws")) {
                ws = a;
            } else if (a.value.equals("wr")) {
                wr = a;
            } else {
                currentSpan.addAnnotation(a.timestamp, a.value);
            }
        } else {
            currentSpan.addAnnotation(a.timestamp, a.value);
        }
    }
    // When bridging between event and span model, you can end up missing a start annotation
    if (cs == null && endTimestampReflectsSpanDuration(cr, source)) {
        cs = V1Annotation.create(source.timestamp, "cs", cr.endpoint);
    }
    if (sr == null && endTimestampReflectsSpanDuration(ss, source)) {
        sr = V1Annotation.create(source.timestamp, "sr", ss.endpoint);
    }
    if (cs != null && sr != null) {
        // in a shared span, the client side owns span duration by annotations or explicit timestamp
        maybeTimestampDuration(source, cs, cr);
        // special-case loopback: We need to make sure on loopback there are two span2s
        Span.Builder client = forEndpoint(source, cs.endpoint);
        Span.Builder server;
        if (hasSameServiceName(cs.endpoint, sr.endpoint)) {
            client.kind(Kind.CLIENT);
            // fork a new span for the server side
            server = newSpanBuilder(source, sr.endpoint).kind(Kind.SERVER);
        } else {
            server = forEndpoint(source, sr.endpoint);
        }
        // the server side is smaller than that, we have to read annotations to find out
        server.shared(true).timestamp(sr.timestamp);
        if (ss != null)
            server.duration(ss.timestamp - sr.timestamp);
        // one-way has no duration
        if (cr == null && source.duration == 0)
            client.duration(null);
    } else if (cs != null && cr != null) {
        maybeTimestampDuration(source, cs, cr);
    } else if (sr != null && ss != null) {
        maybeTimestampDuration(source, sr, ss);
    } else {
        // otherwise, the span is incomplete. revert special-casing
        handleIncompleteRpc(source);
    }
    // implied shared. When we only see the server-side, carry this signal over.
    if (cs == null && sr != null && // case could be due to the client-side of that RPC.
    (source.timestamp == 0 || (ss != null && source.duration == 0))) {
        forEndpoint(source, sr.endpoint).shared(true);
    }
    // ms and mr are not supposed to be in the same span, but in case they are..
    if (ms != null && mr != null) {
        // special-case loopback: We need to make sure on loopback there are two span2s
        Span.Builder producer = forEndpoint(source, ms.endpoint);
        Span.Builder consumer;
        if (hasSameServiceName(ms.endpoint, mr.endpoint)) {
            producer.kind(Kind.PRODUCER);
            // fork a new span for the consumer side
            consumer = newSpanBuilder(source, mr.endpoint).kind(Kind.CONSUMER);
        } else {
            consumer = forEndpoint(source, mr.endpoint);
        }
        consumer.shared(true);
        if (wr != null) {
            consumer.timestamp(wr.timestamp).duration(mr.timestamp - wr.timestamp);
        } else {
            consumer.timestamp(mr.timestamp);
        }
        producer.timestamp(ms.timestamp).duration(ws != null ? ws.timestamp - ms.timestamp : null);
    } else if (ms != null) {
        maybeTimestampDuration(source, ms, ws);
    } else if (mr != null) {
        if (wr != null) {
            maybeTimestampDuration(source, wr, mr);
        } else {
            maybeTimestampDuration(source, mr, null);
        }
    } else {
        if (ws != null)
            forEndpoint(source, ws.endpoint).addAnnotation(ws.timestamp, ws.value);
        if (wr != null)
            forEndpoint(source, wr.endpoint).addAnnotation(wr.timestamp, wr.value);
    }
}
Also used : Span(zipkin2.Span) Endpoint(zipkin2.Endpoint)

Example 10 with CONSUMER

use of zipkin2.Span.Kind.CONSUMER in project zipkin by openzipkin.

the class ScribeSpanConsumerTest method entriesWithoutSpansAreSkipped.

@Test
void entriesWithoutSpansAreSkipped() throws Exception {
    SpanConsumer consumer = (callback) -> {
        // as we shouldn't get here.
        throw new AssertionError();
    };
    ScribeSpanConsumer scribe = newScribeSpanConsumer("zipkin", consumer);
    LogEntry entry = new LogEntry();
    entry.category = "notzipkin";
    entry.message = "hello world";
    expectSuccess(scribe, entry);
    // Storage finishes after callback so wait for it.
    await().untilAsserted(() -> assertThat(scribeMetrics.messages()).isEqualTo(1));
    assertThat(scribeMetrics.messagesDropped()).isZero();
    assertThat(scribeMetrics.bytes()).isZero();
    assertThat(scribeMetrics.spans()).isZero();
    assertThat(scribeMetrics.spansDropped()).isZero();
}
Also used : LogEntry(zipkin2.collector.scribe.generated.LogEntry) InMemoryCollectorMetrics(zipkin2.collector.InMemoryCollectorMetrics) Arrays(java.util.Arrays) ForwardingStorageComponent(zipkin2.storage.ForwardingStorageComponent) Awaitility.await(org.awaitility.Awaitility.await) SpanConsumer(zipkin2.storage.SpanConsumer) InMemoryStorage(zipkin2.storage.InMemoryStorage) UTF_8(java.nio.charset.StandardCharsets.UTF_8) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) V1SpanConverter(zipkin2.v1.V1SpanConverter) Span(zipkin2.Span) V1Span(zipkin2.v1.V1Span) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) CountDownLatch(java.util.concurrent.CountDownLatch) Base64(java.util.Base64) Endpoint(zipkin2.Endpoint) Arrays.asList(java.util.Arrays.asList) SpanBytesEncoder(zipkin2.codec.SpanBytesEncoder) AsyncMethodCallback(org.apache.thrift.async.AsyncMethodCallback) Callback(zipkin2.Callback) StorageComponent(zipkin2.storage.StorageComponent) Call(zipkin2.Call) ResultCode(zipkin2.collector.scribe.generated.ResultCode) SpanConsumer(zipkin2.storage.SpanConsumer) LogEntry(zipkin2.collector.scribe.generated.LogEntry) Test(org.junit.jupiter.api.Test)

Aggregations

Span (zipkin2.Span)17 Test (org.junit.Test)13 Test (org.junit.jupiter.api.Test)7 LogEntry (zipkin2.collector.scribe.generated.LogEntry)6 ProducerRecord (org.apache.kafka.clients.producer.ProducerRecord)4 Call (zipkin2.Call)4 Endpoint (zipkin2.Endpoint)4 StorageComponent (zipkin2.storage.StorageComponent)4 List (java.util.List)3 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)3 TopicPartition (org.apache.kafka.common.TopicPartition)3 Assertions.assertThat (org.assertj.core.api.Assertions.assertThat)3 Before (org.junit.Before)3 Tracing (brave.Tracing)2 Sampler (brave.sampler.Sampler)2 ArrayList (java.util.ArrayList)2 Map (java.util.Map)2 TimeUnit (java.util.concurrent.TimeUnit)2 MethodInvocation (org.aopalliance.intercept.MethodInvocation)2 ConsumerRecord (org.apache.kafka.clients.consumer.ConsumerRecord)2