Tracing Analysis provides a set of tools for distributed application development, including trace mapping, call statistics, trace topology, and application dependency analysis. Alibaba Cloud Service Mesh (ASM) is integrated with Tracing Analysis. This topic describes how to use headers to trace gRPC-based services in ASM.

Sample project

For information about the sample project of gRPC, visit hello-servicemesh-grpc. The directories in this topic are directories of hello-servicemesh-grpc.

Obtain headers on the gRPC server and client

Obtain headers on the gRPC server

  • Basic methods
    • Use Java to implement the basic method to obtain headers on the gRPC server.

      Implement the interceptCall(ServerCall<ReqT, RespT> call,final Metadata m,ServerCallHandler<ReqT, RespT> h) method of the ServerInterceptor operation. Then, run the String v = m.get(k) command to obtain headers on the server. The type of the input parameter of the get() method is Metadata.Key<String>.

    • Use Go to implement the basic method to obtain headers on the gRPC server.

      Implement the metadata.FromIncomingContext(ctx)(md MD, ok bool) method. The format of MD is map[string][]string.

    • Use Node.js to implement the basic method to obtain headers on the gRPC server.

      Implement the call.metadata.getmap() method. The type of the returned value is [key: string]: MetadataValue. The type of MetadataValue is string/Buffer.

    • Use Python to implement the basic method to obtain headers on the gRPC server.

      Implement the context.invocation_metadata() method. The returned value is a two-tuple array in the format of ('k','v'). The key-value pair can be obtained from m.key, m.value.

  • Unary RPC
    • Use Java to implement the unary remote procedure call (RPC) method to obtain headers on the server.

      The headers are intercepted.

    • Use Go to implement the unary RPC method to obtain headers on the server.

      Call metadata.FromIncomingContext(ctx) in the method. The value of the ctx parameter is obtained from the input parameter of the Talk method.

    • Use Node.js to implement the unary RPC method to obtain headers on the server.

      Call call.metadata.getMap() in the method.

    • Use Python to implement the unary RPC method to obtain headers on the server.

      Call context.invocation_metadata() in the method.

  • Server streaming RPC
    • Use Java to implement the server streaming RPC method to obtain headers on the server.

      The headers are intercepted.

    • Use Go to implement the server streaming RPC method to obtain headers on the server.

      Call metadata.FromIncomingContext(ctx) in the method. You can call the stream.Context() method to obtain the value of the ctx parameter from the input parameter stream of the TalkOneAnswerMore method.

    • Use Node.js to implement the server streaming RPC method to obtain headers on the server.

      Call call.metadata.getmap() in the method.

    • Use Python to implement the server streaming RPC method to obtain headers on the server.

      Call context.invocation_metadata() in the method.

  • Client streaming RPC
    • Use Java to implement the client streaming RPC method to obtain headers on the server.

      The headers are intercepted.

    • Use Go to implement the client streaming RPC method to obtain headers on the server.

      Call metadata.FromIncomingContext(ctx) in the method. You can call the stream.Context() method to obtain the value of the ctx parameter from the input parameter stream of the TalkMoreAnswerOne method.

    • Use Node.js to implement the client streaming RPC method to obtain headers on the server.

      Call call.metadata.getmap() in the method.

    • Use Python to implement the client streaming RPC method to obtain headers on the server.

      Call context.invocation_metadata() in the method.

  • Bidirectional streaming RPC
    • Use Java to implement the bidirectional streaming RPC method to obtain headers on the server.

      The headers are intercepted.

    • Use Go to implement the bidirectional streaming RPC method to obtain headers on the server.

      Call metadata.FromIncomingContext(ctx) in the method. You can call the stream.Context() method to obtain the value of the ctx parameter from the input parameter stream of the TalkBidirectional method.

    • Use Node.js to implement the bidirectional streaming RPC method to obtain headers on the server.

      Call call.metadata.getmap() in the method.

    • Use Python to implement the bidirectional streaming RPC method to obtain headers on the server.

      Call context.invocation_metadata() in the method.

Send headers from the client

  • Basic methods
    • Use Java to implement the basic method to send headers from the client.

      Implement the interceptCall(MethodDescriptor<ReqT, RespT> m, CallOptions o, Channel c) method of the ClientInterceptor operation. Implement the start((Listener<RespT> l, Metadata h)) method of the ClientCall<ReqT, RespT> type. Then, run h.put(k, v) to send headers on the client. The type of the input parameter k of put is Metadata.Key<String>, and that of the input parameter v is String.

    • Use Go to implement the basic method to send headers from the client.

      metadata.AppendToOutgoingContext(ctx,kv ...) context.Context

    • Use Node.js to implement the basic method to send headers from the client.

      metadata=call.metadata.getMap()metadata.add(key, headers[key])

    • Use Python to implement the basic method to send headers from the client.

      Set the variable in the metadata_dict = {} command in the following format: metadata_dict[c.key] = c.value. Convert the type of data in the metadata_dict array to list tuple by using list(metadata_dict.items()).

  • Unary RPC
    • Use Java to implement the unary RPC method to send headers from the client.

      The headers are intercepted.

    • Use Go to implement the unary RPC method to send headers on the client.

      Call metadata.AppendToOutgoingContext(ctx,kv) in the method.

    • Use Node.js to implement the unary RPC method to send headers from the client.

      Call the basic method.

    • Use Python to implement the unary RPC method to send headers from the client.

      Call the basic method.

  • Server streaming RPC
    • Use Java to implement the server streaming RPC method to send headers from the client.

      The headers are intercepted.

    • Use Go to implement the server streaming RPC method to send headers from the client.

      Call metadata.AppendToOutgoingContext(ctx,kv) in the method.

    • Use Node.js to implement the server streaming RPC method to send headers from the client.

      Call the basic method.

    • Use Python to implement the server streaming RPC method to send headers from the client.

      Call the basic method.

  • Client streaming RPC
    • Use Java to implement the client streaming RPC method to send headers from the client.

      The headers are intercepted.

    • Use Go to implement the client streaming RPC method to send headers from the client.

      Call metadata.AppendToOutgoingContext(ctx,kv) in the method.

    • Use Node.js to implement the client streaming RPC method to send headers from the client.

      Call the basic method.

    • Use Python to implement the client streaming RPC method to send headers from the client.

      Call the basic method.

  • Bidirectional streaming RPC
    • Use Java to implement the bidirectional streaming RPC method to send headers from the client.

      The headers are intercepted.

    • Use Go to implement the bidirectional streaming RPC method to send headers from the client.

      Call metadata.AppendToOutgoingContext(ctx,kv) in the method.

    • Use Node.js to implement the bidirectional streaming RPC method to send headers from the client.

      Call the basic method.

    • Use Python to implement the bidirectional streaming RPC method to send headers from the client.

      Call the basic method.

Propaganda Headers

In Tracing Analysis, upstream link metadata must be passed through to the downstream to obtain the complete information of a trace. Therefore, the tracing-related header information that is obtained on the server must be passed through to the client that sends the request to the downstream.

The operations of the communication models that are implemented by using Go, Node.js, and Python can receive headers. Therefore, the following three actions can be implemented in order by using the operations of the four communication models: First, the server reads the headers. Then, the server passes the headers. Last, the client sends the headers.

The operations of the communication models that are implemented by using Java cannot be used to propaganda headers in an ordered process. This is because Java reads and writes headers by using two interceptors. Only the read interceptor obtains the unique ID of the tracing. In addition, gRPC services may receive and send requests at the same time. As a result, the two interceptors cannot be connected by using caching, which is the most intuitive method to show traces.

Java uses Metadata-Context Propagation to trace headers.Metadata-Context propagation

When the server interceptor reads headers, the headers are written into Context by using ctx.withValue(key, metadata). The type of the key parameter is Context.Key<String>. Then, the client interceptor reads the headers from Context by using key.get(). By default, the get method uses Context.current(). This ensures that the same context is used when headers are read and written.

When headers can be propagandized, you can trace the request and response messages between the gRPC client and server.

Deploy and verify the topology of the ASM instance

Before you enable Tracing Analysis for gRPC-based services, you must deploy and verify the topology of the AMS instance where the gRPC-based services reside. Make sure that the topology of ASM instance works as expected.

The tracing directory of the sample project contains deployment scripts in Java, Go, Node.js, and Python. In this example, the Go deployment script is used to deploy and verify the topology of the ASM instance.
cd go
# Deploy the topology of the ASM instance.
sh apply.sh
# Verify the topology of the ASM instance.
sh test.sh

If no exceptions occur, the topology of the ASM instance works as expected.

The following figure shows the deployed topology of the ASM instance.ASM instance topology

Tracing data

  1. Log on to the ASM console.
  2. In the left-side navigation pane, choose Service Mesh > Mesh Management.
  3. On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column of the ASM instance.
  4. On the Mesh Management page, click Settings in the upper-right corner.
  5. In the Settings Update panel, select Enable Tracing Analysis, set Sampling method to Tracing Analysis, and then click OK.
  6. In the left-side navigation pane, click Tracing Analysis to go to the Tracing Analysis console.
  7. In the left-side navigation pane of the Tracing Analysis console, click Trace Entrance.
  8. On the Trace Entrance page, click Application Topology of the destination application.
    You can see the complete link, including the local requestor -Ingressgateway-grpc-server-svc1-grpc-server-svc2-grpc-server-svc3.Tracing data
  9. On the End-to-End Aggregation page, click the End-to-End Aggregation tab to view aggregated traces.
    End-to-End Aggregation
  10. On the End-to-End Aggregation tab, click a trace in the Span Name column to view the detailed information of the trace.
    Trace