Trace.CorrelationManager.LogicalOperationStack
enables having nested logical operation identifiers where the most common case is logging (NDC). Should it still work
Yes, LogicalOperationStack
should work with async-await
and it is a bug that it doesn't.
I've contacted the relevant developer at Microsoft and his response was this:
"I wasn't aware of this, but it does seem broken. The copy-on-write logic is supposed to behave exactly as if we'd really created a copy of the
ExecutionContext
on entry into the method. However, copying theExecutionContext
would have created a deep copy of theCorrelationManager
context, as it's special-cased inCallContext.Clone()
. We don't take that into account in the copy-on-write logic."
Moreover, he recommended using the new System.Threading.AsyncLocal
So, I went ahead and implemented LogicalFlow
on top of an AsyncLocal
instead of the LogicalOperationStack
using VS2015 RC and .Net 4.6:
public static class LogicalFlow
{
private static AsyncLocal _asyncLogicalOperationStack = new AsyncLocal();
private static Stack AsyncLogicalOperationStack
{
get
{
if (_asyncLogicalOperationStack.Value == null)
{
_asyncLogicalOperationStack.Value = new Stack();
}
return _asyncLogicalOperationStack.Value;
}
}
public static Guid CurrentOperationId =>
AsyncLogicalOperationStack.Count > 0
? (Guid)AsyncLogicalOperationStack.Peek()
: Guid.Empty;
public static IDisposable StartScope()
{
AsyncLogicalOperationStack.Push(Guid.NewGuid());
return new Stopper();
}
private static void StopScope() =>
AsyncLogicalOperationStack.Pop();
}
And the output for the same test is indeed as it should be:
00000000-0000-0000-0000-000000000000
ae90c3e3-c801-4bc8-bc34-9bccfc2b692a
ae90c3e3-c801-4bc8-bc34-9bccfc2b692a
ae90c3e3-c801-4bc8-bc34-9bccfc2b692a
00000000-0000-0000-0000-000000000000