docs-08-tracing.md 4.6 KB

English version

08 - 上报Tracing到OpenTelemetry

SRPC支持产生和上报链路信息trace和span,并且可以通过多种途径进行上报,其中包括本地导出数据和上报到OpenTelemetry.

SRPC遵循OpenTelemetry数据规范(data specification)以及w3c的trace context,因此可以使用插件RPCTraceOpenTelemetry进行上报。

秉承着Workflow的风格,所有的上报都是异步任务模式,对RPC的请求和服务不会产生任何性能影响。

1. 用法

先构造插件RPCTraceOpenTelemetry,然后通过add_filter()把插件加到serverclient中。

tutorial-02-srpc_pb_client.cc作为client的示例,我们如下加两行代码:

int main()
{
    Example::SRPCClient client("127.0.0.1", 1412);

    RPCTraceOpenTelemetry span_otel("http://127.0.0.1:4318");
    client.add_filter(&span_otel);

    ...
}

tutorial-01-srpc_pb_server.cc作为server的示例,也增加类似的两行。同时我们还增加一个本地插件,用于把本次请求的trace数据也在屏幕上打印:

int main()
{
    SRPCServer server;

    RPCTraceOpenTelemetry span_otel("http://127.0.0.1:4318");
    server.add_filter(&span_otel);

    RPCTraceDefault span_log; // 这个插件会把本次请求的trace信息打到屏幕上
    server.add_filter(&span_log);

    ...
}

执行命令make tutorial可以编译出示例程序,并且分别把server和client跑起来,我们可以在屏幕上看到一些tracing信息:

image

我们可以看到上图client这边的span_id: 04d070f537,它在下图server这里变成了parent_span_id: 04d070f537

image

2. Traces上报到Jaeger

打开Jaeger的主页,我们可以找到我们名为Example的服务(service)和名为Echo的函数(method)。这一个tracing记录上有两个span节点,是由server和client分别上报的。

image

我们可以在Jaeger看到client所上报的span_id: 04d070f537和server所上报的span_id: 00202cf737,同时也是能对应上刚才在屏幕看到的id的。

image

3. 参数

多久收集一份trace信息、上报请求的重试次数、以及其他参数,都可以通过RPCTraceOpenTelemetry的构造函数指定。代码参考:src/module/rpc_trace_filter.h

默认每秒收集1000条trace信息,并且透传tracing信息等其他功能也已遵循上述规范实现。

4. Attributes

我们可以通过add_attributes()添加某些额外的信息,比如数据规范中的OTEL_RESOURCE_ATTRIBUTES。

注意我们的service名"Example"也是设置到attributes中的,key为service.name。如果用户也在OTEL_RESOURCE_ATTRIBUTES中使用了service.name这个key,则SRPC的service name优先级更高,参考:OpenTelemetry#resource

5. Log和Baggage

SRPC提供了log()baggage()接口,用户可以添加需要通过链路透传的数据。

void log(const RPCLogVector& fields);
void baggage(const std::string& key, const std::string& value);

作为Server,我们可以使用RPCContext上的接口来添加log:

class ExampleServiceImpl : public Example::Service                                 
{
public: 
    void Echo(EchoRequest *req, EchoResponse *resp, RPCContext *ctx) override
    {
        resp->set_message("Hi back");
        ctx->log({{"event", "info"}, {"message", "rpc server echo() end."}});
    }
};

作为client,我们可以使用RPCClientTask上的接口添加log:

srpc::SRPCClientTask *task = client.create_Echo_task(...);
task->log({{"event", "info"}, {"message", "log by rpc client echo()."}});