로그파일 저장 그리고 로그를 표시하기 위한 코딩.... 프로그램 개발 할 때마다 만들어야 되는 실정... 질려 죽겠어서 클래스로 만들었습니다.
기본 설정
- 글로벌이나 지역변수로 클래스 변수를 선언합니다.
VB
dim logMgr as claLogMgr
- 이어서 기본 세팅 들어갑니다.
VB
logMgr.m_LogPath = app.path & "\Log" '로그 경로 설정
logMgr.m_SetAppTitle = app.ProductName '미리 프로젝트 설정에서 ProductName을 설정하시거나 붙박이로 넣어주세요.
logMgr.m_SetLogLev = INCLUDE_DEBUG '로그파일 저장 시 어떤 레벨까지 저장할지 지정합니다. 상수는 다음 과 같습니다.
' ESSENTIAL_MESSAGE = 저장하지 않음
' ONLY_CRITICAL_ERROR = CRITICAL 오류만 저장
' INCLUDE_MAJOR_ERROR = CRI를 포함한 MAJOR 오류 저장
' INCLUDE_MINOR_ERROR = CRI, MAJ를 포함한 MINOR 오류 저장
' INCLUDE_WARNING = CRI, MAJ, MIN을 포함한 WARNING 메시지 저장
' INCLUDE_COMMON_MESSAGE = 위에 꺼 다 포함 일반 메시지 저장
' INCLUDE_DEBUG = 위에 꺼 다 포함 DEBUG 메시지까지 저장
- 위의 상수는 어느레벨을 저장할지에 대한 상수이니 로그에 대한 레벨을 설정할 수 있는 상수도 있어야겠죠.
- 에러 등급은 개발자 본인이 정하면 됩니다. 로그는 개발자를 위한 것이니까요.
VB
' COMMON_MSG = 일반 메시지 입니다.
' MIN_ERROR = 마이너한 에러. 운영상에 하나도 문제도 없으나, 사용자 실수에 의한 메시지
' MAJ_ERROR = 운영상에 문제가 없지만 RISK적인 메시지
' CRI_ERROR = 운영상에 문제가 무진장 많으니 데몬이면 바로 정지 할 수 밖에 없는 상태
' DEBUG_LOG = 개발자를 위한 디버깅 메시지
- 이어서 기본설정 다시 들어갑니다.
VB
'위에 SetLev은 파일저장.. 이것은 리스트 박스에의 레벨을 지정합니다. 꼭 파일로는 저장은 해야 하는데 사용자에게 표시할 필요는 없을 때 사용되죠.
logmgr.m_SetDisplayLev = INCLUDE_DEBUG
- 다음은 리스트 박스 세팅입니다. 폼 로딩 시 Set해야겠죠.
VB
Set logMgr.m_ListBox = lstLog 'lstLog라는 리스트박스가 폼에 생성되어 있어야 합니다.
Set logMgr.m_chkSchroll = chkSchroll 'chkSchroll이라는 체크박스가 있어야겠죠. 이것은 리스트박스의 스크롤이 가장 밑으로 새로고침되는데 체크를 해제하게 되면 스크롤을 맘대로 가지고 놀 수 있습니다.
Set logMgr.m_chkRealTime = chkRealTime 'chkRealTime이라는 체크박스가 있어야 합니다. 체크해제하게 되면 리스트박스에 로그가 추가되지 않습니다. 파일에만 저장이 되죠. 로그 표시때문에 프로그램 운영이 0.00000000000001초라도 느려지게 되면 좀 아니어서 추가하였습니다.
기본적인 사용방법
- 설정은 다 했다고 생각하고 들어가겠습니다.
VB
logMgr.addLog "프로그램이 시작되었습니다.",
- 이렇게만 해서 쓰게 되면 기본적인 Optional설정이 되어 사용할 수 있습니다. 완존 기본적인 일반 메시지 추가 시 이렇게 씁니다.
VB
logMgr.addLog "사용자가 맘에 들지 않아요", false, DEBUG_LOG, "그냥", "ProcDebug()", false
- 이게 풀로 파라미터를 쓴 경우입니다. 다음은 파라미터 설명 드릴께요.
- [1] str = 로그 메시지죠. 가장 중요하죠.. 꼭 넣어야 합니다.
- [2] bLstAdd = 리스트박스에 넣을 건지에 대한 여부입니다. 만약 리스트박스 세팅을 하지 않았다면 SKIP합니다.
- [3] ErrLev = 로그에 대한 에러등급입니다. 기본적으로 COMMON_MSG로 되어 있습니다.
- [4] ErrCD = 에러코드를 따로 지정할 수 있습니다. 이것은 에러를 사전에 분류가 되어야 합니다. 가령 네트워크, 디비, 사용자오류 이런식으로 분류를 하여 코드를 따서 관리를 하게 되면 로그관리가 비교적 쉬워집니다.
- [5] sPos = 자바나 웹처럼 몇 번째 줄에서 오류 났는지는 모르지만 인위적으로 어떤 함수에서 에러가 났는지 표현하기 위해서 추가하였습니다.
- [6] bTimeStr = 로그표시 할때 시간정보를 넣게 되는데 이걸 False로 하게 되면 아무것도 넣지 않고 표시 또는 파일저장합니다.
전체 클래스 소스
아래는 claLogMgr.cls 파일 전문 입니다.
VB
VERSION 1.0 CLASS
BEGIN
MultiUse = 0 'False
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "claLogMgr"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
' 로그 등급
Public Enum DISPLAY_ERROR_GRADE
COMMON_MSG = 0
MIN_ERROR = 1
MAJ_ERROR = 2
CRI_ERROR = 3
DEBUG_LOG = 4
End Enum
' 파일저장/표시 레벨
Public Enum LOG_GRADE
ESSENTIAL_MESSAGE = 0
ONLY_CRITICAL_ERROR = 1
INCLUDE_MAJOR_ERROR = 2
INCLUDE_WARNING = 3
INCLUDE_COMMON_MESSAGE = 4
INCLUDE_DEBUG = 5
End Enum
Public m_SetLogLev As LOG_GRADE
Public m_SetDisplayLev As LOG_GRADE
Public m_SetAppTitle As String
Public m_ListBox As ListBox
Public m_ChkSchroll As LunaCheck
Public m_chkRealtime As LunaCheck
Public m_LogPath As String
Public Sub ErrLog(errNum As String, errDesc As String, errPos As String)
Dim sMsg As String
Dim sDispMsg As String
Dim sVer As String
sVer = App.Major & "." & App.Minor & ".0." & App.Revision
sDispMsg = ""
sDispMsg = sDispMsg & " [" & Format(Now, "yyyy-mm-dd HH:mm:ss") & " {CRI}] :: "
sDispMsg = sDispMsg & "(RUNTIME " & errNum & ") " & errDesc & " {" & errPos & "}" & vbCrLf
sDispMsg = sDispMsg & "" & vbCrLf
sMsg = sVer & sDispMsg
If m_LogPath = "" Then
m_LogPath = App.Path & "\Log"
End If
IsBeingDir m_LogPath
FileSave m_LogPath, m_SetAppTitle & "_" & Format(Now, "yyyy-mm-dd") & ".txt", sMsg & vbCrLf
If m_ListBox Is Nothing Then
Else
If m_chkRealtime Is Nothing Then
m_ListBox.AddItem sDispMsg
Else
If m_chkRealtime.Value = True Then
m_ListBox.AddItem sDispMsg
End If
End If
If m_ChkSchroll Is Nothing Then
m_ListBox.ListIndex = m_ListBox.ListCount - 1
Else
If m_ChkSchroll.Value = True Then
m_ListBox.ListIndex = m_ListBox.ListCount - 1
End If
End If
End If
End Sub
Public Sub AddLog(str As String, Optional bLstAdd As Boolean = True, Optional ErrLev As DISPLAY_ERROR_GRADE = COMMON_MSG, Optional ErrCD As String, Optional sPos As String, Optional bTimeStr As Boolean = True)
Dim sMsg As String
Dim sDispMsg As String
Dim sLev As String
Dim sVer As String
Select Case ErrLev
Case COMMON_MSG
sLev = "COM"
Case MIN_ERROR
sLev = "MIN"
Case MAJ_ERROR
sLev = "MAJ"
Case CRI_ERROR
sLev = "CRI"
Case DEBUG_LOG
sLev = "DBG"
End Select
sVer = App.Major & "." & App.Minor & ".0." & App.Revision
If bTimeStr = True Then
sMsg = sVer & " [" & Format(Now, "yyyy-mm-dd HH:mm:ss") & " {" & sLev & "}] :: " & IIf(ErrCD = "", " ", " (" & ErrCD & ") ") & str
sDispMsg = "[" & Format(Now, "yyyy-mm-dd HH:mm:ss") & "] :: " & IIf(ErrCD = "", " ", " (" & ErrCD & ") ") & str & " {" & sLev & "}"
Else
sMsg = str
sDispMsg = str
End If
If m_ListBox Is Nothing Then
Else
If bLstAdd = True Then
If m_SetDisplayLev = COMMON_MSG Then
Select Case ErrLev
Case DEBUG_LOG, MIN_ERROR, MAJ_ERROR, CRI_ERROR
GoTo LogFileSave
End Select
ElseIf m_SetLogLev = MIN_ERROR Then
Select Case ErrLev
Case DEBUG_LOG
GoTo LogFileSave
End Select
End If
If m_ListBox.ListCount >= 1000 Then
m_ListBox.RemoveItem 0
End If
If m_chkRealtime Is Nothing Then
m_ListBox.AddItem sDispMsg
Else
If m_chkRealtime.Value = True Then
m_ListBox.AddItem sDispMsg
End If
End If
If m_ChkSchroll Is Nothing Then
m_ListBox.ListIndex = m_ListBox.ListCount - 1
Else
If m_ChkSchroll.Value = False Then
m_ListBox.ListIndex = m_ListBox.ListCount - 1
End If
End If
End If
End If
LogFileSave:
If m_SetLogLev = COMMON_MSG Then
Select Case ErrLev
Case DEBUG_LOG, MIN_ERROR, MAJ_ERROR, CRI_ERROR
Exit Sub
End Select
ElseIf m_SetLogLev = MIN_ERROR Then
Select Case ErrLev
Case DEBUG_LOG
Exit Sub
End Select
End If
FileSave m_LogPath, m_SetAppTitle & "_" & Format(Now, "yyyy-mm-dd") & ".txt", sMsg & vbCrLf
End Sub
Private Function FileSave(sFilePath As String, sFileName As String, sMessage As String, Optional bIsBeingDel As Boolean = False) As Boolean
'-------------------------------------------------------------------------------
' Function FileSave([파일이름을 제외한 경로], [파일이름], [저장할 문자열], [파일이 있으면 지우는 옵션])
' 설 명: 하나의 레코드씩 저장하는 함수.
' 리턴값: 성공여부 Y, N
'-------------------------------------------------------------------------------
On Error GoTo err
Dim lOutputFNum As Long, sOutputFileName As String
Call IsBeingDir(sFilePath)
sFileName = Replace(sFileName, ":", "_")
If Right(sFilePath, 1) = "\" Then
sOutputFileName = sFilePath & sFileName
Else
sOutputFileName = sFilePath & "\" & sFileName
End If
lOutputFNum = FreeFile
If bIsBeingDel = False And Dir(sOutputFileName) <> "" Then
Open sOutputFileName For Append As #lOutputFNum
Else
Open sOutputFileName For Output As #lOutputFNum
End If
Print #lOutputFNum, sMessage;
Close lOutputFNum
Exit Function
err:
'RaiseEvent ErrLog(err.Number, err.Description, "FileSave")
err.Clear
End Function
Private Function IsBeingDir(sDirPath As String, Optional bCreate As Boolean = True) As Boolean
'-------------------------------------------------------------------------------
' Function IsBeingDir([폴더경로], [없을경우 생성하고 True반환])
' 설 명: 폴더가 있는지 체크하고 옵션에 따라 없으면 하위폴더(OS가 지원하는한)까지 생성한다.
' 리턴값: Y/N
'-------------------------------------------------------------------------------
On Error GoTo err
Dim asFolderCount() As String
Dim sSplitDir As String
Dim iIndex As Integer
If Dir(sDirPath, vbDirectory) <> "" Then
IsBeingDir = True
Exit Function
End If
asFolderCount = Split(sDirPath, "\")
sSplitDir = asFolderCount(0)
For iIndex = 1 To UBound(asFolderCount)
sSplitDir = sSplitDir & "\" & asFolderCount(iIndex)
If Dir(sSplitDir, vbDirectory) = "" Then
If bCreate = False Then Exit Function
MkDir sSplitDir
End If
Next
IsBeingDir = True
Exit Function
err:
IsBeingDir = False
Debug.Print "CODE ERROR! = {IsBeingDir()}"
err.Clear
End Function