= Overview =
Logging 체계는 현재 프로젝트의 초기 개발 단계에서 검토가 되었어야 하나, 검토가 이루어지지 않은 채로 와서 지금까지 계속되어 온 상태이다. 어쨌든 프로젝트를 이어 받은 내 입장에서는 로깅 체계를 만드는게 필요했다.
일단 로깅은 내 생각으로는 크게 다음의 세 가지로 나누어진다.
# 디버깅을 위한 Console Logging
# Major한 Event를 위한 System Level Logging
# 사용자에게 보여주기 위한 User Level Logging
그러나 현재 프로젝트에서는 Console Logging과 User Level Logging 만이 존재하며, 그나마도 두 가지는 분리되어 있는 상태이다. System Level Logging이 없는 상태라, 뭐가 잘못돼어가는지 알 수 없는 상태다.
어쨌든 세 가지는 통합되어야 가장 효율적이며 이에 따라서 일단 Console Logging과 System Level Logging에 대한 처리를 하기 위한 로깅 라이브러리를 검토하였다. User Level Logging은 현재 DB로 되어 있는 상태라 통합하지 않고, Console과 System Level Logging이 완료되면 이전할 생각이다.
* [wiki:S3_Logging_Survey 로깅 라이브러리에 대한 검토 및 예제]
향후에는 세 가지가 모두 같은 체계를 통해서 Logging이 이루어질 것이다.
= Logging 체계 =
앞에서 말한 세 가지 형태의 분류에 따르면, Console Logging은 스크린 또는 파일로 기록이 되어야 하며, System Level Logging은 파일 또는 Syslog가 적당하다.
Media Server에서는 기본적으로 SysLog가 System Level Logging에 쓰이며, Screen이 User Level Logging에 쓰일 것이다. 다만 Release되는 실행 파일의 경우에는 System Level Logging만 활성화될 것이다.
== Logging 체계 ==
* Prioirity : CRIT 이상만 Syslog를 통해서 출력
* Facility : Syslog를 통해서 출력할 경우 LOCAL2를 통해서 출력
=== Log4cpp Priority ===
Log4cpp의 Loggin 우선 순위는 아래와 같이 정해져 있다. 이 중 ALERT 이상만 SysLog로 보내어지게 설정될 것이다. 그리고 그 외는 일단
{{{
typedef enum {EMERG = 0,
FATAL = 0,
ALERT = 100,
CRIT = 200,
ERROR = 300,
WARN = 400,
NOTICE = 500,
INFO = 600,
DEBUG = 700,
NOTSET = 800
} PriorityLevel;
}}}
== Log4CPP Configuration File ==
앞의 원칙에 따라서 미디어 서버에서 사용될 log.cfg 라는 파일의 샘플이다. Release 할 때 사용될 파일은 모든 Logging이 꺼져 있고, 아주 높은 Priority만 SysLog로 보내지는 예가 될 것이다.
디버깅이 필요할 시에는 주석 처리된 부분을 풀면 File이나 Console로 보내어지고, rootCategory의 Priority를 수정하면 될 것이다.
실제 지원되는 문법에 대해서는 PropertyConfigurator를 직접 보는 수 밖에 없다.
{{{
log4j.rootCategory=CRIT, basic_syslogger
#log4j.rootCategory=INFO, basic_syslogger, fileAppender,console_a
log4j.appender.basic_syslogger=org.apache.log4j.LocalSyslogAppender
log4j.appender.basic_syslogger.threshold=CRIT
log4j.appender.basic_syslogger.facility=LOCAL2
log4j.appender.basic_syslogger.layout=org.apache.log4j.BasicLayout
#log4j.appender.fileAppender=org.apache.log4j.FileAppender
#log4j.appender.fileAppender.fileName=/tmp/A1.log
#log4j.appender.fileAppender.layout=org.apache.log4j.BasicLayout
#log4j.appender.basic_syslogger=org.apache.log4j.LocalSyslogAppender
#log4j.appender.basic_syslogger.facility=LOCAL2
#log4j.appender.basic_syslogger.layout=org.apache.log4j.BasicLayout
#log4j.appender.console_a=org.apache.log4j.ConsoleAppender
#log4j.appender.console_a.layout=org.apache.log4j.BasicLayout
}}}
= Implementation =
== 라이브러리 설치 ==
개발 서버에 일단 필요한 라이브러리를 모두 설치하였다. 크로스 컴파일 환경이라면 별도의 설치 위치가 있어야 하나, 두 개의 환경이 동일하므로 그냥 설치하였다.
미디어 서버 상에는 /mnt/dom/work/lib 에 항상 동적 라이브러리가 설치되어 있는 것으로 가정한다.
== configuration file 생성 ==
실행 파일과 같은 디렉토리에 위의 예제와 같은 파일을 생성해준다.
== logging 체계의 초기화 ==
Exception을 Catch하는 부분에서 필요한 초기화를 더 해주어야 한다. 예를 들면, 자기가 선호하는 기본 Appender와 Layout은 제공해주어야 할 것이다.
{{{
int init_log_system(void)
{
/// Step 1 : If the configuration is exist, use that.
/// Else, set root priority to Crit
try {
log4cpp::PropertyConfigurator::configure("log.cfg");
}
catch (log4cpp::ConfigureFailure e) {
log4cpp::Category::setRootPriority(log4cpp::Priority::CRIT);
}
return 0 ;
}
}}}
== 실제 Logging ==
로깅할 Object Instance를 얻기 위해서는 log4cpp::Category::getInstance("Camera")를 사용한다. 이 함수는 Reference를 돌려주며, 이름이 동일할 경우 다시 Object를 생성하지 않고, 그 Instance를 돌려준다.
클래스 멤버로는 다음과 같이 사용하였다.
{{{
Constructor
{
log4cpp::Category & m_logger ;
}
Constructor::Constructor(int x) : m_logger( log4cpp::Category::getInstance("Camera") )
{
m_logger.notice("Con is created");
}
}}}
클래스 멤버가 아닌 즉각적인 사용이 필요할 경우는
{{{
log4cpp::Category &logger = log4cpp::Category::getInstance("Camera") ;
logger.notice("Instant notice");
}}}
= Reference =
* log4cpp
* [http://log4cpp.sourceforge.net/ log4cpp Homepage]
* [http://joysofprogramming.com/log4cpp-tutorial/ Tutorial]
WRITTEN BY
- HanDDol
여행이란 건 말이지. 첫 걸음을 내딜 때는 모든 게 낯설고.. 그리고 점점 더 낯선 세상에 익숙해지면서 세상의 모든 곳이 고향처럼 느껴진다. 고향으로 돌아오는 여행의 마지막 걸음에는 나의 고향이 더 이상 익숙한 곳이 아닌 낯선 곳임을 알게 된다.
,