How-To : 使用 Dapr 的 W3C 跟踪上下文

将 W3C 追踪标准与 Dapr 一起使用

如何使用追踪上下文

Dapr 使用 W3C 追踪上下文对服务调用和 pub/sub 消息传递进行分布式跟踪。 Dapr 承担生成和传播跟踪上下文信息的所有繁重工作,并且很少需要传播或创建跟踪上下文。 First read scenarios in the W3C distributed tracing article to understand whether you need to propagate or create a trace context.

To view traces, read the how to diagnose with tracing article.

如何从响应中检索跟踪上下文

注意: 在 Dapr SDK 中没有用于传播和检索跟踪上下文的辅助方法。 您需要使用 http/gRPC 客户端通过 http 标头和 gRPC 元数据传播和检索跟踪标头。

在 Go 中检索跟踪上下文

对于 HTTP 调用

OpenCensus Go SDK 提供 ochttp 包,提供从 http 响应中检索跟踪上下文的方法。

若要从 HTTP 响应检索跟踪上下文,可以使用 :

  1. f := tracecontext.HTTPFormat{}
  2. sc, ok := f.SpanContextFromRequest(req)

对于gRPC 调用

在 gRPC 调用返回时检索追踪上下文头部, 您可以将响应头的引用作为gRPC 调用选项传递给响应头,这个选项包含响应头:

  1. var responseHeader metadata.MD
  2. // Call the InvokeService with call option
  3. // grpc.Header(&responseHeader)
  4. client.InvokeService(ctx, &pb.InvokeServiceRequest{
  5. Id: "client",
  6. Message: &commonv1pb.InvokeRequest{
  7. Method: "MyMethod",
  8. ContentType: "text/plain; charset=UTF-8",
  9. Data: &any.Any{Value: []byte("Hello")},
  10. },
  11. },
  12. grpc.Header(&responseHeader))

在 C# 中检索跟踪上下文

对于 HTTP 调用

要从 HTTP 响应检索跟踪上下文,可以使用 .NET API:

  1. // client is HttpClient. req is HttpRequestMessage
  2. HttpResponseMessage response = await client.SendAsync(req);
  3. IEnumerable<string> values1, values2;
  4. string traceparentValue = "";
  5. string tracestateValue = "";
  6. if (response.Headers.TryGetValues("traceparent", out values1))
  7. {
  8. traceparentValue = values1.FirstOrDefault();
  9. }
  10. if (response.Headers.TryGetValues("tracestate", out values2))
  11. {
  12. tracestateValue = values2.FirstOrDefault();
  13. }

对于gRPC 调用

要从 gRPC 响应检索跟踪上下文,可以使用 Grpc.Net.Client ResponseHeadersAsync 方法。

  1. // client is Dapr proto client
  2. using var call = client.InvokeServiceAsync(req);
  3. var response = await call.ResponseAsync;
  4. var headers = await call.ResponseHeadersAsync();
  5. var tracecontext = headers.First(e => e.Key == "grpc-trace-bin");

有关使用 .NET 客户端调用 gRPC 服务的其他细节 在此处

如何在请求中传播跟踪上下文

注意: 在 Dapr SDK 中没有用于传播和检索跟踪上下文的辅助方法。 您需要使用 http/gRPC 客户端通过 http 标头和 gRPC 元数据传播和检索跟踪标头。

在 Go 中传递跟踪上下文

对于 HTTP 调用

OpenCensus Go SDK 提供 ochttp 包,提供在 http 请求中附加跟踪上下文的方法。

  1. f := tracecontext.HTTPFormat{}
  2. req, _ := http.NewRequest("GET", "http://localhost:3500/v1.0/invoke/mathService/method/api/v1/add", nil)
  3. traceContext := span.SpanContext()
  4. f.SpanContextToRequest(traceContext, req)

对于gRPC 调用

  1. traceContext := span.SpanContext()
  2. traceContextBinary := propagation.Binary(traceContext)

然后,可以通过 gRPC 元数据grpc-trace-bin 头传递跟踪上下文。

  1. ctx = metadata.AppendToOutgoingContext(ctx, "grpc-trace-bin", string(traceContextBinary))

然后,您可以在后续的 Dapr gRPC 调用中继续传递此go上下文 ctx 作为第一个参数。 例如, InvokeService,上下文在第一个参数中传递。

在 C 中传递跟踪上下文

对于 HTTP 调用

要在 HTTP 请求中传递跟踪上下文,可以使用 .NET API:

  1. // client is HttpClient. req is HttpRequestMessage
  2. req.Headers.Add("traceparent", traceparentValue);
  3. req.Headers.Add("tracestate", tracestateValue);
  4. HttpResponseMessage response = await client.SendAsync(req);

对于gRPC 调用

要在 gRPC 调用元数据中传递跟踪上下文,您可以使用 Grpc.Net.Client ResponseHeadersAsync 方法。

  1. // client is Dapr.Client.Autogen.Grpc.v1
  2. var headers = new Metadata();
  3. headers.Add("grpc-trace-bin", tracecontext);
  4. using var call = client.InvokeServiceAsync(req, headers);

有关使用 .NET 客户端调用 gRPC 服务的其他细节 在此处

如何创建跟踪上下文

您可以使用推荐的 OpenCensus SDK 创建跟踪上下文。 OpenCensus 支持多种不同的编程语言。

语言SDK
GoLink
JavaLink
C#Link
C++Link
Node.jsLink
PythonLink

在 Go 中创建跟踪上下文

1. 1. 获取 OpenCensus Go SDK

先决条件:OpenCensus Go 库需要 Go 1.8 或更高版本。 有关安装的详细信息,请访问 这里

2. 2. 导入包 “go.openensuss.io/trace”

$ go get -u go.opencensus.io

3. 3. 创建跟踪上下文

  1. ctx, span := trace.StartSpan(ctx, "cache.Get")
  2. defer span.End()
  3. // Do work to get from cache.

在 Java 中创建跟踪上下文

  1. try (Scope ss = TRACER.spanBuilder("cache.Get").startScopedSpan()) {
  2. }

在 Python 中创建跟踪上下文

  1. with tracer.span(name="cache.get") as span:
  2. pass

在 NodeJS 中创建跟踪上下文

  1. tracer.startRootSpan({name: 'cache.Get'}, rootSpan => {
  2. });

在 C++ 中创建跟踪上下文

  1. opencensus::trace::Span span = opencensus::trace::Span::StartSpan(
  2. "cache.Get", nullptr, {&sampler});

在 C# 中创建跟踪上下文

  1. var span = tracer.SpanBuilder("cache.Get").StartScopedSpan();

把它和一个Go 示例一起放在一起

在 Dapr 中配置跟踪

首先需要在 Dapr 中启用跟踪配置。 提到此步骤是为了完整地从启用跟踪到调用具有跟踪上下文的 Dapr。 创建一个部署配置 yaml ,例如 appconfig.yaml 具有以下配置。

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Configuration
  3. metadata:
  4. name: appconfig
  5. spec:
  6. tracing:
  7. samplingRate: "1"

在 Kubernetes中,您可以应用以下配置 :

  1. kubectl apply -f appconfig.yaml

然后在部署 YAML 中设置以下跟踪注释。 You can add the following annotaion in sample grpc app deployment yaml.

  1. dapr.io/config: "appconfig"

使用跟踪上下文调用 dapr

Dapr 包含生成跟踪上下文,您无需明确创建跟踪上下文。

但是,如果您选择显式传递跟踪上下文,那么 Dapr 将使用被传递的跟踪上下文并在整个 HTTP/GRPC 调用中传播。

Using the grpc app in the example and putting this all together, the following steps show you how to create a Dapr client and call the InvokeService method passing the trace context:

The Rest code snippet and details, refer to the grpc app.

1. 导入包

  1. package main
  2. import (
  3. pb "github.com/dapr/go-sdk/dapr"
  4. "go.opencensus.io/trace"
  5. "go.opencensus.io/trace/propagation"
  6. "google.golang.org/grpc"
  7. "google.golang.org/grpc/metadata"
  8. )

2. 创建客户端

  1. // Get the Dapr port and create a connection
  2. daprPort := os.Getenv("DAPR_GRPC_PORT")
  3. daprAddress := fmt.Sprintf("localhost:%s", daprPort)
  4. conn, err := grpc.Dial(daprAddress, grpc.WithInsecure())
  5. if err != nil {
  6. fmt.Println(err)
  7. }
  8. defer conn.Close()
  9. // Create the client
  10. client := pb.NewDaprClient(conn)

3. 使用跟踪上下文调用 InvokeService 方法

  1. // Create the Trace Context
  2. ctx , span := trace.StartSpan(context.Background(), "InvokeService")
  3. // The returned context can be used to keep propagating the newly created span in the current context.
  4. // In the same process, context.Context is used to propagate trace context.
  5. // Across the process, use the propagation format of Trace Context to propagate trace context.
  6. traceContext := propagation.Binary(span.SpanContext())
  7. ctx = metadata.NewOutgoingContext(ctx, string(traceContext))
  8. // Pass the trace context
  9. resp, err := client.InvokeService(ctx, &pb.InvokeServiceRequest{
  10. Id: "client",
  11. Message: &commonv1pb.InvokeRequest{
  12. Method: "MyMethod",
  13. ContentType: "text/plain; charset=UTF-8",
  14. Data: &any.Any{Value: []byte("Hello")},
  15. },
  16. })

现在,您可以使用相同的跟踪上下文将应用中和跨服务的调用与 Dapr 关联。

相关链接