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 元数据传播和检索跟踪标头。
OpenCensus Go SDK 提供 ochttp 包,提供从 http 响应中检索跟踪上下文的方法。
若要从 HTTP 响应检索跟踪上下文,可以使用 :
f := tracecontext.HTTPFormat{}
sc, ok := f.SpanContextFromRequest(req)
在 gRPC 调用返回时检索追踪上下文头部, 您可以将响应头的引用作为gRPC 调用选项传递给响应头,这个选项包含响应头:
var responseHeader metadata.MD
// Call the InvokeService with call option
// grpc.Header(&responseHeader)
client.InvokeService(ctx, &pb.InvokeServiceRequest{
Id: "client",
Message: &commonv1pb.InvokeRequest{
Method: "MyMethod",
ContentType: "text/plain; charset=UTF-8",
Data: &any.Any{Value: []byte("Hello")},
},
},
grpc.Header(&responseHeader))
要从 HTTP 响应检索跟踪上下文,可以使用 .NET API:
// client is HttpClient. req is HttpRequestMessage
HttpResponseMessage response = await client.SendAsync(req);
IEnumerable<string> values1, values2;
string traceparentValue = "";
string tracestateValue = "";
if (response.Headers.TryGetValues("traceparent", out values1))
{
traceparentValue = values1.FirstOrDefault();
}
if (response.Headers.TryGetValues("tracestate", out values2))
{
tracestateValue = values2.FirstOrDefault();
}
要从 gRPC 响应检索跟踪上下文,可以使用 Grpc.Net.Client ResponseHeadersAsync 方法。
// client is Dapr proto client
using var call = client.InvokeServiceAsync(req);
var response = await call.ResponseAsync;
var headers = await call.ResponseHeadersAsync();
var tracecontext = headers.First(e => e.Key == "grpc-trace-bin");
有关使用 .NET 客户端调用 gRPC 服务的其他细节 在此处。
注意: 在 Dapr SDK 中没有用于传播和检索跟踪上下文的辅助方法。 您需要使用 http/gRPC 客户端通过 http 标头和 gRPC 元数据传播和检索跟踪标头。
OpenCensus Go SDK 提供 ochttp 包,提供在 http 请求中附加跟踪上下文的方法。
f := tracecontext.HTTPFormat{}
req, _ := http.NewRequest("GET", "http://localhost:3500/v1.0/invoke/mathService/method/api/v1/add", nil)
traceContext := span.SpanContext()
f.SpanContextToRequest(traceContext, req)
traceContext := span.SpanContext()
traceContextBinary := propagation.Binary(traceContext)
然后,可以通过 gRPC 元数据 到 grpc-trace-bin
头传递跟踪上下文。
ctx = metadata.AppendToOutgoingContext(ctx, "grpc-trace-bin", string(traceContextBinary))
然后,您可以在后续的 Dapr gRPC 调用中继续传递此go上下文 ctx
作为第一个参数。 例如, InvokeService
,上下文在第一个参数中传递。
要在 HTTP 请求中传递跟踪上下文,可以使用 .NET API:
// client is HttpClient. req is HttpRequestMessage
req.Headers.Add("traceparent", traceparentValue);
req.Headers.Add("tracestate", tracestateValue);
HttpResponseMessage response = await client.SendAsync(req);
要在 gRPC 调用元数据中传递跟踪上下文,您可以使用 Grpc.Net.Client ResponseHeadersAsync 方法。
// client is Dapr.Client.Autogen.Grpc.v1
var headers = new Metadata();
headers.Add("grpc-trace-bin", tracecontext);
using var call = client.InvokeServiceAsync(req, headers);
有关使用 .NET 客户端调用 gRPC 服务的其他细节 在此处。
您可以使用推荐的 OpenCensus SDK 创建跟踪上下文。 OpenCensus 支持多种不同的编程语言。
语言 | SDK |
---|---|
Go | Link |
Java | Link |
C# | Link |
C++ | Link |
Node.js | Link |
Python | Link |
先决条件:OpenCensus Go 库需要 Go 1.8 或更高版本。 有关安装的详细信息,请访问 这里。
$ go get -u go.opencensus.io
ctx, span := trace.StartSpan(ctx, "cache.Get")
defer span.End()
// Do work to get from cache.
try (Scope ss = TRACER.spanBuilder("cache.Get").startScopedSpan()) {
}
with tracer.span(name="cache.get") as span:
pass
tracer.startRootSpan({name: 'cache.Get'}, rootSpan => {
});
opencensus::trace::Span span = opencensus::trace::Span::StartSpan(
"cache.Get", nullptr, {&sampler});
var span = tracer.SpanBuilder("cache.Get").StartScopedSpan();
首先需要在 Dapr 中启用跟踪配置。 提到此步骤是为了完整地从启用跟踪到调用具有跟踪上下文的 Dapr。 创建一个部署配置 yaml ,例如 appconfig.yaml
具有以下配置。
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: appconfig
spec:
tracing:
samplingRate: "1"
在 Kubernetes中,您可以应用以下配置 :
kubectl apply -f appconfig.yaml
然后在部署 YAML 中设置以下跟踪注释。 You can add the following annotaion in sample grpc app deployment yaml.
dapr.io/config: "appconfig"
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.
package main
import (
pb "github.com/dapr/go-sdk/dapr"
"go.opencensus.io/trace"
"go.opencensus.io/trace/propagation"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
// Get the Dapr port and create a connection
daprPort := os.Getenv("DAPR_GRPC_PORT")
daprAddress := fmt.Sprintf("localhost:%s", daprPort)
conn, err := grpc.Dial(daprAddress, grpc.WithInsecure())
if err != nil {
fmt.Println(err)
}
defer conn.Close()
// Create the client
client := pb.NewDaprClient(conn)
// Create the Trace Context
ctx , span := trace.StartSpan(context.Background(), "InvokeService")
// The returned context can be used to keep propagating the newly created span in the current context.
// In the same process, context.Context is used to propagate trace context.
// Across the process, use the propagation format of Trace Context to propagate trace context.
traceContext := propagation.Binary(span.SpanContext())
ctx = metadata.NewOutgoingContext(ctx, string(traceContext))
// Pass the trace context
resp, err := client.InvokeService(ctx, &pb.InvokeServiceRequest{
Id: "client",
Message: &commonv1pb.InvokeRequest{
Method: "MyMethod",
ContentType: "text/plain; charset=UTF-8",
Data: &any.Any{Value: []byte("Hello")},
},
})
现在,您可以使用相同的跟踪上下文将应用中和跨服务的调用与 Dapr 关联。