Neir0
Neir0

Reputation: 13377

Get stacktrace inside c# method

I want to implement universal logger which help me to see call stack of the methods.

I know there are some methods from System.Diagnostic but they were introduced in .net 4.0 and I'm afraid it will not work on xamarin or .net core or something like that. So I want to have more universal solution.

Another problem is async\await which introduce some mess.

I through about passing additional parameter in each method which store some context and help me to determinate call stack, but this solution is a bit complex.

Also I can read thread stack memory using unsafe code and check call stack by myself but it is not reliable.

Are there any other solution ?

Upvotes: 7

Views: 5492

Answers (1)

Manfred Radlwimmer
Manfred Radlwimmer

Reputation: 13394

You could just use Environment.StackTrace. That has been part of the Framework since the very beginning.

Environment.StackTrace will return the complete stacktrace (including the call to Environment.StackTrace itself) as a line separated string.

Something like this:

at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at WpfApplication2.MainWindow.GetStack(Int32 removeLines)
at WpfApplication2.MainWindow.Button_Click(Object sender, RoutedEventArgs e)
...
at System.Threading.ThreadHelper.ThreadStart()

All you need to do is split/parse/format it, whatever you want to do with it.

Since you'll be using this from within your own classes, remember to remove the newest X lines.

This code should work everywhere since it's deliberately low-level.

private static string[] GetStack(int removeLines)
{
    string[] stack = Environment.StackTrace.Split(
        new string[] {Environment.NewLine},
        StringSplitOptions.RemoveEmptyEntries);

    if(stack.Length <= removeLines)
        return new string[0];

    string[] actualResult = new string[stack.Length - removeLines];
    for (int i = removeLines; i < stack.Length; i++)
        // Remove 6 characters (e.g. "  at ") from the beginning of the line
        // This might be different for other languages and platforms
        actualResult[i - removeLines] = stack[i].Substring(6);

    return actualResult;
}

Upvotes: 11

Related Questions