49. 面向对象的LotusScript(十五)之Log4Dom下

Log4Dom是模仿Log4J的思想建立的。Log4J能够向多种记录媒介以统一的格式写入各种级别的日志信息(包括错误、调试和信息等),还可以籍配置文件在运行时方便地修改记入日志的级别。Log4Dom提供了类似的功能。现在我们就来看看它的各部分元素和代码。

1.      记录日志的文档所用的表单

2.      用于配置日志级别的表单

3.      日志文档视图

第一列按创建日期分类,第二列是文档序号,第三列是创建时间,最后一列是日志名称。还有一个操作可以编辑配置文档。

4.      日志类代码

'version 1.2-18th March 2008
'added Log4Dom profile,
'simplified the usage and renamed some methods, 
'deleted unnecessary log document size check
'added several features e.g. logging generated error message 
'corrected several bugs
'@author Starrow Pan
' 
' Original comments
' class for the domino implementation of a logger in a similar format
' as log4J (http://jakarta.apache.org/log5j/
' @author tony.palmer@ing.com.au
' @version 1.0 - 4th November 2003

Private Const CUSTOM_ERR=10000
Private Const CUSTOM_ERROR="CUSTOM ERROR: "

' debugging levels 0 - 5 system, 6 - 10 custom
Const LEVEL_DEBUG = 5
Const LEVEL_DEBUG_STRING = "DEBUG"
Const LEVEL_INFO = 4
Const LEVEL_INFO_STRING="INFO"
Const LEVEL_WARN = 3
Const LEVEL_WARN_STRING = "WARN"
Const LEVEL_ERROR = 2
Const LEVEL_ERROR_STRING = "ERROR"
Const LEVEL_FATAL = 1
Const LEVEL_FATAL_STRING = "FATAL"
Const LEVEL_NONE = 0

' destination types
Const DEST_TYPE_DB = 0		'/ notes database
Const DEST_TYPE_FILE = 1		'/ text file
Const DEST_TYPE_STATUS = 2	'/ notes status bar
Const DEST_TYPE_PROMPT = 3   '/ message box prompts

Class Log4Dom	
	public logLevel As Integer
	public module As String			'module
	
	'the Log Destination, set as a variant then depending on the log type, 
	'set as either a LogDB, logNotesFile, logStatus or logPrompt	
	Private logFile As Variant					
	
	Private m_sess As NotesSession 
	Private m_curdb As NotesDatabase 'current database
	Private m_profile As NotesDocument 'Log4Dom profile document
	public logName As String 'log name from the profile
	
	Sub New ()
		Set m_sess=New NotesSession
		logLevel = LEVEL_DEBUG
	End Sub
	
	%REM
		Add a log destination.
		As the de facto only used log destination is Notes DB,
		I didn't handle the case of multiple log destinations of different types.
	%END REM
	Public Function AddLogFile(file As Variant)
		Set logFile = file
		
		If TypeName(file)="LOGDB" then
			'read parameter from Log4Dom profile by starrow
			Set m_curdb=m_sess.CurrentDatabase
			Set m_profile=m_curdb.GetProfileDocument("Log4DomProfile")
			If Not m_profile Is Nothing Then
				If m_profile.GetItemValue("LogLevel")(0)><"" then
					logLevel=m_profile.GetItemValue("LogLevel")(0)
				End if
				logName=m_profile.GetItemValue("LogName")(0)
			End If
			'if no parameter provided, try the agent name
			If logName="" Then
				If Not m_sess.CurrentAgent Is Nothing Then
					logName=m_sess.CurrentAgent.Name
				End If
			End If
			
			logFile.LogName=logName	
		End if	
	End Function
	
	'logging at the different levels, INFO, WARN etc
	Public Function info(message As String) As Integer			
		info = WriteLog(LEVEL_INFO, message)	
	End Function
	
	Public Function warn(message As String) As Integer
		warn = WriteLog(LEVEL_WARN, message)
	End Function
	
	Public Function debug(message As String) As Integer
		debug = WriteLog(LEVEL_DEBUG, message)	
	End Function
	
	'Can't use error as the function name because it's a reserved word.
	'If used for logging a runtime error, leave the argument as an empty string.	
	Public Function LogError(message As String) As Integer
		If message="" Then
			'Generate the message for a runtime error.
			'The GetThreadInfo(LSI_THREAD_CALLPROC) must be called here instead of 
			'calling an universal function to get the error message because that would
			'always return LogError as the function raising the error.  
			'LSI_THREAD_CALLMODULE=11, LSI_THREAD_CALLPROC=10
			message = GetThreadInfo(11) & ">" & GetThreadInfo(10) & ": " & _
			"Error(" & Err() & "): " & Error() & " at line "& Erl()
		End If
		LogError = WriteLog(LEVEL_ERROR, message) 	
	End Function
	
	Public Function fatal(message As String) As Integer
		fatal = WriteLog(LEVEL_FATAL, message)		
	End Function
	
	'user level logging, for specific level logging
	'@param level integer - the level 10 is the most detail, 1 the lowest level
	'message - a string to be logged. Number, boolean and date values would be
	'automatically converted to strings by LotusScript. Other types should be manually converted.
	Public Function WriteLog(level As Integer, message As String) As Integer
		Dim theDate As String
		Dim theLevel As String
		Dim theMessage As String
		theDate = Cstr(Now)
		theLevel = "["+GetLevelString(level)+"] "		
		theMessage = theDate+" "+theLevel+" "+module+" - "+message
		' check that logging is turned on for this level
		' otherwise there is no need to log
		If level <= logLevel Then
			Call logFile.writelog(theMessage)
		End If
	End Function
	
	'closes the log, saves notes doc or closes file
	Public Function Close
		logFile.close
	End Function
	
	
	'convert from level numbers into string
	Private Function GetLevelString(level As Integer) As String
		Select Case level
			Case LEVEL_INFO : GetLevelString = LEVEL_INFO_STRING
			Case LEVEL_DEBUG : GetLevelString = LEVEL_DEBUG_STRING
			Case LEVEL_WARN : GetLevelString = LEVEL_WARN_STRING
			Case LEVEL_ERROR : GetLevelString = LEVEL_ERROR_STRING
			Case LEVEL_FATAL : GetLevelString = LEVEL_FATAL_STRING
			Case Else : GetLevelString = "LEVEL "+Cstr(level)
		End Select
	End Function
	
End Class
'/**
'* Set Log destination as a domino database
'*/
Class LogDB
	Private m_sess As NotesSession
	Private m_dbLog As NotesDatabase		'nsf if destination is db
	Private m_docLog As NotesDocument	'document that the log gets appended to
	Private m_rtitem As NotesRichTextItem   'rtf
	public logName As String 
	
	Sub New(db As NotesDatabase)
		Set m_sess=New NotesSession
		If db Is Nothing Then
			Set m_dbLog = m_sess.currentdatabase
		Else
			Set m_dbLog = db
			If m_dbLog.isOpen = False Then
				Error CUSTOM_ERR, CUSTOM_ERROR & "Could not open the log Database."
			End If
		End If		
	End Sub
	
	'get the log document as some calling program may need access it e.g. mail it.
	Public Property Get LogDocument As NotesDocument
		Set LogDocument=m_docLog
	End Property
	
	'/**
	'*  method for logging to a notes document 
	'*/
	Public Function writeLog(message As String) As Integer		
		If m_docLog Is Nothing Then
			' create a new log document
			Set m_docLog = m_dbLog.createDocument
			Call m_docLog.ReplaceItemValue("LogName",logName)
			If m_sess.IsOnServer Then
				Call m_docLog.ReplaceItemValue("ScriptRunOn","Server")
			Else
				Call m_docLog.ReplaceItemValue("ScriptRunOn","Workstation")
			End If
			Set m_rtitem = New NotesRichTextItem(m_docLog, "logBody")
		End If
		'currently each log line is in one paragraph, no limits will be violated
		m_rtitem.appendtext(message)
		m_rtitem.addnewline(1)
		
		writeLog= True
	End Function
		
	'/**
	'* closes the log, saves notes doc
	'*/
	Public Function Close
		If Not(m_docLog Is Nothing) Then
			m_docLog.Form="log"
			Call m_docLog.Save(True,True)
		End If
	End Function	
End Class

'Get a logger instance that writes to the specified db.
Public Function GetLogger(db As NotesDatabase) As log4Dom
	Dim logger As log4dom
	Set logger = New log4dom()
	Dim logFile As New LogDB(db)
	Call logger.AddLogFile(logFile)	
	Set GetLogger=logger
End Function

上述代码的各个方法都有注释。使用的时候像上一篇文章里所示样例一样,只需初始化一个logger实例并添加目标数据库(若为当前数据库,就传入Nothing),之后就可以调用Info()、Debug()、LogError()等各种方法写入日志。传入LogError()方法的如果是空字符串,它就会试图记录最近发生的错误的详细信息,因此可以用作处理错误的语句。最后要调用Close()方法,记录日志的文档才会被保存。

原来版本所具的其他日志目标媒介类,实际上都极少用到。Notes文档和视图的现成功能使其很适宜用来记录和查询日志。文本文件比起来不那么方便,而要写到状态栏或者用对话框显示直接用LotusScript对应的语句即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值