user3105453
user3105453

Reputation: 1981

Name an external dependency in Zipkin to have it drawn

I am using Zipkin with Spring Sleuth to display traces. When I use it locally, http://localhost:9411/zipkin/dependency/ displays a nicely created graph of dependencies within the eco-system. Sometimes, backends from outside that eco-system get called and those are not displayed in that graph. Is it possible to annotate a call (let's assume RestTemplate and Feign clients) to such an external system so Zipkin would actually draw that dependency? If it's possible, what do I have to do?

This would be my baseline of code:

@Bean
RestTemplate restTemplate() {
    return new RestTemplate();
}

@RequestMapping("/")
public String callExternalBackend() {
    return restTemplate.getForObject("https://httpbin.org/get", String.class);
}

Somewhere I would like to type httpbin so this call gets drawn in the dependency-graph of Zipkin.

Thank you!


// Edit based on current solution I'm using Spring Cloud Finchley and added the following line before restTemplate's call:

@RequestMapping("/")
public String callBackend() {
    spanCustomizer.tag("peer.service", "httpbin");
    return restTemplate.getForObject("https://httpbin.org/get", String.class);
}

I simply inject SpanCustomizer in this class. The Span is sent to Zipkin and I see the tag is set:

enter image description here

Unfortunately, it is not drawn in the dependencies-view. Is there anything else I need to configure, maybe in Zipkin rather than in Sleuth?

Upvotes: 0

Views: 557

Answers (1)

Marcin Grzejszczak
Marcin Grzejszczak

Reputation: 11179

EDGWARE

Have you read the documentation? If you use Spring Cloud Sleuth in Edgware version if you read the Sleuth section you would find this piece of the documentation https://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#_custom_sa_tag_in_zipkin

Let me copy that for you

54.5 Custom SA tag in Zipkin Sometimes you want to create a manual Span that will wrap a call to an external service which is not instrumented. What you can do is to create a span with the peer.service tag that will contain a value of the service that you want to call. Below you can see an example of a call to Redis that is wrapped in such a span.

org.springframework.cloud.sleuth.Span newSpan = tracer.createSpan("redis");
try {
    newSpan.tag("redis.op", "get");
    newSpan.tag("lc", "redis");
    newSpan.logEvent(org.springframework.cloud.sleuth.Span.CLIENT_SEND);
    // call redis service e.g
    // return (SomeObj) redisTemplate.opsForHash().get("MYHASH", someObjKey);
} finally {
    newSpan.tag("peer.service", "redisService");
    newSpan.tag("peer.ipv4", "1.2.3.4");
    newSpan.tag("peer.port", "1234");
    newSpan.logEvent(org.springframework.cloud.sleuth.Span.CLIENT_RECV);
    tracer.close(newSpan);
}

[Important] Important Remember not to add both peer.service tag and the SA tag! You have to add only peer.service.

FINCHLEY

The SA tag will not work for Finchley. You have to do it in the following manner using the remoteEndpoint on the span.

    Span span = tracer.newTrace().name("redis"); 
    span.remoteEndpoint(Endpoint.newBuilder().serviceName("redis").build()); 
    span.kind(CLIENT);
    try(SpanInScope ws = tracer.withSpanInScope(span.start())) {
          // add any tags / annotations on the span
          // return (SomeObj) redisTemplate.opsForHash().get("MYHASH", someObjKey);
    } finally {
      span.finish();
    }

Upvotes: 1

Related Questions