我通过为System.Windows.Forms.Application.ThreadException
. 我对我的日志记录的可靠性相当有信心,但这让我想知道是什么原因造成的。此外,当服务器速度如此之慢导致超时时,有多少Exceptions
人可以登录到服务器上。
基本上,有几个实例是我们的 SQL 服务器在一天中进行导入过程,而用户收到SqlExceptions
“Exception.Message
超时已过期。在操作完成之前超时时间已过或服务器没有响应”。现在,在此期间记录的大多数异常都正常间隔,但在 3 个不同的日子里,一个客户SqlException
在几分钟内记录了数千个异常。
所以我问:
- 日志记录代码是否是生成这么多异常记录的罪魁祸首
- 如果
System.Data.SqlClient
幕后有任何东西可以产生这么多,以及是否有任何配置可以防止这种情况发生。 - 如果事件处理中有任何东西可能导致事件被重发这么多次。
日志记录函数的调用是一条直线,这让我相信它实际上捕获了数千个异常,尽管我无法理解会生成多少异常。
但是,记录器中有一个后备循环,我想知道这是否是原因。虽然在我的测试中,在异常处理程序中未捕获的异常会导致程序崩溃,所以我在异常处理期间看不到异常,然后自己处理和记录。此外,21.5k 总堆栈跟踪中没有一个表明处理程序中发生了异常。
所以这里是记录器本身的代码:(注意tries
和相关的逻辑是一个新的添加,以防止潜在的无限循环)
''' <summary>
''' Tries to log an Exception to the database.
''' </summary>
''' <param name="out">The results of Exception handling</param>
''' <param name="ex">The Exception to log.</param>
''' <param name="customMessage">A custom message to append to the Exception's message when logging to DB.</param>
Private Shared Sub LogException(ByVal out As ExceptionLogOutcome, ByVal ex As Exception, Optional ByVal customMessage As String = "", Optional ByVal priority As ExceptionDE.Priority = ExceptionDE.Priority.Medium)
If ex IsNot Nothing Then
out.ExceptionDataEntity = New DataEntity.ExceptionDE(ex, priority, CurrentBatchAuditDate, CurrentMachineID, CurrentBatchID, CurrentDocNum, CurrentTransactionID, CurrentUser)
If customMessage.Length > 0 Then
out.ExceptionDataEntity.Message &= " NOTE: " & customMessage
End If
Dim retry As Boolean = False
Dim tries As Integer = 0
Do
Try
DataAccess.LoggerDAO.CreateExceptionLog(out.ExceptionDataEntity)
Catch exc As SqlClient.SqlException
retry = MsgBox(String.Format("An error occured while logging an exception in the program. Retry?"), MsgBoxStyle.RetryCancel) = MsgBoxResult.Retry
If Not retry Then
'Failure logging
out.WasLogged = False
Return
End If
Catch exc As Exception
out.LoggingException = exc
out.WasLogged = False
Return
End Try
Loop While retry And tries < 10
Else
'Ex is nothing
out.WasLogged = False
Return
End If
out.WasLogged = True
Return
End Sub
然而,进一步导致我排除我自己的代码是问题的原因是,我在 21.5k 重复记录上做了一个 select distinctSqlExceptions
并且只返回了 4 个唯一的堆栈跟踪,没有一个表明在处理期间发生了异常,并且没有一个在任何类型的循环。2 个在Keydown
触发 Sql 查询代码的处理程序内,一个在Load
触发查询的处理程序内,一个在Click
事件内。
这是两个堆栈跟踪,除了客户端代码 FWIW:
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket()
at System.Data.SqlClient.TdsParser.ConsumePreLoginHandshake(Boolean encrypt, Boolean trustServerCert, Boolean& marsCapable)
at System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, SqlConnection owningObject)
at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, Int64 timerExpire, SqlConnection owningObject)
at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(String host, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, Int64 timerStart)
at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance)
at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options)
at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()
和#2
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.ReadBuffer()
at System.Data.SqlClient.TdsParserStateObject.ReadByte()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()