[C/C++] spdlog를 활용한 로깅

Alexandria·2024년 3월 4일
1

C lang

목록 보기
6/14
post-thumbnail

1. 환경

로그를 읽고 쓰기 편리한 라이브러리로 header only파일이라 include만 시켜주면 된다.

소스를 다운받자.

$ git clone https://github.com/gabime/spdlog.git

컴파일시 헤더를 포함시켜준다.

$ g++ main.cpp -I./spdlog/include/ -o main

2. 로깅

spdlog를 이용하여 파일에 로그를 남겨본다.

#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"

int main(void) {
    std::shared_ptr<spdlog::logger> Logger;
    Logger = spdlog::basic_logger_mt("HelloLogger", "./hello.log");
    Logger->critical("Hello world");
    return 0;
}

해당 소스를 컴파일 후 실행하면 hello.log라는 파일이 생성되고

내용을 확인해본다.

[2022-11-12 12:41:35.577] [HelloLogger] [critical] Hello world

로그 파일의 최대 크기 및 최대 백업 개수를 설정할 수 있는 로테이팅 설정을 해본다.

한 파일에 최대 200byte가 저장될 수 있으며 백업 수는 최대 2개로 설정해본다.

#include "spdlog/spdlog.h"
#include "spdlog/sinks/rotating_file_sink.h"

int main(void) {
    std::shared_ptr<spdlog::logger> RotatingLogger;
    size_t LogFileMaxSize = 200;
    size_t LogFileMaxCount = 2;
    RotatingLogger = spdlog::rotating_logger_mt("HelloLogger", "./hello.log", LogFileMaxSize, LogFileMaxCount);

    for(int idx = 0; idx < 10; idx ++) RotatingLogger->error("Hello World : {0}", idx);
    return 0;
}

소스를 컴파일 후 실행하면 총 3개의 파일이 생성된다.

로그 파일들의 사이즈를 확인해보자.

$ ls -al hello*
-rw-rw-r-- 1 user user 192 Nov 12 12:45 hello.1.log
-rw-rw-r-- 1 user user 192 Nov 12 12:45 hello.2.log
-rw-rw-r-- 1 user user 128 Nov 12 12:45 hello.log

로그 파일들의 내용을 확인해보면 "Hello World : 1"은 사라졌다.

hello.1.log와 hello.2.log는 3개의 로그가 들어가있다.

$ grep -r "Hello" ./hello*
./hello.1.log:[2022-11-12 12:45:26.995] [HelloLogger] [error] Hello World : 5
./hello.1.log:[2022-11-12 12:45:26.995] [HelloLogger] [error] Hello World : 6
./hello.1.log:[2022-11-12 12:45:26.995] [HelloLogger] [error] Hello World : 7
./hello.2.log:[2022-11-12 12:45:26.995] [HelloLogger] [error] Hello World : 2
./hello.2.log:[2022-11-12 12:45:26.995] [HelloLogger] [error] Hello World : 3
./hello.2.log:[2022-11-12 12:45:26.995] [HelloLogger] [error] Hello World : 4
./hello.log:[2022-11-12 12:45:26.995] [HelloLogger] [error] Hello World : 8
./hello.log:[2022-11-12 12:45:26.995] [HelloLogger] [error] Hello World : 9

별도의 파일로 로그를 관리하는 것이 아닌 syslog에 같이 로깅을 해본다.

#include "spdlog/spdlog.h"
#include "spdlog/sinks/syslog_sink.h"

int main(void) {
    std::shared_ptr<spdlog::logger> SysLogger;
    SysLogger = spdlog::syslog_logger_mt("syslog", "HelloLogger", LOG_PID);
    SysLogger->error("Hello World");
    return 0;
}

syslog를 확인해본다.

$ tail -n 100 /var/log/syslog | grep HelloLogger
Nov 12 12:56:23 dev HelloLogger[3216]: Hello World

3. 설정

최소 로그 레벨을 설정하고 해당 레벨 이상만 로깅해본다.

아래의 예에서는 info로 레벨을 설정하였으니, debug레벨의 로그는 기록되지 않는다.

#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"

int main(void) {
    std::shared_ptr<spdlog::logger> logger;
    logger = spdlog::basic_logger_mt("logger", "./hello.log");
    logger->set_level(spdlog::level::info);
    spdlog::flush_on(spdlog::level::info);

    logger->debug("hello world");
    logger->info("hello world");
    logger->warn("hello world");
    logger->error("hello world");
    logger->critical("hello world");
    return 0;
}

로그파일을 확인해보면 debug레벨은 기록이 안되어 있다.

[2022-11-12 13:01:04.561] [logger] [info] hello world
[2022-11-12 13:01:04.561] [logger] [warning] hello world
[2022-11-12 13:01:04.561] [logger] [error] hello world
[2022-11-12 13:01:04.561] [logger] [critical] hello world

로그 레벨은 다음과 같이 trace부터 critical순으로 높은 값을 가진다.

trace -> debug -> info -> warn -> error -> critical

다양한 포맷팅을 활용하여 메세지를 생성해본다.

#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"

int main(void) {
    std::shared_ptr<spdlog::logger> logger;
    logger = spdlog::basic_logger_mt("logger", "./hello.log");
    logger->set_level(spdlog::level::debug);
    spdlog::flush_on(spdlog::level::info);

    logger->debug("hello world");
    logger->info("{1} {0}", "hello", "world");
    logger->warn("float {:03.2f}", 3.989);
    logger->error("{:>7}", "hello world");
    logger->error("{:>7}", "hello");
    logger->critical("{:08d}", 10);
    logger->critical("{:03d}", 1011);
    return 0;
}

로그 파일의 내용을 확인해본다.

[2022-11-12 13:04:03.949] [logger] [debug] hello world
[2022-11-12 13:04:03.949] [logger] [info] world hello
[2022-11-12 13:04:03.950] [logger] [warning] float 3.99
[2022-11-12 13:04:03.950] [logger] [error] hello world
[2022-11-12 13:04:03.950] [logger] [error]   hello
[2022-11-12 13:04:03.950] [logger] [critical] 00000010
[2022-11-12 13:04:03.950] [logger] [critical] 1011

시간에 대한 포맷팅을 적용해본다.

#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"

int main(void) {
    std::shared_ptr<spdlog::logger> logger;
    logger = spdlog::basic_logger_mt("logger", "./hello.log");
    logger->set_level(spdlog::level::debug);
    spdlog::flush_on(spdlog::level::info);

    spdlog::set_pattern("[%Y-%m-%d %X.%e][%n][%l] %v");
    logger->error("hello");
    spdlog::set_pattern("[%Y-%B-%d (%A) %r %z][%n][%l] %v");
    logger->error("world");
    return 0;
}

로그 파일의 내용을 확인해본다.

[2022-11-12 13:06:22.754][logger][error] hello
[2022-November-12 (Saturday) 01:06:22 PM +00:00][logger][error] world

포맷 별 결과는 다음과 같다.

formatresult
%a,%AFri,Friday
%b,%BOct,October
%c,%CFri Oct 22 14:35:59 2021,21
%d,%D22,10/22/21
%e,%E963,1634880959
%f,%F963224,963224959
%h,%HOct,14
%i,%I17,02
%l,%Lerror,E
%m,%M10,35
%nFormattingLoggerName
%o,%O0,0
%p,%PPM,63959
%r,%R02:35:59 PM,14:35
%S59
%t,%T63959,14:35:59
%u17106
%vworld
%x,%X10/22/21,14:35:59
%Y2021
%z+09:00

byte형 데이터를 hex표현해본다.

#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/fmt/bin_to_hex.h"

int main(void) {
    std::shared_ptr<spdlog::logger> logger;
    logger = spdlog::basic_logger_mt("logger", "./hello.log");
    
    unsigned char data[3] = {0xa5, 0xde, 0x66};
    logger->error("bin to hex : {:xsn}", spdlog::to_hex(std::begin(data), std::begin(data) + sizeof(data)));
    return 0;
}

로그파일의 내용을 확인해보자.

[2022-11-12 13:08:18.218] [logger] [error] bin to hex : a5de66

포맷 별 결과는 다음과 같다.

예시에서 쓴 xsn은 소문자형태(x)와 구분자를 없애며(s) 위치(0000)와 개행(\n)을 제거(n)한 조합이다.

formatresult
%x"\n0000: a5 de 66"
%s"\n0000: a5de66"
%p"\na5 de 66"
%n" a5 de 66"
%a"0000: a5 de 66 ..f"
%X"0000: A5 DE 66"
profile
IT 도서관

0개의 댓글

관련 채용 정보