유저가 자유롭게 커스터마이징 가능한, 멀티 쓰레딩 로깅 라이브러리를 개발했다. 예전부터 로거가 필요하면 그때그때 작성해서 사용했는데 이럼 중복 코드도 많아지고 다른 프로젝트에서 짠 로거랑 호환이 안되는 등 여러가지 문제들이 많아서 각 잡고 제대로 만들어 보았다.
valgrind
통과 valgrind
결과는 에러 없이 완벽하게 통과한다. 사실 몇 가지 Exception Handling
이 부족한 상태이지만, 유저가 API 를 정상적으로 사용한다면 발생할 일이 없기 때문에 나중에 구현할 예정이다.
필자가 만든 로깅 라이브러리는 다음의 기능을 지원한다.
Atomicity
하게 동작.FILE *
를 인자로 받아 설정이 가능.logger_create()
Logger logger_create(void);
로거를 생성해주는 함수. 실패 시 NULL
반환
logger_destroy()
void logger_destroy(Logger );
logger_create()
를 통해 생성된 Logger
를 소멸시키는 함수.
logger_define_level()
bool logger_define_level(Logger, int level, char *name, FILE *fp);
로거의 레벨을 정의하는 함수. 이를 통해 로거의 레벨, 이름, 그리고 출력 방식을 지정할 수 있다.
logger_set_format()
bool logger_set_format(Logger , int level, char *format);
로거 레벨에 따른 출력 형식을 지정할 수 있다. 출력 형식으로 사용 가능한 placeholder
는 다음과 같다:
place holoder | 결과 |
---|---|
%f | 함수의 이름 |
%n | 파일 이름 |
%l | 라인 넘버 |
%s | 출력할 문자열 |
%d | Locale 에 따른 로컬 날짜 |
%t | Locale 에 따른 로컬 타임 |
%p | 로거 레벨 명 |
"[%d %t][%n:%l:%f] (%p) %s\n"
log(... ,"user name: %s", mythos);
대충 위와 같이 출력을 시도하면 이하와 같이 출력된다:
[06/22/24 09:43:30][source/main.c:64:main] (info) user name: mythos
개행 문자는 mythos
뒤에 출력되어 자동으로 개행이 이뤄진다.
logger_log()
int logger_log(Logger , int level,
const char *file, const char *funciton, const char *line,
const char *formatted, ...
);
형태가 복잡하고 채워야 되는 인자가 많은데 매번 로그를 출력할 때마다 이를 다 지정하는 것은 번거롭기 때문에 매크로를 통해 축약형으로 호출할 수 있다:
#define log(LOGGER, LEVEL, FMT, ...)
로거, 레벨, 출력 문자만 지정해주면 된다. 여기에서 로그 레벨은 숫자로 지정할 수 있는데 숫자는 외우기도 불편하고 직관적으로 와닿지 않으므로 이하와 같이 매크로를 정의한 뒤
#define LOGGER_LEVEL_INFO 1
이하와 같이 출력하면 된다:
log(logger, INFO, "no problem."); // INFO 는 자동으로 LOGGER_LEVEL_INFO 로 expand 된다.