For debugging purposes I store exception's stack trace to log file in my ASP.NET application. But in most of cases it contains a looot of redundant information: stack trace of ASP.NET's core before my routines and System calls after.
Is there any way to trim this unrelevant, not in my assembly information from StackTrace object I create from Exception? I'm interested only in chunk of frames inside of whole trace.
Thank you.
Denis.
One way would be to create a StackTrace object, get the frames from it and loop through them, checking whether each frame was created for a method in one of your assemblies.
I don't think you really should do this though. You chould rather focus on getting less error messages in your logs than shortening them (which will likely make things more difficult to debug).
I ended up parsing ex.ToString() and removing unwanted entries with Regex. It's not a universal solution, you have to specify each excluded entry manually, but it helps reduce size of logs and improve log readability. It's also fairly maintainable. Something like this:
private static string TrimStackTrace(Exception ex)
{
var sb = new StringBuilder();
string[] lines = ex.ToString().Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
var excludeRegex = new Regex(#"^\s+at (Microsoft.AspNetCore|lambda_)");
foreach (string line in lines)
{
if (excludeRegex.IsMatch(line))
{
continue;
}
sb.AppendLine(line);
}
return sb.ToString();
}
You can of course make excluded entries part of your app config.
Related
I am working on an asp.net mvc-5 web application and i am using ap.net version 4.5.
Inside my web application I am executing some power-shell scripts to get some hardware info about some servers and VMs, and get back the results inside my code, as follows:
var shell = PowerShell.Create();
string PsCmd =
"add-pssnapin VMware.VimAutomation.Core; $vCenterServer = '"
+ vCenterName.Trim() + "';$vCenterAdmin = '" + vCenterUsername.Trim()
+ "' ;$vCenterPassword = '" + vCenterPassword + "';"
+ System.Environment.NewLine;
PsCmd += "$VIServer = Connect-VIServer -Server $vCenterServer -User $vCenterAdmin -Password $vCenterPassword;" + System.Environment.NewLine;
PsCmd += "Get-VMHost " + System.Environment.NewLine;
shell.Commands.AddScript(PsCmd);
dynamic results = shell.Invoke();
var temp_result = results[0].BaseObject == null ? results[0] : results[0].BaseObject;
var otherIdentityInfo = temp_result.ExtensionData.Hardware.SystemInfo.OtherIdentifyingInfo;
now currently when i run this inside my Visual Studio 2012 professional , i will get the following exception :-
System.StackOverflowException was unhandled
An unhandled exception of type 'System.StackOverflowException' occurred in VimService55.XmlSerializers.dll
on
var otherIdentityInfo = temp_result.ExtensionData.Hardware.SystemInfo.OtherIdentifyingInfo;
So can anyone adivce on this? I know that in general a "StackOverflowException" exception is related to the fact that too many data exists inside the stack, but in my case I do not have control over this data as I am scanning VM server information. So can anyone advice on this please?
EDIT
I am not sure what is really raising the error (the debugger OR the code)? because when i try calling this code on the hosted application inside IIS (not inside Visual Studio) I will get null value for the otherIdentityInfo variable, rather than getting an exception. However, when i debug the code inside Visual Studio using Autos i will get the exception, so as #JmaesP mentioned the exception is being raised by the debugger, but not sure how i can debug this value to see why i am getting null??
A stack overflow exception from an XML serializer might indicate an issue with one of you serializable types. If the type declaration by itself is somewhat recursice, the default XML serializer will end up in inifite recursion. Consider this example:
[Serializable()]
public class Foo : IEnumerable<Foo>
{
public Foo()
{
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
public IEnumerator<Foo> GetEnumerator()
{
throw new NotImplementedException();
}
public void Add(Foo item)
{
throw new NotImplementedException();
}
}
The default XML serializer first tries to figure out how to (de-)serialize an instance of Foo, then it tries to figure out how to (de-)serialize an IEnumerable<Foo>, and to do that it tries to figure out how to (de-)serialize a Foo — resulting in infinite recursion. Typically, a solution to this would to use a custom serializer as described here.
However, in your case the serializer is provided by the third-party component. The exception likely occurs during the serialization/deserialization that is happening when objects are passed from the PowerShell session to your process. So what you could to is to change the object that is returned from the PowerShell script. Instead of returning a VMHost object (requiring to serialize the entire object tree of the VMHost object), you could just return the SystemInfo or OtherIdentifyingInfo.
Large recursions can cause out-of-stack errors.
Your problem is likely that your program is attempting to consume an infinite amount /very large amount of stack.
Without seeing your stack trace, it's a bit difficult to provide a definitive answer, but I think sticking to the basics leads me to believe the source of your StackOverflow is the PsCmd += which continuously adding the data into the stack and results in StackOverflowException.
You can increase the stack size by using the below code:
Editbin.exe /Stack:14000000 "$(TargetDir)MyProject.exe"
Have you analyzed your code to find out that how deep your recursion goes on average? Does it always hit a StackOverflow? Try hardcoding a single entity and see the result.
Since 64 bit code can up more stack space than equivalent 32 bit code, large recursions can cause out-of-stack errors to occur earlier.
In that case, making the stack larger is not a good idea either. Instead we should find the deeply recursive algorithm and make it into an iterative one.
For Stack-Trace;
You can read up this property: Environment.StackTrace.
If the stacktrace exceded a specific threshold that you preset, you can return the function.
Note: From .Net 2.0 and above, you cannot get a StackOverflowException object using a try-catch block.
Let me know if at all it helps you.
I have a global error trap in the Application_Error method of Global.asax that writes any unhandled exception to a log file.
Is there anyway of reporting the variable names and their values as part of the exception report?
Unless you do something really tricky with Aspect-Oriented Programming, you pretty much need to make sure that you manually introduce any relevant information into the stack trace when exceptions are thrown. For example:
public void DoSomething(int number, string name)
{
try
{
...
}
catch (Exception e)
{
throw new Exception("Error occurred while doing something: " +
new {number, name}, e);
}
}
This way, the number and name will be included in the stack trace when this exception trickles up to the top level.
Edit
After reading David Stratton's answer, I felt the need to expand on this a little. I get the sense that even some very experienced C# programmers haven't learned some of the tricks that I've learned.
First of all, I wanted to point out that the exception-handling system in .NET was designed with the idea of an InnerException specifically for this purpose (providing additional information at various points of the stack trace), and it is not at all hacky to do. However, you should definitely provide the exception as the innerException constructor parameter, rather than appending e.ToString() to the new exception's message.
Secondly, based on various comments and answers I've read on StackOverflow, as well as my own experience, it's best to:
Avoid catching an exception if there's nothing specific you plan to do with it.
When you catch an exception, rethrow it unless you know why the exception was thrown and you're in a scope where you know how to gracefully retreat from what you were trying to do. Simply pretending nothing went wrong is asking for more trouble down the road.
When re-throwing exceptions, either just throw; to preserve the original exception's stack trace, or include the original exception as a new exception's InnerException.
Consistently log exceptions that don't get re-thrown. This will generally only happen at the UI level, so you can tell the user something unexpected happened rather than allowing the program to crash.
Finally, I wanted to mention that the anonymous type declaration syntax is ideal for this kind of thing because it is very concise and it will automatically produce a string that uses the given variable names and values. For example, new {number, name}.ToString() might produce "{ number = 1, name = Test }".
We do this in some cases, but in a roundabout way. We use a try/catch at the granular level and if we want to pass the exception up to the global error handler, we build the error message. For example:
int someCounterValue = 0;
string someStringValue = "Some string we want to track to send to the global error handler."
private void SomeFunction()
{
try
{
someStringValue = "in the try block";
someCounterValue = 1.5 // should thrown an exception
}
catch(Exception ex)
{
throw new Exception("Error in SomeFunction. someStringValue = " + someStringValue + "; someCounterValue = " + someCounterValue.ToString() + "\r\nException details: " + ex.ToString());
}
}
It's a lot of work so we really don't do this very often. Usually our error handling is better handled at the local level but in those very rate cases where you want to pass it off to the global error handler, this is about the only way we've found, since the variables would be out of scope otherwise, and therefore, inaccessible.
An easier/less hack-like option would be to set up a static class in your web app called ErrorLogger or something similar, and just handle the exceptions better locally and pass them up to the global handler ONLY when you can't do it locally.
In my opinion (and in the way we do it here by policy) a global error handler should be used to catch exceptions that you forgot to handler better at a more granular level. It should NOT just be an easy way to be lazy about proper exception handling.
Also it feels like a hack to me, so if anyone has a better option I'd like to know it, too.
How to identify the line nr. where the exception has occured and show a piece of code around the exception?
I would like to implement a custom exception handler page which would display the stack trace, and I'm looking for the easiest way to accomplish the above. While most of the information is available through the Exception object, the source code information is not available there.
You need to use the StackTrace class.
For example:
var st = new StackTrace(exception, true);
var sourceFrame = Enumerable.Range(0, st.FrameCount).FirstOrDefault(i => st.GetFrame(i).GetFileLineNumber() > 0);
This code will find the first frame which has line number information available, or null, if none of the frames have line numbers.
You can then call the methods of the StackFrame object to get more information. Note that source information is usually only available in debug builds.
I can't get NVelocity to initialize. I'm not trying to do anything complicated, so it's just fine if it initializes at the defaults, but it won't even do that.
This:
VelocityEngine velocity = new VelocityEngine();
ExtendedProperties props = new ExtendedProperties();
velocity.Init(props);
Results in: "It appears that no class was specified as the ResourceManager..."
So does this:
VelocityEngine velocity = new VelocityEngine();
velocity.Init();
I can find precious little documentation on what the properties should be, nor how to get it to initialize with the simple defaults. Can anyone point to a resource?
A lot of pages point back to this page:
http://www.castleproject.org/others/nvelocity/usingit.html
But this page skips over the (seemingly) most important point -- how to set the properties and what to set them to.
I just want to load a simple template from a file.
Here's what I found out --
I was using the original NVelocity library, which hasn't had an update since 2003. I think it's a dead project.
I switched to the Castle Project version, and it's much easier -- in fact, it runs much like the examples on the page I linked to. It seems to set intelligent defaults for properties. I can initialize it without any properties set, but the template directory defaults to ".", so I generally set that one (do it before running "init").
To get the correct DLL, you need to download the latest NVelocity release (as of this writing it's 1.1).
Castle Project Download Page
You need to include the following files in your assembly, and make sure that their type is set to "Resource"
src\Runtime\Defaults\directive.properties
src\Runtime\Defaults\nvelocity.properties
These will then be found by ResourceLocator
src\Runtime\Resource\Loader\ResourceLocator.cs
If you get an exception on GetManifestResourceNames() as I did when trying to run Dvsl, then try modifying the ResourceLocator constructor to catch and ignore the error since the required files are in your local assembly (if you included them above) and the exception is only thrown by external assemblies (no idea why).
foreach(Assembly a in assemblies) {
String prefix = a.FullName.Substring(0,a.FullName.IndexOf(",")).ToLower();
try
{
String[] names = a.GetManifestResourceNames();
foreach (String s in names)
{
if (s.ToLower().Equals(fn) || s.ToLower().Equals(prefix + "." + fn))
{
this.filename = s;
assembly = a;
isResource = true;
}
}
} catch {
}
}
I'm using Office Automation in .NET. It is leaving behind the excel.exe program. I know the fix - it is all about explicitely defining the variables. Once defined, I can properly de-allocate the ram and the GC will clean them up.
The problem is, I have literally thousands of lines of code to go through. So I'm wondering: Is there some sort of a utility in .net (or 3rd party) that is capable of showing me a list of variables for which I have ram allocated still? If so, I would be able to target those items and specificially de-allocate them.
Thanks
Ryan
http://www.automatedqa.com/techpapers/net_allocation_profiler.asp
Just to be clear, you need to explicitly Quit Excel after you are done using it through automation. If you don't an instance will keep running, even if your variables go out of scope and garbage collection runs. I believe the command it Quit():
Excel.ApplicationClass excel = new Excel.ApplicationClass();
//do some work with Excel
excel.Quit();
I would recommend you do this with a try/catch/finally
Excel.ApplicationClass excel = null;
try
{
excel = new Excel.ApplicationClass();
//do some Excel work
}
catch(Exception ex)
{
//log exception
throw;
}
finally
{
if(excel != null)
excel.Quit();
}