VB6 로그 프레임웍

gisman

Java에서 많이 사용하는 Log4J 라는 로깅 프레임웍이 있다.

VB에서 로그 남기기 위해 만든 클래스가 있는데, 어느날 보니 Log4J와 기능과 구조가 비슷하다.

제대로 손 좀 봐서 Log4VB 라고 이름 붙여도 되겠다.

목차

VB에서 사용하는 로그용 클래스의 핵심 함수

Public Sub PrintOut(s As String, Optional nLevel As Long = 0)
    If nLevel > m_nLogLevel Then Exit Sub
 
    Dim sLog As String
    sLog = String(nLevel, vbTab) & Replace(s, vbCrLf, vbCrLf & String(nLevel, vbTab))
 
    Select Case m_LogTo
    Case LOGTO_DEBUGPRINT
        Debug.Print sLog
    Case LOGTO_FILE
        Print #m_FileNumber, sLog
    Case LOGTO_OUTPUTWINDOW
        m_OutPutWindow.PrintOut sLog
    End Select
End Sub


  • LOG 출력 위치
    • 파일로 남기거나,
    • OutputDebugstring API로 디버깅 메세지를 날리거나,
    • 화면으로 출력할 수 있다.

어디로 LOG를 날릴지는 클래스의 프로퍼티로 지정할 수 있다.

로그 레벨

로그를 상세하게 찍다보면 양이 엄청 많아지면서 오히려 불편해진다. 이 문제를 해결하기 위해, [로그레벨]이라는 개념이 있다.

로그가 상세하면 상세할 수록 [로그레벨]의 숫자를 크게 지정한다.

로그를 실제로 찍는 코드를 보면

        oLog.PrintOut "출력시 표제목에 표시 붙이기:" & oTxt.TableTitleMark, 1
            oLog.PrintOut "첫 쪽 표시:" & oTxt.FirstPageMark, 2
            oLog.PrintOut "나머지 쪽 표시:" & oTxt.PageMark, 2
        oLog.PrintOut "쪽 번호 표시:" & oTxt.PageNo, 1

이런식으로 만들었다고 할 때

마지막 파라미터가 로그레벨이다.


만약 1레벨의 로그만 출력하고 싶다면 즉, 굵직굵직한 로그만 보고 싶다면,

로그 클래스의 출력레벨을 1로 설정한다.

그럼 로그레벨이 1보다 큰 로그는 출력을 안 한다.


위의 oLog.PrintOut 함수의 내부를 첫 줄만 들여다 보면 아래와 같이 되어 있다.

If nLevel > m_nLogLevel Then Exit Sub

이미 알고 있겠지만, 로그 레벨을 검사해서 출력하지 않고 빠져나가는 코드이다.


얼마나 상세하게 남길까?

로그를 얼마나 상세하게 남길것인가? 요것도 고민인데..

모든 코드에 다 로그를 달 수 는 없는 노릇이니 딱 필요한 부분에만 달아 놓고 싶은데 그게 어디인지 미리 점칠 수 없다는게 딜레마이다.


내가 쓰는 방법은 객체의 상태를 출력하는 로그 기능을 만드는 것이다.

"어디서" 에러가 발생했는지 찾는게 아니라, 에러가 발생할때의 모든 "객체의 상태"를 들여다 보는 것이다.

이렇게 하기 위해 모든 클래스에 DebugPrint(FILE* fp, int nLogDepth=99) 라는 멤버를 만든다.

이 멤버함수는 자기자신의 상태(멤버변수의 값 등)를 출력한다.

그리고 자기가 포함하고 있는 다른 객체가 있으면, 그 객체의 DebugPrint()를 모두 호출해준다.

그리고 자기의 슈퍼클래스의 DebugPrint()도 호출한다.

이렇게 하면 관련된 모든 객체들의 상태가 재귀적으로 출력된다.


포함 객체 출력 범위 제한

모든 객체를 출력하는 것이 너무 광범위한 일이라고 생각된다면, 포함 객체의 DebugPrint를 호출할 때 nLogDepth를 1씩 줄여서 호출하면 된다.

예를 들어보자. A 클래스가 B를 포함하고, B는 C를 포함하고 있다.

A.DebugPrint(fp, 2)라고 호출하면 이 함수에서

B.DebugPrint(fp, 1)을 호출한다. 그럼 B는

C.DebugPrint(fp, 0)을 호출한다,

C는 nLogDepth가 0이므로 이 호출을 무시하고 로그를 안 찍고 바로 리턴하도록 한다.

C까지 다 출력해야한다면 A.DebugPrint(fp, 2) 대신 LogDepth를 2보다 큰 값으로 바꿔서 호출하면 된다.

이런 원리로 로그 레벨을 상속과 포함관계에도 출력 범위 제한기능을 사용할 수 있다.


정리하자면 VB에서 사용한 방법은 집중적으로 로그를 찍어야 하는 부분에서 중요도를 기준으로 필터링 하는 방법을 제시하는 것이고,

아래에 설명한 것은 모든 객체들에게 로그 출력 기능을 두고, 포함관계 또는 상속관계에 따라 연관 Depth로 제한을 가해서 출력하는 방법이다.


여러 프로젝트에서 꽤 효과를 본 검증된 방법이다.

소스코드가 꼭 필요한 분은 메일 보내시오.


함께 읽을만한 글

함께 읽을 꺼리

디버그 간단 설명

시작하는 학생에게 조언

로그파일을 이용한 디버그 팁

This pointer evaluate 하기

Watch Window Symbol Format

유용한 VC6 팁 : Alt+F10

Main() 의 return 0