Closed Chakrygin closed 6 years ago
Hey, thanks for opening the issue. If I'm reading this right, your use case is to start a span in one async method, then finish it in a different async method? I think you'd need to manually pass the span context around in that case rather than using the scope manager. Alternately, the following pseudo-code should work I'd imagine -
async Task Prepare() {
using (prepareScope = tracer.BuildSpan("prepareAndExecute"))
{
DoPrepare()
await Execute()
}
}
async Task Execute() {
using (executeScope = tracer.BuildSpan("execute"))
{
DoExecute()
}
}
using (scope = tracer.BuildSpan("root"))
{
await PrepareAndExecute();
}
Unfortunately, we use DiagnosticSource similar to this and cannot explicitly create a root span: https://github.com/opentracing-contrib/csharp-netcore/blob/master/src/OpenTracing.Contrib.NetCore/EntityFrameworkCore/EntityFrameworkCoreDiagnostics.cs#L32
We tried to make spans similar to this:
Start "Query" span
Start "Open Connection" span
...
Finish "Open Connection" span
Start "Execute Command" span
...
Finish "Execute Command" span
Start "Execute Command" span
...
Finish "Execute Command" span
Finish "Query" span
The last thing you posted should work, but it's hard to say without real code. There's a couple of options as I see it.
The default AsyncLocalScopeManager
is going to use AsyncLocal Thread Storage to automatically set the scope on each thread (thus each async method will get its own scope and span, that's why your example fails). You could implement a different scope manager (using the IScopeManager
interface) that would allow you more control over the active scope at any given time and pass that scope manager in to your tracer.
Rather than using scopes, use manual span passing (this is how things work in Golang for example) to your child functions so that you can be more confident about when they're being executed.
Is that helpful?
Thank you, manual span passing does not suit us. Maybe, we will try to use own IScopeManager.
Hi!
We have encountered the following OpenTracing usage scenario (pseudo code):
I expected that after performing the
await PrepareAsync
method, thePrepare + Execute
span would be active as it was not finished.But the active span is
Root
Apparently this is due to the classes AsyncLocalScopeManager and AsyncLocalScope.
This test (for class AsyncLocalScopeManagerTests) shows the problem:
I tried to modify the class AsyncLocalScopeManager and change
AsyncLocal<IScope>
toAsyncLocal<Stack<IScope>>
with Push, Pop and Peak calls, but it breaks the tests MultipleCallbacksTest and NestedCallbacksTest in OpenTracing.Examples project.Tell me, please, is it possible to implement such a scenario (and is it possible)?