I'm trying to find a way to keep a track on async tasks execution flow in a way that it would be easy to understand regarding task, what was the original flow that initiated it. I need it mostly for logging, debugging and preserving a sort of stack trace for a specific execution flow.
For example: If I have a server with many clients from multiple IPs and the server needs to execute a work flow for each client that involves many async actions thus involves many different tasks per execution flow; logging such a flow is difficult especially when using async/await
mechanism.
I haven't figured out a way to wrap the tasks in a way that for each task that is executed I would know the initial flow description when logging. For example if I start a new flow of tasks for an action with description - "Taking care of 10.0.3.4 client" I want to be able to add this description for each log item coming out from this flow in any task that created from it.
When using threads only, its easy because you have thread static variables. with tasks its impossible...
I even tried to create my own task scheduler that will wrap out any task that uses it (even when using async/await
methods) but got into a dead end because the task scheduler base sometimes uses new threads (even though there wasn't any implicit request to use a new thread)- the method TryExecuteTaskInline
can sometimes run in a new thread.
Any idea or suggestion of how can I achieve that?
The tracking number is typically printed on the shipping label as a bar code that can be scanned by anyone with a bar code reader or smartphone. In the United States, some of the carriers using tracking numbers include UPS, FedEx, and the United States Postal Service.
What is C note number in courier? The "C" in C-note refers to the Roman numeral for 100, which was printed on $100 bills, and it can also refer to a century.
A China Post EMS tracking number (shipment ID) has 13 characters. It starts with the letter “E” for Express Mail and ends with “CN” or “CS” with 9 digits in between. For epacket/EUB, the tracking number starts with “LK”. For China International Express, it begins with “CT”.)
One of the ways is through the India Post SMS service. All you have to do for this is type send the typically 13-digit India Post tracking number via SMS on 166 or 51969. Alternatively, if you are online you can track your India Post delivery through the Ship24 website.
You can use Trace.CorrelationManager.ActivityId
to store a logical operation id, or even better store an ImmutableStack
of logical operation ids. It is stored in the CallContext
and is copied through the async
method calls:
public static class LogicalFlow
{
private static readonly string _name = typeof (LogicalFlow).Name;
private static ImmutableStack<Guid> LogicalStack
{
get
{
return CallContext.LogicalGetData(_name) as ImmutableStack<Guid> ?? ImmutableStack.Create<Guid>();
}
set
{
CallContext.LogicalSetData(_name, value);
}
}
public static Guid CurrentId
{
get
{
var logicalStack = LogicalStack;
return logicalStack.IsEmpty ? Guid.Empty : logicalStack.Peek();
}
}
}
You can use it as an IDisposable
so you can utilize a using
scope to make sure there's a Pop
to every Push
:
private static readonly Popper _popper = new Popper();
public static IDisposable StartScope()
{
LogicalStack = LogicalStack.Push(Guid.NewGuid());
return _popper;
}
private sealed class Popper : IDisposable
{
public void Dispose()
{
LogicalStack = LogicalStack.Pop();
}
}
Usage:
using (LogicalFlow.StartScope())
{
Console.WriteLine(LogicalFlow.CurrentId);
await DoSomethingAsync();
Console.WriteLine(LogicalFlow.CurrentId);
}
This answer previously relied on Trace.CorrelationManager.LogicalOperationStack
but Is LogicalOperationStack
incompatible with async in .Net 4.5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With