错误捕捉方案
来源:互联网 发布:买淘宝店铺安全吗 编辑:程序博客网 时间:2024/05/16 12:14
IBMS错误处理改善
设计说明书V1.0
修订历史
版本 日期 修改内容 作者 审核人 批准
1.0
2011-03-30
发布
1. 概述
1.1 目的
目前IBMS系统后台捕捉错误的信息只有代理或脚本库名称和出错行数,并且是通过描述的方式输出在控制台上,这种方式很不规范,造成了查询、跟踪错误比较困难。为了更好的跟踪IBMS系统发生的错误信息,需要改善目前捕捉错误日志信息的处理方式。
1.2 适用范围
IBMS错误捕捉与处理
1.3 术语表
表1-1术语与缩写表
缩写、术语
解释
2. 架构设计
2.1 基本逻辑图
系统关系说明:
n 应用数据库:IBMS系统的一个应用库,当用户操作或系统自动处理出现异常错误时,程序的错误捕捉机制获取到错误信息,抛出错误到控制台,并在错误日志库中建立相应文档。
n 错误日志库:IBMS架构下的数据库,为了方便设计,路径固定为“lks/sys/lks_ErrorLog.nsf”。按照一定规则保存所有抛出的异常错误,同时通过代理定时将错误日志导入到关系型数据库中(SQL)。
n 关系型数据库:用于长期保存所有的异常错误。
3. 错误日志库
3.1 表单设计说明
3.1.1 错误日志
n 表单画面
暂略
n 表单字段说明
字段名
Notes字段名
SQL字段名
SQL字段类型
是否必需
描述
错误编号
F_ErrorNo
Error_No
NVARCHAR(50)
是
控制台显示错误消息时,可以根据错误编号到错误日志库中查询对应文档查看详细错误日志
编号规则:
Err_yymmdd_0001(四位流水号)
错误类型
F_ErrorType
Error_Type
INT
是
0 -系统捕捉到错误,并且已针对错误进行处理
1 -系统捕捉的未知错误,未对错误进行处理
默认:1
严重程度
F_ErrorLevel
Error_Level
INT
是
0 -一般(不会对用户造成影响)
1 -严重(可能对用户造成影响,但仅局限于某个用户或单独的应用模块)
2 -非常严重(可能对整个系统造成影响)
默认:1
错误时间
F_ErrorTime
Error_Time
DateTime
是
发生错误时间
代理名称
F_ErrorAgent
Error_Name
NVARCHAR(255)
是
发生错误的代理名称
脚本库名称
F_ErrorLibary
Error_Libary
NVARCHAR(50)
是
发生错误的脚本库名称
函数名称
F_ErrorFunction
Error_Function
NVARCHAR(50)
是
发生错误的函数名称
错误行数
F_ErrorLine
Error_Line
INT
是
错误代码
F_ErrorCode
Error_Code
INT
是
错误描述
F_ErrorDesc
Error_Desc
NVARCHAR(255)
是
服务器名称
F_ErrorServer
Error_Server
NVARCHAR(50)
是
发生错误的服务器名称
数据库ID
F_ErrorDBID
Error_DBID
CHAR(32)
是
发生错误的代理所在数据库ID
数据库路径
F_ErrorDBPath
Error_DBPath
NVARCHAR(255)
是
发生错误的代理所在数据库路径
处理文档
F_ErrorDocID
Error_DocID
NVARCHAR(255)
否
发生错误时正在处理的文档ID
处理字段
F_ErrorField
Error_Field
NVARCHAR(50)
否
发生错误时正在处理的字段名称
当前用户
F_ErrorUser
Error_User
NVARCHAR(50)
否
发生错误时当前用户名称
当前用户IP
F_ErrorIP
Error_IP
NVARCHAR(50)
否
发生错误时用户的访问IP地址
当前流程名称
F_ErrorFlow
ErrorFlow
NVARCHAR(100)
否
发生错误时当前流程名称
当前流程节点
F_ErrorFlowNode
ErrorFlowNode
NVARCHAR(100)
否
发生错误时当前流程环节
3.1.2 系统设定
n 表单画面
暂略
n 表单字段说明
字段名
Notes字段名
Notes字段类型
是否必填
描述
服务器
F_Server
文本
是
SQL Server服务器名称或ip地址
数据库
F_Database
文本
是
存放错误日志的数据库名称
表单
F_Form
文本
是
存放错误日志的表
用户名
F_Login
文本
是
链接Sql的用户名,需要有写的权限
密码
F_Password
密码
是
3.2 代理
代理用于将日志文档定时导入到关系型数据库中。
运行方式:定时运行
运行频率:每周一次
处理方式:从日志库中获取Flag标志不等于“1”的错误日志文档,成功导入到关系型数据库后将文档Flag标志设为“1”。
4. 应用库
4.1 错误处理范围
错误处理的涉及范围:所有应用库的代理、脚本库。
4.2 错误处理方案
因原先的错误处理方式多样,没有统一的接口来处理,且经过多次开发后,代码格式也不统一,没法通过程序统一来部署,所以本方案只能采用人工一一部署的方式。
(一)旧错误捕捉方式处理
因原先已经存在的错误处理方式多样,且存在量很多。如果一一分析是否需要删除并用新的方案替换,此种方式工作量太大。所以采用原来的错误保持不变,在原先的基础上增加新的处理机制,当出现问题时,只要关注新的错误提示信息即可。
(二)新的错误捕捉方式处理
n 代码添加的两种方式:
A. 错误冒泡模式,即错误会反映到上层调用者(即引起上层调用者触发错误),如:
序号
部署前代码
部署后代码
描述
1
一般的函数
Sub Sample()
On Error Goto errhandle
代码块
errhandle:
原错误处理块
End Sub
Use "LS_CError"
Sub Sample()
On Error Goto errhandle
代码块
errhandle:
原错误处理块
Dim cError As New CError(Erl,Err,Error)
Error Err,cError.GetError
End Sub
n "LS_CError"脚本中为错误处理类
n 黄色标记的为新的错误处理方式:
像这种部署前的代码可以看出报错后,错误会反映到上层调用者,那么在此sub内就不需要建立错误日志文档和将错误信息输入到服务器控制台,只需要将错误信息手动抛出到上层调用者那即可。
注:部署只要将黄色标记代码添加到合理位置即可
Function Sample()也是如此
2
一般类
Public Class temp
Sub Sample()
On Error Goto errhandle
代码块
errhandle:
原错误处理块
End Sub
End Class
Use "LS_CError"
Public Class temp
Sub Sample()
On Error Goto errhandle
代码块
errhandle:
原错误处理块
Dim cError As New CError(Erl,Err,Error)
Error Err,cError.GetError
End Sub
End Class
n "LS_CError"脚本中为错误处理类
n 黄色标记的为新的错误处理方式:
像这种部署前的代码可以看出报错后,错误会反映到上层调用者,那么在此sub内就不需要建立错误日志文档和将错误信息输入到服务器控制台,只需要将错误信息手动抛出到上层调用者那即可。
注:部署只要将黄色标记代码添加到合理位置即可
Function Sample()也是如此
错误描述说明
保存到错误日志库和输出到控制台的错误信息格式为:
【ErrorNo】_【Server】_【Database】_【Agent】_【LotusScript】_【Function】_【Error】_
示例:
【Server】CN=homedev/O=STP【Database】suntech/sto/lks_MaterialIntroduce.nsf【Agent】测试错误日志代理|test【LotusScript】TESTSCRIPT【Function】TEST【Error】Type mismatch(10,13)
Type mismatch(10,13)括号中的第一个表示错误行,第二个表示错误代码
B. 错误不冒泡模式,即错误不会反映到上层调用者,如:
序号
部署前代码
部署后代码
描述
1
脚本库
Sub Initialize
On Error Goto errhandle
代码块
errhandle:
原错误处理块
End sub
Use "LS_CError"
Sub Initialize
On Error Goto errhandle
代码块
errhandle:
原错误处理块
Dim cError As New CError(Erl,Err,Error)
cError.ThrowError
End sub
n 黄色标记的为新的错误处理方式:
像这种部署前的代码可以看出报错后,在Initialize错误不会反映到外层,那么在此sub内就需要建立错误日志文档和将错误信息输入到服务器控制台
注:部署只要将黄色标记代码添加到合理位置即可
2
代理
Sub Initialize
On Error Goto errhandle
代码块
errhandle:
原错误处理块
End sub
Use "LS_CError"
Sub Initialize
On Error Goto errhandle
代码块
errhandle:
原错误处理块
Dim cError As New CError(Erl,Err,Error)
cError.ThrowError
End sub
n 黄色标记的为新的错误处理方式:
像这种部署前的代码可以看出报错后,在Initialize错误不会反映到外层,那么在此sub内就需要建立错误日志文档和将错误信息输入到服务器控制台
注:部署只要将黄色标记代码添加到合理位置即可
3
代理和脚本的一般函数
Sub Sample()
On Error Goto errhandle
代码块
Exitfunc:
Exit sub
errhandle:
原错误处理块
Resume exitfunc
End sub
Use "LS_CError"
Sub Sample()
On Error Goto errhandle
代码块
Exitfunc:
Exit sub
errhandle:
原错误处理块
Dim cError As New CError(Erl,Err,Error)
cError.ThrowError
resume exitfunc
End sub
n 黄色标记的为新的错误处理方式:
像这种部署前的代码可以看出报错后,错误不会反映到上层调用者,那么在此sub内就需要建立错误日志文档和将错误信息输入到服务器控制台。
注:部署只要将黄色标记代码添加到合理位置即可
Function Sample()也是如此
说明:如果通过exit function/sub的方式结束的话一般不会将错误反映到上层调用者
4一般函数
Sub Sample()
On Error Goto errhandle
代码块
Exit sub
errhandle:
原错误处理块
Resume next
End subn 黄色标记的为新的错误处理方式:
像这种部署前的代码可以看出报错后,错误不会反映到上层调用者,那么在此sub内就需要建立错误日志文档和将错误信息输入到服务器控制台。
注:部署只要将黄色标记代码添加到合理位置即可
Function Sample()也是如此
说明:如果通过<FONT style="LINE-HEIGHT: 125%" color="red" face=""">exit function/sub的方式结束的话一般不会将错误反映到上层调用者
错误描述说明
保存到错误日志库和输出到控制台的错误信息格式为:
【ErrorNo】_【Server】_【Database】_【Agent】_【LotusScript】_【Function】_【Error】_【Execute Relation】_
示例:
【Server】CN=homedev/O=STP【Database】suntech/sto/lks_MaterialIntroduce.nsf【Agent】测试错误日志代理|test【LotusScript】TESTSCRIPT【Function】TEST【Error】Type mismatch(10,13)【Execute Relation】[LS]TESTSCRIPT[Func]TEST1(5)<<[LS]TESTSCRIPT[Func]TEST2(3)<<[LS]DADDC54[Func]INITIALIZE(3)
n 【Execute Relation】表示错误程序的一个调用关系,关系为代理“测试错误日志代理|test”的INITIALIZE方法调用了方法test2,test2调用了test1,test1调用了test,test方法报错,将错误信息冒泡到调用层,生成了此错误信息。
n [LS]TESTSCRIPT[Func] TEST1 (5)表示脚本库TESTSCRIPT的方法TEST1的第5行报错,它调用了test方法
n [LS]DADDC54[Func]INITIALIZE(3)中LS为DADDC54时不像一个脚本的名称则表示此LS其实是Agent代号(无法获得代理名,代理名称前面已经通过其他方式获取了,所以不影响)
n 可选参数的设置
错误类型、严重程度和处理文档ID、自定义参数(描述看类的方法),这4个参数默认情况下可以不需要处理。但有些方法体内报错时有此4个参数中的部分参数需要保存到错误日志时,可以通过CError类的SetOptional成员方法来完成。
如:
Use "LS_CError"
Sub Sample()
On Error Goto errhandle
代码块
Exitfunc:
Exit sub
errhandle:
原错误处理块
Dim cError As New CError(Erl,Err,Error)
Call cError.SetOptional(1,1,cdoc.DocumentUniqueID,"F_ErrorField:1;F_ErrorUser:1;F_ErrorIP:1; F_ErrorFlow:1;F_ErrorFlowNode:1")
cError.ThrowError
resume exitfunc
End sub
n 特殊部署说明
在部署过程中,可能有些方法并没有加On Error goto语句来捕捉错误,所以这里可能就不会部署新的错误捕捉机制。当一个方法报错并触发新的错误捕捉机制(错误冒泡模式)时,它的调用链(方法的调用者,一直到代理的Initialize方法)中没有一个方法部署了新的错误捕捉机制,出现的问题为抛出的错误信息未使用类CError的ThrowError方法来处理,那么将不会保存错误信息到错误日志库中,只会抛出如下的错误信息到控制台:
2011-06-29 13:06:41 HTTP Server: Agent '测试错误日志代理(部分无错误处理) test3' error: F_ErrorType:1;F_ErrorLevel:1;F_ErrorDocID:;F_ErrorField:;F_ErrorUser:CN=guangbiao Pan/OU=WuXi/O=STP;F_ErrorIP:1;F_ErrorFlow:1;F_ErrorFlowNode:1*&$#【Ser
ver】CN=homedev/O=STP【Database】suntech/sto/ErrorTemp.nsf【Agent】测试错误日志代理(部分无错误处理) test3【LotusScript】TESTSCRIPT3【Function】TEST【Error】Type mismatch(7,13)
注:错误信息由 类CError的方法GetError产生
A. 解决方法一:在所有代理的Initialize方法中使用新的错误捕捉机制,但可能会无法获得完整的调用链(建议)
B. 解决方法二:不执行解决方法一,让错误只在控制台显示(不建议)
5. 原代码
错误日志类的原代码
'****************************************************'类名:CError
'描述:记录脚本运行错误,并保存到错误日志库中(lks/sys/lks_ErrorLog.nsf)
'作者:潘广彪
'日期:2011.06.13-2013.11.12
'****************************************************
Public Class CError
'◆定义属性----------------------------------------------------------------------------------
Public session As NotesSession
Public cdb As NotesDatabase
Public cAgent As NotesAgent
Public errorDb As NotesDatabase '错误日志库
'==============属性1========================
Public ErrorLine As Long '错误行数
Public ErrorCode As Integer '错误代码
Public ErrorDesc As String '错误描述
'==============属性2========================
Public ErrorNo As String '错误编号:Err_yymmdd_0001(四位流水号)
Public ErrorTime As NotesDateTime '错误时间
Public ErrorServer As String '服务器名称
Public ErrorDBID As String '数据库ID
Public ErrorDBPath As String '数据库路径
Public ErrorAgent As String '代理名称
Public ErrorLibary As String '脚本库名称
Public ErrorFunction As String '函数名称
'==============属性3========================
Public ErrorType As Integer '错误类型:
'0-系统捕捉到错误,并且已针对错误进行处理
'1 -系统捕捉的未知错误,未对错误进行处理
Public ErrorLevel As Integer '严重程度:
'0- 一般(不会对用户造成影响)
'1 - 严重(可能对用户造成影响,但仅局限于某个用户或单独的应用模块)
'2 - 非常严重(可能对整个系统造成影响)
Public ErrorDocID As String '处理文档ID
Public SelfDefineParam As String '自定义参数,在方法SetOptional中详细描述
'●构造方法-----------------------------------------------------------------------------------
Public Sub New(errorLine As Long,errorCode As Integer,errorDesc As String)
Me.ErrorLine=errorLine
Me.ErrorCode=errorCode
Me.ErrorDesc=errorDesc
ErrorType=1
ErrorLevel=1
Set session=New NotesSession
Set cdb=session.CurrentDatabase
Set cAgent=session.CurrentAgent
Set errorDb=session.GetDatabase(cdb.Server,"lks/sys/lks_ErrorLog.nsf",False)
End Sub
'●定义方法-----------------------------------------------------------------------------------
'*******************************************
'方法:抛出错误信息
'描述:抛出所有错误信息并保存到错误日志库中
'*******************************************
Public Sub ThrowError()
ErrorLibary=Getthreadinfo(11)
ErrorFunction=Getthreadinfo(10)
'获取错误信息
Me.GetError
'保存错误日志
Me.save
'输出错误到控制台
Me.PrintToConsole
End Sub
'*******************************************
'方法:获取错误信息
'描述:获取所有错误信息并保存到错误日志库中
'*******************************************
Public Function GetError()
ErrorServer=cdb.Server
ErrorDBID=cdb.Replicaid
ErrorDBPath=cdb.FilePath
Set ErrorTime=New NotesDateTime(Now)
ErrorAgent=cAgent.Name
If ErrorFunction=""Then
ErrorLibary=Getthreadinfo(11)
ErrorFunction=Getthreadinfo(10)
End If
GetError=Me.GetErrorDesc
End Function
'*******************************************
'方法:保存错误日志
'描述:保存错误信息到错误日志库中
'*******************************************
Private Sub Save()
If errorDb Is Nothing Then
Msgbox "错误日志库打开失败..."
Else
'保存必要属性
Dim errDoc As NotesDocument '错误日志文档
Set errDoc=errorDb.CreateDocument
errDoc.Form="FM_ErrorLog"
'获取详细错误描述
Dim fullErrorDesc As String
Dim errorDesc As String
fullErrorDesc=Me.GetErrorDesc
errorDesc=Strright(fullErrorDesc,"*&$#")
errDoc.F_ErrorDesc=errorDesc
'从详细错误描述中提取错误行、错误代码、脚本名、函数名
Dim errorInfo As String
errorInfo=StrMiddle(errorDesc,"【Error】","【")
errorInfo=Strright(errorInfo,"(")
errDoc.F_ErrorLine=Strleft(errorInfo,",")
errDoc.F_ErrorCode=StrMiddle(errorInfo,",",")")
errDoc.F_ErrorLibary=StrMiddle(errorDesc,"【LotusScript】","【")
errDoc.F_ErrorFunction=StrMiddle(errorDesc,"【Function】","【")
'--------------------------------------------------------
ErrorNo=GetErrorNo()
errDoc.F_ErrorNo=ErrorNo
Dim item As New NotesItem(errDoc,"F_ErrorTime",ErrorTime)
item.IsSummary=True
errDoc.F_ErrorServer=ErrorServer
errDoc.F_ErrorDBID=ErrorDBID
errDoc.F_ErrorDBPath=ErrorDBPath
errDoc.F_ErrorAgent=ErrorAgent
'获取非必要属性
Dim arrFullErrorDesc As Variant
arrFullErrorDesc=Split(Strleft(fullErrorDesc,"*&$#"),";")
arrFullErrorDesc=fulltrim(arrFullErrorDesc)
Dim i As Integer
For i=0 To Ubound(arrFullErrorDesc)
Call errDoc.AppendItemValue(Strleft(arrFullErrorDesc(i),":"),Strright(arrFullErrorDesc(i),":"))
Next
Call errDoc.Save(True,False)
End If
End Sub
'*******************************************
'方法:获取详细错误描述
'描述:将错误信息分类组合显示
'格式:非必要属性*&$#必要属性+触发错误机制的方法调用链
'*******************************************
Private Function GetErrorDesc() As String
If Instr(ErrorDesc,"【Server】") <> 0 Then '表示GetErrorDesc的方法已经被执行过至少一次
'增加触发错误机制所在方法的调用链
If Instr(ErrorDesc,"【Execute Relation】") <> 0 Then
GetErrorDesc=ErrorDesc & |<<[LS]|& ErrorLibary & |[Func]| & ErrorFunction & |(| & ErrorLine & |)|
Else
GetErrorDesc=ErrorDesc & |【Execute Relation】| & |[LS]|& ErrorLibary & |[Func]| & ErrorFunction & |(| & ErrorLine & |)|
End If
Else
'获取非必要属性描述
Dim optionnalDesc As String
GetErrorDesc=|F_ErrorType:| & ErrorType & |;F_ErrorLevel:| & ErrorLevel & |;F_ErrorDocID:| & ErrorDocID & |;| & SelfDefineParam
'获取必要属性描述
GetErrorDesc=GetErrorDesc & |*&$#| & |【Server】| & ErrorServer &|【Database】| & ErrorDBPath & |【Agent】| & ErrorAgent & |【LotusScript】| & ErrorLibary &_
|【Function】| & ErrorFunction & |【Error】| & ErrorDesc & |(| & ErrorLine & |,| & ErrorCode & |)|
End If
End Function
'*******************************************
'方法:获取错误编号
'描述:
'*******************************************
Private Function GetErrorNo() As String
Dim profileDoc As NotesDocument
Dim prefix As String
Dim no As String
Set profileDoc=errorDb.GetProfileDocument("SysErrorNo")
prefix="Err_" & Right(Year(Today),2) & Format(Month(Today),"00") & Format(Day(Today),"00")
If prefix<>profileDoc.F_Prefix(0)Then
GetErrorNo= prefix & "0001"
profileDoc.F_Prefix=prefix
profileDoc.F_No="0001"
Else
no=Format(Int(profileDoc.F_No(0))+1,"0000")
profileDoc.F_No=no
GetErrorNo= prefix & no
End If
Call profileDoc.Save(True,False)
End Function
'*******************************************
'方法:设置多个属性值
'描述:对部分非必要的属性赋值
'参数:
'selfDefineParam:自定义参数
'格式:Notes字段名:值;Notes字段名:值;...;Notes字段名:值
'为了字段统一,提供几个自定义参数的字段名 :
'F_ErrorField(处理字段),F_ErrorUser(当前用户), F_ErrorIP (当前用户IP),F_ErrorFlow(当前流程名称),F_ErrorFlowNode(当前流程节点)
'*******************************************
Public Sub SetOptional(errorType As Integer,errorLevel As Integer,errorDocID As String,selfDefineParam As String)
Me.ErrorType=errorType
Me.ErrorLevel=errorLevel
Me.ErrorDocID=errorDocID
Me.SelfDefineParam=selfDefineParam
End Sub
'*******************************************
'方法:输出错误信息到控制台
'描述:
'*******************************************
Public Sub PrintToConsole()
Msgbox |【ErrorNo】| & ErrorNo & Strright(Me.GetErrorDesc,"*&$#")
End Sub
'*******************************************
'方法:截取字符串
'描述:
'*******************************************
Private Function StrMiddle(sourceStr As String,startStr As String,endStr As String) As String
Dim returnInfo As Variant
returnInfo=Evaluate(|@Middle("| & sourceStr & |";"| & startStr & |";"| & endStr & |")|)
StrMiddle=returnInfo(0)
End Function
End Class
- 错误捕捉方案
- SQL Server2005捕捉错误的2种方案
- 错误捕捉
- sql2005 中捕捉错误
- Opencv 错误捕捉
- openCV错误捕捉
- LotusScript捕捉错误
- Linux错误捕捉
- 设置NSZombieEnabled捕捉错误
- ORACLE错误捕捉
- 捕捉存储过程错误
- 悬而未决:如何捕捉warning错误?
- 捕捉Flash的全局错误
- php错误及异常捕捉
- linux下的错误捕捉
- java 捕捉错误try-catch
- php错误及异常捕捉
- Matlab运行错误捕捉办法
- 应该这样
- Java RMI
- CListCtrl表头控制
- 可空类型的转换问题(?|nullable)
- gcc 指定运行时动态库路径
- 错误捕捉方案
- 登录远程SQL服务器
- ASP.NET自定义错误页面
- Remove Microsoft Security Center 2012 Furtive Fraud Utility
- window.open()的所有参数列表
- Uninstall Kaspersky Internet Security 2010 – Windows Kaspersky Internet Security 2010 Uninstaller Review
- 设计模式--observer pattern
- 晨起自勉文
- tomcat 注册卸载服务