use of zipkin2.Span.Kind.CONSUMER in project brave by openzipkin.
the class TracingConsumer method poll.
/**
* This
*/
@Override
public ConsumerRecords<K, V> poll(long timeout) {
ConsumerRecords<K, V> records = delegate.poll(timeout);
if (records.isEmpty() || tracing.isNoop())
return records;
Map<String, Span> consumerSpansForTopic = new LinkedHashMap<>();
for (TopicPartition partition : records.partitions()) {
String topic = partition.topic();
List<ConsumerRecord<K, V>> recordsInPartition = records.records(partition);
for (int i = 0, length = recordsInPartition.size(); i < length; i++) {
ConsumerRecord<K, V> record = recordsInPartition.get(i);
TraceContextOrSamplingFlags extracted = extractor.extract(record.headers());
// make or reuse a span for this topic
if (extracted.samplingFlags() != null && extracted.extra().isEmpty()) {
Span consumerSpanForTopic = consumerSpansForTopic.get(topic);
if (consumerSpanForTopic == null) {
consumerSpansForTopic.put(topic, consumerSpanForTopic = tracing.tracer().nextSpan(extracted).name("poll").kind(Span.Kind.CONSUMER).tag(KafkaTags.KAFKA_TOPIC_TAG, topic).start());
}
// no need to remove propagation headers as we failed to extract anything
injector.inject(consumerSpanForTopic.context(), record.headers());
} else {
// we extracted request-scoped data, so cannot share a consumer span.
Span span = tracing.tracer().nextSpan(extracted);
if (!span.isNoop()) {
span.name("poll").kind(Span.Kind.CONSUMER).tag(KafkaTags.KAFKA_TOPIC_TAG, topic);
if (remoteServiceName != null) {
span.remoteEndpoint(Endpoint.newBuilder().serviceName(remoteServiceName).build());
}
// span won't be shared by other records
span.start().finish();
}
// remove prior propagation headers from the record
tracing.propagation().keys().forEach(key -> record.headers().remove(key));
injector.inject(span.context(), record.headers());
}
}
}
consumerSpansForTopic.values().forEach(span -> {
if (remoteServiceName != null) {
span.remoteEndpoint(Endpoint.newBuilder().serviceName(remoteServiceName).build());
}
span.finish();
});
return records;
}
use of zipkin2.Span.Kind.CONSUMER in project brave by openzipkin.
the class ITKafkaTracing method continues_a_trace_when_only_trace_id_propagated.
@Test
public void continues_a_trace_when_only_trace_id_propagated() throws Exception {
consumerTracing = KafkaTracing.create(Tracing.newBuilder().spanReporter(consumerSpans::add).propagationFactory(new Propagation.Factory() {
@Override
public <K> Propagation<K> create(Propagation.KeyFactory<K> keyFactory) {
return new TraceIdOnlyPropagation<>(keyFactory);
}
}).sampler(Sampler.ALWAYS_SAMPLE).build());
producerTracing = KafkaTracing.create(Tracing.newBuilder().spanReporter(producerSpans::add).propagationFactory(new Propagation.Factory() {
@Override
public <K> Propagation<K> create(Propagation.KeyFactory<K> keyFactory) {
return new TraceIdOnlyPropagation<>(keyFactory);
}
}).sampler(Sampler.ALWAYS_SAMPLE).build());
producer = createTracingProducer();
consumer = createTracingConsumer();
producer.send(new ProducerRecord<>(testName.getMethodName(), TEST_KEY, TEST_VALUE)).get();
ConsumerRecords<String, String> records = consumer.poll(10000);
assertThat(records).hasSize(1);
Span producerSpan = producerSpans.take();
Span consumerSpan = consumerSpans.take();
assertThat(producerSpan.traceId()).isEqualTo(consumerSpan.traceId());
for (ConsumerRecord<String, String> record : records) {
TraceContext forProcessor = consumerTracing.nextSpan(record).context();
assertThat(forProcessor.traceIdString()).isEqualTo(consumerSpan.traceId());
}
}
use of zipkin2.Span.Kind.CONSUMER in project brave by openzipkin.
the class TracingRabbitListenerAdviceTest method reports_span_if_consume_fails.
@Test
public void reports_span_if_consume_fails() throws Throwable {
Message message = MessageBuilder.withBody(new byte[] {}).build();
onMessageConsumeFailed(message, new RuntimeException("expected exception"));
assertThat(reportedSpans).extracting(Span::kind).containsExactly(CONSUMER, null);
assertThat(reportedSpans).filteredOn(span -> span.kind() == null).extracting(Span::tags).extracting(tags -> tags.get("error")).contains("expected exception");
}
use of zipkin2.Span.Kind.CONSUMER in project brave by openzipkin.
the class TracingRabbitListenerAdviceTest method reports_span_if_consume_fails_with_no_message.
@Test
public void reports_span_if_consume_fails_with_no_message() throws Throwable {
Message message = MessageBuilder.withBody(new byte[] {}).build();
onMessageConsumeFailed(message, new RuntimeException());
assertThat(reportedSpans).extracting(Span::kind).containsExactly(CONSUMER, null);
assertThat(reportedSpans).filteredOn(span -> span.kind() == null).extracting(Span::tags).extracting(tags -> tags.get("error")).contains("RuntimeException");
}
use of zipkin2.Span.Kind.CONSUMER in project brave by openzipkin.
the class V2SpanConverter method toSpan.
/**
* Converts the input, parsing {@link Span#kind()} into RPC annotations.
*/
public static zipkin.Span toSpan(Span in) {
String traceId = in.traceId();
zipkin.Span.Builder result = zipkin.Span.builder().traceId(HexCodec.lowerHexToUnsignedLong(traceId)).parentId(in.parentId() != null ? HexCodec.lowerHexToUnsignedLong(in.parentId()) : null).id(HexCodec.lowerHexToUnsignedLong(in.id())).debug(in.debug()).name(// avoid a NPE
in.name() != null ? in.name() : "");
if (traceId.length() == 32) {
result.traceIdHigh(HexCodec.lowerHexToUnsignedLong(traceId, 0));
}
long startTs = in.timestamp() == null ? 0L : in.timestamp();
Long endTs = in.duration() == null ? 0L : in.timestamp() + in.duration();
if (startTs != 0L) {
result.timestamp(startTs);
result.duration(in.duration());
}
zipkin.Endpoint local = in.localEndpoint() != null ? toEndpoint(in.localEndpoint()) : null;
zipkin.Endpoint remote = in.remoteEndpoint() != null ? toEndpoint(in.remoteEndpoint()) : null;
Kind kind = in.kind();
Annotation cs = null, sr = null, ss = null, cr = null, ms = null, mr = null, ws = null, wr = null;
String remoteEndpointType = null;
boolean wroteEndpoint = false;
for (int i = 0, length = in.annotations().size(); i < length; i++) {
zipkin2.Annotation input = in.annotations().get(i);
Annotation a = Annotation.create(input.timestamp(), input.value(), local);
if (a.value.length() == 2) {
if (a.value.equals(Constants.CLIENT_SEND)) {
kind = Kind.CLIENT;
cs = a;
remoteEndpointType = SERVER_ADDR;
} else if (a.value.equals(Constants.SERVER_RECV)) {
kind = Kind.SERVER;
sr = a;
remoteEndpointType = CLIENT_ADDR;
} else if (a.value.equals(Constants.SERVER_SEND)) {
kind = Kind.SERVER;
ss = a;
} else if (a.value.equals(Constants.CLIENT_RECV)) {
kind = Kind.CLIENT;
cr = a;
} else if (a.value.equals(Constants.MESSAGE_SEND)) {
kind = Kind.PRODUCER;
ms = a;
} else if (a.value.equals(Constants.MESSAGE_RECV)) {
kind = Kind.CONSUMER;
mr = a;
} else if (a.value.equals(Constants.WIRE_SEND)) {
ws = a;
} else if (a.value.equals(Constants.WIRE_RECV)) {
wr = a;
} else {
wroteEndpoint = true;
result.addAnnotation(a);
}
} else {
wroteEndpoint = true;
result.addAnnotation(a);
}
}
if (kind != null) {
switch(kind) {
case CLIENT:
remoteEndpointType = Constants.SERVER_ADDR;
if (startTs != 0L)
cs = Annotation.create(startTs, Constants.CLIENT_SEND, local);
if (endTs != 0L)
cr = Annotation.create(endTs, Constants.CLIENT_RECV, local);
break;
case SERVER:
remoteEndpointType = Constants.CLIENT_ADDR;
if (startTs != 0L)
sr = Annotation.create(startTs, Constants.SERVER_RECV, local);
if (endTs != 0L)
ss = Annotation.create(endTs, Constants.SERVER_SEND, local);
break;
case PRODUCER:
remoteEndpointType = Constants.MESSAGE_ADDR;
if (startTs != 0L)
ms = Annotation.create(startTs, Constants.MESSAGE_SEND, local);
if (endTs != 0L)
ws = Annotation.create(endTs, Constants.WIRE_SEND, local);
break;
case CONSUMER:
remoteEndpointType = Constants.MESSAGE_ADDR;
if (startTs != 0L && endTs != 0L) {
wr = Annotation.create(startTs, Constants.WIRE_RECV, local);
mr = Annotation.create(endTs, Constants.MESSAGE_RECV, local);
} else if (startTs != 0L) {
mr = Annotation.create(startTs, Constants.MESSAGE_RECV, local);
}
break;
default:
throw new AssertionError("update kind mapping");
}
}
for (Map.Entry<String, String> tag : in.tags().entrySet()) {
wroteEndpoint = true;
result.addBinaryAnnotation(BinaryAnnotation.create(tag.getKey(), tag.getValue(), local));
}
if (cs != null || sr != null || ss != null || cr != null || ws != null || wr != null || ms != null || mr != null) {
if (cs != null)
result.addAnnotation(cs);
if (sr != null)
result.addAnnotation(sr);
if (ss != null)
result.addAnnotation(ss);
if (cr != null)
result.addAnnotation(cr);
if (ws != null)
result.addAnnotation(ws);
if (wr != null)
result.addAnnotation(wr);
if (ms != null)
result.addAnnotation(ms);
if (mr != null)
result.addAnnotation(mr);
wroteEndpoint = true;
} else if (local != null && remote != null) {
// special-case when we are missing core annotations, but we have both address annotations
result.addBinaryAnnotation(BinaryAnnotation.address(CLIENT_ADDR, local));
wroteEndpoint = true;
remoteEndpointType = SERVER_ADDR;
}
if (remoteEndpointType != null && remote != null) {
result.addBinaryAnnotation(BinaryAnnotation.address(remoteEndpointType, remote));
}
// don't report server-side timestamp on shared or incomplete spans
if (Boolean.TRUE.equals(in.shared()) && sr != null) {
result.timestamp(null).duration(null);
}
if (local != null && !wroteEndpoint) {
// create a dummy annotation
result.addBinaryAnnotation(BinaryAnnotation.create(LOCAL_COMPONENT, "", local));
}
return result.build();
}
Aggregations