14

C# stack traces take the following form:

   at Foo.Core.Test.FinalMethod(Doh doh) in C:\Projects\src\Core.Tests\Test.cs:line 21
   at Foo.Core.Test.AnotherMethod(Bar bar)
   at Foo.Core.Test.AMethod() in C:\Projects\src\Core.Tests\Test.cs:line 6
   at Foo.Core.Test.<>c__DisplayClass7.<SomeAnonDelegate>b__6(Object _) in C:\Projects\src\Core.Tests\Test.cs:line 35

How can I retrieve namespace, class, method, file and line number from each line?

  • Are there any existing classes to do this?
  • If not what would be the the best approach?
  • Regex? How would I greedily match the namespace but leave the class and method?
  • Custom parser?

Would appreciate some ideas and input.

chillitom
  • 24,888
  • 17
  • 83
  • 118
  • Just out of curiosity, to you intend to use this in a production environment? As far as i remember, the stack-trace isn't included in release mode. See http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx which states that all these information are obtained from the debug symbols, which aren't included in the release builder per default. – J. Tihon Feb 28 '11 at 22:15
  • @J. Tihon, good point, however we include symbol information in our Release builds – chillitom Feb 28 '11 at 22:19
  • Well, I just didn't want you to go through all the trouble with regex and all, when you can't really use it at the end. – J. Tihon Feb 28 '11 at 22:31
  • @J. Tihon: Stack traces do emanate from release builds even without symbols, but they are missing line numbers and filenames. – adrianbanks Feb 28 '11 at 22:37
  • 1
    There is very little reason not to ship your symbols when deploying. PDBs do not cause notable performance degradation (it is a common misconception that they are related to debug builds). – TheXenocide Sep 14 '12 at 23:27
  • can you put full code for parsing StackTrace string value from an exception? – Kiquenet Oct 13 '15 at 09:39

3 Answers3

16

If you're getting this from a StackTrace, then you can loop through the StackFrames via GetFrame and call GetMethod, GetFileName, and GetFileLineNumber. Namespace and class can be retrieved from the method.

EDIT
In response to the first comment (unfortunately we get the traces from Exception.StackTrace), you can call the StackTrace(Exception) constructor.

EDIT
I should've linked to this constructor instead -- StackTrace(Exception,bool).

Austin Salonen
  • 49,173
  • 15
  • 109
  • 139
  • 3
    `Exception.StackTrace` is a `string`, which **cannot be passed into the constructor** of `StackTrace` (it doesn't take a `string`). – adrianbanks Feb 28 '11 at 22:41
  • @adrianbanks: That is indeed true and while OP said that he got it from `Exception.StackTrace`, there was nothing stating he doesn't have access to the Exception object (+1 for your comment BTW). – Austin Salonen Feb 28 '11 at 22:46
  • Fortunately I do have access to Exception so this is a good solution. Unfortunately it won't provide file, line# and column# but I think I can probably live without that. – chillitom Feb 28 '11 at 22:48
  • 1
    I take that back, there is an overload which will provide file info also. – chillitom Feb 28 '11 at 22:55
  • This doesn't work in PCL. One also has to think about localization if parsing the stack trace. – Blake Niemyjski Apr 24 '14 at 11:47
4

I read the Austin Salonen's answer and it's obvious better, but I've already started with regex. so I'll write it anyway.

Regex r = new Regex(@"at (?<namespace>.*)\.(?<class>.*)\.(?<method>.*(.*)) in (?<file>.*):line (?<line>\d*)");
var result = r.Match(@"at Foo.Core.Test.FinalMethod(Doh doh) in C:\Projects\src\Core.Tests\Test.cs:line 21");
if (result.Success)
{
    string _namespace = result.Groups["namespace"].Value.ToString();
    string _class = result.Groups["class"].Value.ToString();
    string _method = result.Groups["method"].Value.ToString();
    string _file = result.Groups["file"].Value.ToString();
    string _line = result.Groups["line"].Value.ToString();
    Console.WriteLine("namespace: " + _namespace);
    Console.WriteLine("class: " + _class);
    Console.WriteLine("method: " + _method);
    Console.WriteLine("file: " + _file);
    Console.WriteLine("line: " + _line);
}
Homam
  • 23,263
  • 32
  • 111
  • 187
  • Looks good, I'm glad you posted anyway as you reminded me that C# allows named matches. Out of interest will the namespace match cope with nested namespaces e.g. Ns1.Ns2.Ns3.Class.Method? – chillitom Feb 28 '11 at 22:45
  • Yes it will, try it. but seems I have a problem when the string doesn't contains all the parts, I mean `in` and the path. – Homam Feb 28 '11 at 22:47
  • 1
    What if you run this program in Germany with localized .NET runtime? – Lasse V. Karlsen Feb 28 '11 at 23:02
  • @Lasse V. Karlsen: You're right. But I've answered to a question with an example in English and tagged with `regex`. I know that my answer isn't good enough but I shared it anyway. – Homam Feb 28 '11 at 23:07
  • 1
    I found this answer helpful for a tool I'm working on using logged exceptions. I've updated the regex for proper optional file and line support. Also, @LasseV.Karlsen Regex is rarely appropriate for localized strings; it's outside the scope of this problem. – TheXenocide Sep 14 '12 at 23:25
  • This regex only works if your stack traces are localized in english – Blake Niemyjski Apr 24 '14 at 11:48
2

StackTraceParser can parse a stack trace text output (e.g. typically returned by Environment.StackTrace or Exception.StackTrace) back into a sequence of stack trace frames, including the following components:

Type
Method
Parameter types and names
File and line information, if present

It is available as a NuGet source package that directly embeds into a C# project.

However it requires a few functions to specify and it's usage is not immediately obvious.

public static IEnumerable<TFrame> Parse<TToken, TMethod, TParameters, TParameter, TSourceLocation, TFrame>(
    string text,
    Func<int, int, string, TToken> tokenSelector,
    Func<TToken, TToken, TMethod> methodSelector,
    Func<TToken, TToken, TParameter> parameterSelector,
    Func<TToken, IEnumerable<TParameter>, TParameters> parametersSelector,
    Func<TToken, TToken, TSourceLocation> sourceLocationSelector,
    Func<TToken, TMethod, TParameters, TSourceLocation, TFrame> selector)

See examples in https://github.com/atifaziz/StackTraceParser and https://bitbucket.org/project-elmah/main/src/2a6b0b5916a6b4913ca5af4c22c4e4fc69f1260d/src/Elmah.AspNet/ErrorDetailPage.cs?at=default&fileviewer=file-view-default

Michael Freidgeim
  • 26,542
  • 16
  • 152
  • 170