Skip to content

Commit

Permalink
Translate Spring 6 HTTP spans to Stackdriver convention
Browse files Browse the repository at this point in the history
From Spring Cloud Sleuth to Spring Framework 6, the tags on HTTP spans changed. This updates the SpanTranslator to handle the Spring 6 tags.
  • Loading branch information
shakuzen committed Nov 18, 2024
1 parent fdefc59 commit b1eb627
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
import com.google.devtools.cloudtrace.v2.Span.TimeEvent;
import com.google.devtools.cloudtrace.v2.Span.TimeEvents;
import com.google.protobuf.Timestamp;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Logger;

import static java.util.logging.Level.FINE;
import static zipkin2.reporter.stackdriver.brave.AttributesExtractor.toAttributeValue;
import static zipkin2.reporter.stackdriver.brave.SpanUtil.toTruncatableString;

/** SpanTranslator converts a Zipkin Span to a Stackdriver Trace Span. */
Expand All @@ -33,6 +36,15 @@ final class SpanTranslator {
RENAMED_LABELS.put("http.url", "/http/url");
}

private static final Map<String, String> SPRING6_RENAMED_HTTP_LABELS;

static {
Map<String, String> map = new LinkedHashMap<>();
map.put("status", "/http/status_code");
map.put("method", "/http/method");
SPRING6_RENAMED_HTTP_LABELS = Collections.unmodifiableMap(map);
}

private final AttributesExtractor attributesExtractor;

SpanTranslator(Tag<Throwable> errorTag) {
Expand Down Expand Up @@ -79,6 +91,16 @@ Span.Builder translate(Span.Builder spanBuilder, MutableSpan braveSpan) {
}
spanBuilder.setAttributes(attributesExtractor.extract(braveSpan));

// Spring 6 HTTP spans need mapping to Stackdriver conventional attribute names
if (braveSpan.name() != null && braveSpan.name().contains("http")) {
braveSpan.tags().forEach((key, value) -> {
if (SPRING6_RENAMED_HTTP_LABELS.containsKey(key)) {
spanBuilder.getAttributesBuilder()
.putAttributeMap(SPRING6_RENAMED_HTTP_LABELS.get(key), toAttributeValue(value));
}
});
}

if (braveSpan.annotationCount() > 0) {
TimeEvents.Builder events = TimeEvents.newBuilder();
braveSpan.forEachAnnotation(SpanTranslator::addAnnotation, events);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import static zipkin2.reporter.stackdriver.brave.AttributesExtractor.toAttributeValue;
import static zipkin2.reporter.stackdriver.brave.SpanUtil.toTruncatableString;
import static zipkin2.reporter.stackdriver.brave.TestObjects.clientSpan;
import static zipkin2.reporter.stackdriver.brave.TestObjects.spring6ServerSpan;

class SpanTranslatorTest {
SpanTranslator spanTranslator = new SpanTranslator(Tags.ERROR);
Expand Down Expand Up @@ -73,4 +74,48 @@ class SpanTranslatorTest {

assertThat(translated.getDisplayName().getValue()).isEqualTo("unknown");
}

@Test void translate_spring6ServerSpan() {
MutableSpan braveSpan = spring6ServerSpan();
Span translated = spanTranslator.translate(Span.newBuilder(), braveSpan).build();

assertThat(translated)
.isEqualTo(
Span.newBuilder()
.setSpanId(braveSpan.id())
.setDisplayName(toTruncatableString("http get /test"))
.setStartTime(Timestamp.newBuilder().setSeconds(1472470996).setNanos(199_000_000).build())
.setEndTime(Timestamp.newBuilder().setSeconds(1472470996).setNanos(406_000_000).build())
.setAttributes(Span.Attributes.newBuilder()
.putAttributeMap("/agent", toAttributeValue("zipkin-java"))
.putAttributeMap("exception", toAttributeValue("none"))
.putAttributeMap("/http/url", toAttributeValue("/test"))
.putAttributeMap("/http/method", toAttributeValue("GET"))
.putAttributeMap("outcome", toAttributeValue("SUCCESS"))
.putAttributeMap("/http/status_code", toAttributeValue("200"))
.putAttributeMap("uri", toAttributeValue("/test"))
.putAttributeMap("method", toAttributeValue("GET"))
.putAttributeMap("status", toAttributeValue("200"))
.putAttributeMap("/kind", toAttributeValue("server"))
.putAttributeMap("/component", toAttributeValue("backend"))
.putAttributeMap("endpoint.ipv4", toAttributeValue("127.0.0.1"))
.build())
.setTimeEvents(Span.TimeEvents.newBuilder()
.addTimeEvent(Span.TimeEvent.newBuilder()
.setTime(Timestamp.newBuilder().setSeconds(1472470996).setNanos(238_000_000).build())
.setAnnotation(
Span.TimeEvent.Annotation.newBuilder()
.setDescription(toTruncatableString("foo"))
.build())
.build())
.addTimeEvent(Span.TimeEvent.newBuilder()
.setTime(Timestamp.newBuilder().setSeconds(1472470996).setNanos(403_000_000).build())
.setAnnotation(
Span.TimeEvent.Annotation.newBuilder()
.setDescription(toTruncatableString("bar"))
.build())
.build())
.build())
.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,25 @@ static MutableSpan clientSpan() {
braveSpan.tag("http.path", "/api");
return braveSpan;
}

static MutableSpan spring6ServerSpan() {
MutableSpan braveSpan = new MutableSpan();
braveSpan.traceId("673adb3c54aa03af9e941a86a679a9d5");
braveSpan.id("9e941a86a679a9d5");
braveSpan.name("http get /test");
braveSpan.kind(brave.Span.Kind.SERVER);
braveSpan.localServiceName("backend");
braveSpan.localIp("127.0.0.1");
braveSpan.startTimestamp(1472470996199000L);
braveSpan.finishTimestamp(1472470996199000L + 207000L);
braveSpan.annotate(1472470996238000L, "foo");
braveSpan.annotate(1472470996403000L, "bar");
braveSpan.tag("exception", "none");
braveSpan.tag("http.url", "/test");
braveSpan.tag("method", "GET");
braveSpan.tag("outcome", "SUCCESS");
braveSpan.tag("status", "200");
braveSpan.tag("uri", "/test");
return braveSpan;
}
}

0 comments on commit b1eb627

Please sign in to comment.