1
votes

I'm using this library (grpc-spring-boot-starter) so I can have gRPC capabilities in a Spring Boot app.

I want to know how to properly integrate this with Istio + Jaeger tracing.

I need to know what are the needed dependencies for this to happen.

I have two (2) apps, one serves as the gRPC client and one serves as the gRPC server,

The expectation is that the trace between the gRPC client and the gRPC server must be reflected in Jaeger. But it's not happening.

I am inside a Kubernetes cluster that has Istio.

What really happens is HTTP request -> Envoy sidecar -> gRPC Client's Spring Boot @RestController -> get the Headers from HTTP request -> copy those to gRPC call before making the call -> gRPC Service.

How can I make the gRPC client <-> gRPC Service trace shown to Jaeger?

Are there any dependencies that needs to be imported?

Right now I have:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<!-- Used together with Sleuth to be able to trace gRPC calls. -->
<dependency>
    <groupId>io.zipkin.brave</groupId>
    <artifactId>brave-instrumentation-grpc</artifactId>
</dependency>
<!-- Add'l dependency for Istio + Jaeger gRPC tracing -->
<dependency>
    <groupId>io.jaegertracing</groupId>
    <artifactId>jaeger-client</artifactId>
</dependency>

I also have done something like this to "propagate the headers":

private void propagateHeaders(HttpHeaders headers) {
    // TODO: adding these string values to a final / constant.
    // get these tracing headers from HTTP request, (coming from Envoy)
    String xRequestIdFromHttpHeader = headers.getFirst("x-request-id");
    String xB3TraceIdFromHttpHeader = headers.getFirst("x-b3-traceid");
    String xB3SpanIdFromHttpHeader = headers.getFirst("x-b3-spanid");
    String xB3ParentSpanIdFromHttpHeader = headers.getFirst("x-b3-parentspanid");
    String xB3SampledFromHttpHeader = headers.getFirst("x-b3-sampled");
    String xB3FlagsFromHttpHeader = headers.getFirst("x-b3-flags");
    String xOtSpanContextFromHttpHeader = headers.getFirst("x-ot-span-context");

    // create a custom gRPC header, they call it Metadata
    Metadata xRequestIdMetadata = new Metadata();
    Metadata xB3TraceIdMetadata = new Metadata();
    Metadata xB3SpanIdMetadata = new Metadata();
    Metadata xB3ParentSpanIdMetadata = new Metadata();
    Metadata xB3SampledMetadata = new Metadata();

    // TODO: refactor. putting to List<> and using foreach to attach this one.
    // assign value of the x-request-id Metadata to the value of the HTTP Header
    xRequestIdMetadata.put(Metadata.Key.of("x-request-id", Metadata.ASCII_STRING_MARSHALLER), xRequestIdFromHttpHeader);
    xB3TraceIdMetadata.put(Metadata.Key.of("x-b3-traceid", Metadata.ASCII_STRING_MARSHALLER), xB3TraceIdFromHttpHeader);
    xB3SpanIdMetadata.put(Metadata.Key.of("x-b3-spanid", Metadata.ASCII_STRING_MARSHALLER), xB3SpanIdFromHttpHeader);
    xB3ParentSpanIdMetadata.put(Metadata.Key.of("x-b3-parentspanid", Metadata.ASCII_STRING_MARSHALLER), xB3ParentSpanIdFromHttpHeader);
    xB3SampledMetadata.put(Metadata.Key.of("x-b3-sampled", Metadata.ASCII_STRING_MARSHALLER), xB3SampledFromHttpHeader);

    // TODO: refactor. putting to List<> and using foreach to attach this one.
    // use MetadataUtils to attach that new Metadata to our stub before requesting to our gRPC Server via gRPC
    greetingServiceStub = MetadataUtils.attachHeaders(greetingServiceStub, xRequestIdMetadata);
    greetingServiceStub = MetadataUtils.attachHeaders(greetingServiceStub, xB3TraceIdMetadata);
    greetingServiceStub = MetadataUtils.attachHeaders(greetingServiceStub, xB3SpanIdMetadata);
    greetingServiceStub = MetadataUtils.attachHeaders(greetingServiceStub, xB3ParentSpanIdMetadata);
    greetingServiceStub = MetadataUtils.attachHeaders(greetingServiceStub, xB3SampledMetadata);
}

But it doesn't seem to work..

1
Could you explain what´s wrong? Your apps works but you dont see any tracing? Did you configure jaeger and trace sampling as mentioned in istio documentation? Additionally take a look at this article.Jakub
Oh sorry, yes, the problem is that I should be expecting a the trace / span between my grpc client (Spring Boot) and grpc server (Spring Boot). But I don't see it. The request goes through as I'm getting a valid response but the traces are not there. I also see the HTTP requests I went through before going to the gRPC part.. but not the gRPC traces itself. I am now investigating that this is due to Spring Cloud Sleuth + brave-instrumentation-grpc dependency, assuming that Istio works as intended.Ken Flake
I have not dived into the Istio part, I'm just assuming that it's configured properly. We're using Rancher to enable Istio by the way. I'll check out the docs and article as you've mentioned, thank you so much for this! As of now actually I can't pinpoint whether my app is at fault or an Istio config is missing.Ken Flake
@KenFlake did you find an answer? Would you mind posting the solution?kane
hi @kane, the overall idea is Istio will take care of the Jaeger tracing propagation, NOT in the application-level. By that, I updated my K8s Service of my gRPC Client. The "name" of the K8s Service should start with the "grpc" prefix (important, this is included as well in Istio docs), then, for the port, for some reason port 8080 didn't work. I used 50101 and it did work. I can't explain why, though..Ken Flake

1 Answers

1
votes

What you did is for http 1.x, and it doesn't work for http2/grpc. Please dive into grpc impl in springboot doc.