Describe the bug
When rpcz is enabled in a brpc client process, root client-side RPC spans may not be recorded if the RPC is initiated without an existing local parent span.
The client process can successfully enable /rpcz, and rpcz internal service calls may appear, but application-level client RPC spans are missing from the rpcz output.
Root cause: Controller::_span is stored as std::weak_ptr<Span>. For a root client span, there is no local parent span and therefore no parent _client_list holding a strong reference. Once the caller-side temporary shared_ptr<Span> goes out of scope, the span can be destroyed before Controller::SubmitSpan() submits it to rpcz.
To Reproduce
- Enable rpcz in a brpc client process.
- Send an outgoing RPC from the client without an existing local parent span.
- Check the client-side
/rpcz output.
- Observe that rpcz internal calls may be visible, but the application-level outgoing client RPC span is missing.
Expected behavior
Client-side root RPC spans should remain alive until the RPC finishes and Controller::SubmitSpan() has a chance to submit them to rpcz.
The outgoing client RPC should be visible in client-side /rpcz.
Versions
OS:
Compiler:
brpc:
protobuf:
Additional context/screenshots
Nested client spans created under a server span are less likely to hit this issue because the parent span owns child spans through _client_list.
A possible fix is to let Controller hold the current RPC span with std::shared_ptr<Span> until the RPC finishes, SubmitSpan() runs, or the Controller is reset. Child-to-parent references can remain weak, so this does not introduce a shared_ptr cycle.
Describe the bug
When rpcz is enabled in a brpc client process, root client-side RPC spans may not be recorded if the RPC is initiated without an existing local parent span.
The client process can successfully enable
/rpcz, and rpcz internal service calls may appear, but application-level client RPC spans are missing from the rpcz output.Root cause:
Controller::_spanis stored asstd::weak_ptr<Span>. For a root client span, there is no local parent span and therefore no parent_client_listholding a strong reference. Once the caller-side temporaryshared_ptr<Span>goes out of scope, the span can be destroyed beforeController::SubmitSpan()submits it to rpcz.To Reproduce
/rpczoutput.Expected behavior
Client-side root RPC spans should remain alive until the RPC finishes and
Controller::SubmitSpan()has a chance to submit them to rpcz.The outgoing client RPC should be visible in client-side
/rpcz.Versions
OS:
Compiler:
brpc:
protobuf:
Additional context/screenshots
Nested client spans created under a server span are less likely to hit this issue because the parent span owns child spans through
_client_list.A possible fix is to let
Controllerhold the current RPC span withstd::shared_ptr<Span>until the RPC finishes,SubmitSpan()runs, or the Controller is reset. Child-to-parent references can remain weak, so this does not introduce ashared_ptrcycle.