opencensus-cpp
opencensus-cpp copied to clipboard
any plan to support in multi thread?
I was also wondering this, as in our case we use TBB (actually ConCRT) spawning parallel_for and std::thread, but then tried to pass just the context - e.g. span.context() and it worked. Because after all the context is simply three "integer" values (of different sizes): thrace id, span id and options
@malkia you can see this link context. Java and go,c# have official implement,but cpp have none.
I ended up with hacky, but workable (for my case) way: a thread_local s_activeSpanContext; that gets saved (in RAII object), then restored back. I also ave another special one s_rootSpanContext - created at the begining, which gets used if the !s_activeSpanContext.IsValid() (just to handle edge cases). It's not perfect, and I know I should be handing off actual context, but at the same time this means changing a lot of the code - basically adding an additional argument to a lot of places (still the proper thing to do, but need to evaluate a bit more and then do it).
I do the same work
Hi all,
@g-easy will start working on adding a Context support soon. I will keep this issue updated.
Hava any progress report? @bogdandrutu
Hi billowqiu, @g-easy has a prototype we are trying to polish the public API for the moment. This week the PR should land.
@bogdandrutu if i have multiple threads to handle incoming requests May be use the "std::function<void()> Wrap(std::function<void()> fn) const;" to warp a task or new thread func can do the work to propagation the context. But i want to know there are any best-practices?
@g-easy please follow on this
@billowqiu Best practices:
- Always have the correct Context installed as the "current" context.
- To set a current Span, use a WithSpan object.
- Treat WithSpan as RAII - always stack-allocate it.
- For callbacks, as you said, Wrap the callback while the correct context is installed.
e.g.
{
WithSpan ws(span);
executor.add(Context::Current()::Wrap(callback_fn));
}
Does this help?
thanks
发自我的 iPhone
在 2018年10月12日,上午11:47,easy [email protected] 写道:
@billowqiu Best practices:
Always have the correct Context installed. To set a current Span, use a WithSpan object. Treat WithSpan as RAII - always stack-allocate it. For callbacks, as you said, Wrap the callback while the correct context is installed. e.g.
{ WithSpan ws(span); executor.add(Context::Current()::Wrap(callback_fn)); } Does this help?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
I'm trying to document this in #224
I have a scene,like the diagram:
All request are async,server need wait recv rsp-3 then send req-4.
I must tracing all span as a one tracer:1->2->3->4->5->6,now i via hold client-span's parent span before request,and restore the span as Context's current span when response,to accomplish this task.
Undoubtedly, there are other ways of accomplishing the same thing (and maybe some of them are even easier). @g-easy I want your advice.
To do this in an async way, I would suggest the server component does something like this:
void Server1(RequestFromClient req) {
// Server receives trace context and tagging context from client.
SpanContext parent_ctx = req.GetContext();
TagMap tags = reg.GetTags();
// Create the server-side span.
Span span = Span::StartSpanWithRemoteParent("ServerSpan", parent_ctx);
// Create a Context for this operation.
WithSpan ws(span);
WithTagMap wt(tags);
// Send request to s1 with the current Context installed.
// When that request completes, it will run a callback.
DownstreamRequest req1(...);
req1.Run(/* callback = */ Context::Current()::Wrap(Server2));
}
void Server2(ReplyFromDownstream reply1) {
// The current Context is correct.
Process(reply1);
// Send request to s2 with the current Context installed.
// When that request completes, it will run a callback.
DownstreamRequest req2(...);
req2.Run(/* callback = */ Context::Current()::Wrap(Server3));
}
void Server3(ReplyFromDownstream reply2) {
// The current Context is correct.
Process(reply2);
ReplyToClient();
// Operation is complete, remember to end the span.
GetCurrentSpan().End();
}
Where DownstreamRequest::Run()
sends the currently installed Context to the downstream service.
Does this make sense? Does it look okay to you? Do you think there is a better and/or simpler approach?
My plan for the gRPC integration is that the gRPC plugin will take care of:
- Decoding the incoming trace and tagging contexts. (trace is already implemented)
- Creating a server-side Span. (this is already implemented)
- Installing the Span and tags in Context::Current().
- Child RPCs take the current Context and propagate it on the wire.
- End the server-side Span after sending the reply. (this is already implemented)
To do this in an async way, I would suggest the server component does something like this:
void Server1(RequestFromClient req) { // Server receives trace context and tagging context from client. SpanContext parent_ctx = req.GetContext(); TagMap tags = reg.GetTags(); // Create the server-side span. Span span = Span::StartSpanWithRemoteParent("ServerSpan", parent_ctx); // Create a Context for this operation. WithSpan ws(span); WithTagMap wt(tags); // Send request to s1 with the current Context installed. // When that request completes, it will run a callback. DownstreamRequest req1(...); req1.Run(/* callback = */ Context::Current()::Wrap(Server2)); } void Server2(ReplyFromDownstream reply1) { // The current Context is correct. Process(reply1); // Send request to s2 with the current Context installed. // When that request completes, it will run a callback. DownstreamRequest req2(...); req2.Run(/* callback = */ Context::Current()::Wrap(Server3)); } void Server3(ReplyFromDownstream reply2) { // The current Context is correct. Process(reply2); ReplyToClient(); // Operation is complete, remember to end the span. GetCurrentSpan().End(); }
Where
DownstreamRequest::Run()
sends the currently installed Context to the downstream service.Does this make sense? Does it look okay to you? Do you think there is a better and/or simpler approach?
This is helpful.
gRPC integration
look forward to see this integration 👍