Skip to content

Instantly share code, notes, and snippets.

@thomaslevesque
Created August 16, 2013 13:42
Show Gist options
  • Save thomaslevesque/6250080 to your computer and use it in GitHub Desktop.
Save thomaslevesque/6250080 to your computer and use it in GitHub Desktop.
Extension method to add "logical" stack trace to async methods, with usage example. Copy/paste in Linqpad and add the following namespaces: - System.Runtime.CompilerServices - System.Threading.Tasks
async void Main()
{
try
{
await FooAsync().AsyncTrace();
}
catch(Exception ex)
{
ex.FullTrace().Dump();
}
}
async Task FooAsync()
{
await Console.Out.WriteLineAsync("Entering FooAsync");
await BarAsync().AsyncTrace();
await Console.Out.WriteLineAsync("Leaving FooAsync");
}
async Task BarAsync()
{
await Console.Out.WriteLineAsync("Entering BarAsync");
string s = await BazAsync().AsyncTrace();
Console.WriteLine(s);
await Console.Out.WriteLineAsync("Leaving BarAsync");
}
async Task<string> BazAsync()
{
await Console.Out.WriteLineAsync("Entering BazAsync");
throw new Exception("Oops");
return "hello world";
await Console.Out.WriteLineAsync("Leaving BazAsync");
}
static class AsyncExceptionExtensions
{
public static async Task AsyncTrace(
this Task task,
[CallerMemberName] string callerMemberName = null,
[CallerFilePath] string callerFilePath = null,
[CallerLineNumber] int callerLineNumber = 0)
{
try
{
await task;
}
catch (Exception ex)
{
AddAsyncStackTrace(ex, callerMemberName, callerFilePath, callerLineNumber);
throw;
}
}
public static async Task<T> AsyncTrace<T>(
this Task<T> task,
[CallerMemberName] string callerMemberName = null,
[CallerFilePath] string callerFilePath = null,
[CallerLineNumber] int callerLineNumber = 0)
{
try
{
return await task;
}
catch (Exception ex)
{
AddAsyncStackTrace(ex, callerMemberName, callerFilePath, callerLineNumber);
throw;
}
}
private static void AddAsyncStackTrace(Exception ex, string callerMemberName, string callerFilePath, int callerLineNumber = 0)
{
var trace = ex.Data["_AsyncStackTrace"] as IList<string>;
if (trace == null)
trace = new List<string>();
trace.Add(string.Format("@{0}, in '{1}', line {2}", callerMemberName, callerFilePath, callerLineNumber));
ex.Data["_AsyncStackTrace"] = trace;
}
public static string AsyncTrace(this Exception ex)
{
var trace = ex.Data["_AsyncStackTrace"] as IList<string>;
if (trace == null)
return string.Empty;
return string.Join("\n", trace);
}
public static string FullTrace(this Exception ex)
{
var trace = ex.Data["_AsyncStackTrace"] as IList<string>;
if (trace == null)
return string.Empty;
return string.Format("{0}\n--- Async stack trace:\n\t", ex)
+ string.Join("\n\t", trace);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment