Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slimming Down Exception/Environment.StackTrace Meaningfully

I am analyzing errors in a legacy application as I clean it up and improve it. I have some stack traces being logged to the database, but there is a limit (VARCHAR2(1000)) to how much it is storing, and errors are occurring deep within System.Data...

   at System.Data.OracleClient.OracleConnection.CheckError(OciErrorHandle errorHandle, Int32 rc)
   at System.Data.OracleClient.OracleCommand.Execute(OciStatementHandle statementHandle, CommandBehavior behavior, Boolean needRowid, OciRowidDescriptor& rowidDescriptor, ArrayList& resultParameterOrdinals)
   at System.Data.OracleClient.OracleCommand.Execute(OciStatementHandle statementHandle, CommandBehavior behavior, ArrayList& resultParameterOrdinals)
   at System.Data.OracleClient.OracleCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.OracleClient.OracleCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
   at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
   at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet)

I don't care about all this stuff - I just need to find which C# code and which proc is generating the errors. So I can figure out the root cause, refactor the code to quality and improve each module as I hit the lowest-hanging most-error-producing code.

Before I go off and write something, does someone have something which will limit the stack trace to certain assemblies so I can get to the root cause? Or a stack trace parser or something off the shelf which I can use to strip out the stuff I'm not interested in before logging the error?

like image 795
Cade Roux Avatar asked Jan 17 '26 01:01

Cade Roux


2 Answers

Code to reduce .Net exception

You're in luck - somebody who's done that read your post! I'd gather I've saved my eyes from from reading at least a Steven King novel's worth of fluff by reformatting my errors into something like this:

(<pre> didn't honor my tabstops so it looks better in real life)

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
FUNCTION    FILE    LINE
CoCreateInstance    (no .PDB)
CreateWithoutLicense    (no .PDB)
CreateWithLicense   (no .PDB)
CreateInstanceCore  (no .PDB)
CreateInstance  (no .PDB)
GetOcxCreate    (no .PDB)
TransitionUpTo  (no .PDB)
CreateHandle    (no .PDB)
CreateControl   (no .PDB)
CreateControl   (no .PDB)
EndInit (no .PDB)
InitializeComponent frmGetSig.Designer.vb   187
ctor    frmGetSig.vb    264
btnSign_Click   ucSignCapture_v2.vb 306

Using this code:

Public Shared Function ReduceError(ByVal stExceptionToString As String) As String
    Try
        ''// split into message and stack trace items
        Dim stMainSplit() As String = Split(stExceptionToString, vbCrLf & "   at ")
        If UBound(stMainSplit) = 0 Then
            Return stExceptionToString
        End If
        ''// add the message
        Dim stResults As String = stMainSplit(0) & vbCrLf
        Dim bLastWasInner As Boolean
        ''// Headings, if there is a stack trace
        If UBound(stMainSplit) > 0 Then
            stResults &= "FUNCTION" & vbTab & "FILE" & vbTab & "LINE" & vbCrLf
        End If
        ''// reduce the stack trace
        For i As Integer = 1 To UBound(stMainSplit)
            Dim st As String = stMainSplit(i)
            ''// skip the line following inner exception in stack trace
            If Not bLastWasInner Then
                ''// split the sub from line # info
                Dim stln() As String = Split(st, ")")
                If UBound(stln) = 1 Then
                    ''// first put the sub on there
                    Dim stsub As String = Mid(stln(0), 1, InStrRev(stln(0), "(") - 1)
                    If InStr(stsub, ".") <> 0 Then
                        stsub = Mid(stsub, InStrRev(stsub, ".") + 1)
                    End If
                    stResults &= stsub & vbTab
                    ''// Now if there is file/line # info, add that. 
                    Dim stFile As String = "(no .PDB)"
                    If 0 <> InStr(stln(1), "\") Then '' " //good grief SOF learn vb ;-)
                        stFile = Replace(Mid(stln(1), InStrRev(stln(1), "\") + 1), ":line ", vbTab) '' "
                        ''// take off CR and 'inner exception..." text
                        If InStr(stFile, vbCrLf) > 1 Then
                            stFile = Mid(stFile, 1, InStr(stFile, vbCrLf) - 1)
                        End If
                    End If
                    stResults &= stFile & vbCrLf
                Else
                    stResults &= "Line split by ) has no (" & vbTab & vbCrLf
                End If
            End If
            If 0 <> InStr(st, "End of inner exception stack trace") Then
                bLastWasInner = True
            Else
                bLastWasInner = False
            End If
        Next
        Return stResults
    Catch ex As Exception 
        ''// might want to return orig error here as well..
        Return "Error summarizing routine as error'd: " & ex.ToString
    End Try
End Function

It puts in tabs which I use in a text box, easy enough to change if you want; if you don't care about the system.data lines you could always exclude them. Written for .net 1.1, should convert to c# well.

like image 191
FastAl Avatar answered Jan 19 '26 17:01

FastAl


The simplest way would be to increase the limit.

Runner-up simplest way is to modify the logging so it takes the last 1000 characters (if it's longer) of the stack trace rather then inserting the whole thing. Any other solution would also have to modify the logging or be a MitM to intercept and alter the information before letting it continue on to the logger.

You can't change how .NET produces stack trace text (such as ignoring certain assemblies), so it all comes down to string manipulation before logging.

like image 36
Joel B Fant Avatar answered Jan 19 '26 17:01

Joel B Fant



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!