Introduction

C++ 用のロギングライブラリといえば

  • spdlog
  • log4cxx
  • boost log

等があるのですが、 spdlog が高速、ヘッダーオンリー、MIT ライセンスと使いやすいことこの上ないのですが、一つだけ欠点があります。
それが、「設定ファイルによる制御ができない」です。

例えば、log4cxx は log4j.xml といった設定ファイルでソースコードの変更なしにログレベルや出力先を制御できますが、 spdlog にはそのような機能はありません。

厳密には、コマンドラインの引数などを駆使すれば、制御できなくもないのですが、それはそれで面倒。

という欠点を解決したのが、

です。

toml ファイルによって、ログを制御できます。

spdlog も含めた、自動ビルドによる、spdlog_setup のサンプルコードを下記に用意しました。

https://github.com/takuya-takeuchi/Demo/tree/master/Logging/spdlog/01_configuration_by_toml

How to use

基本、上のサンプルの Build.ps1 を叩き、 Demog.exe を実行するだけなのですが、それだけではあれなので。

サンプルのソースは下記です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Demo.cpp : このファイルには 'main' 関数が含まれています。プログラム実行の開始と終了がそこで行われます。
//

#include <iostream>

// It occurs compile error
//#define SPDLOG_WCHAR_FILENAMES
// enable std::wstring
#define SPDLOG_WCHAR_TO_UTF8_SUPPORT
#include <spdlog_setup/conf.h>

int main()
{
try
{
// Consoled can not output as UTF-8 if comment out it
SetConsoleOutputCP(CP_UTF8);

// spdlog_setup::setup_error thrown if file not found
spdlog_setup::from_file("logging.toml");

// setup logger
auto logger = spdlog::get("root");

logger->info(L"Hello World!");
}
catch (const spdlog_setup::setup_error& e)
{
std::cout << e.what() << std::endl;
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
}
}

特に難しい点もありません。

設定ファイルを spdlog_setup::from_file で読み込み、設定ファイルに記載された設定を spdlog::get でメモリに展開するだけです。

logger 変数が std::shard_ptr<spdlog::logger> になっているくらいが、注意点です。

また、設定ファイルは下記です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# max_size supports suffix
# - T (terabyte)
# - G (gigabyte)
# - M (megabyte)
# - K (kilobyte)
# - or simply no suffix (byte)

[[sink]]
name = "console"
type = "color_stdout_sink_mt"
level = "info"

[[sink]]
name = "rotate_out"
type = "rotating_file_sink_mt"
base_filename = "logs/application.log"
max_size = "1M"
max_files = 10
level = "info"
# optional flag to indicate the set - up to create the log dir first
create_parent_dir = true

[[logger]]
name = "root"
sinks = ["console", "rotate_out"]
level = "info"

spdlog でお馴染みのワードが出てきますが、 sinks に複数の sink を指定することで、ログを複数の出力際に吐き出せます。

上記は標準出力とログファイルに出力しています。

Watch out!

spdlog も spdlog_setup も割とモダンな実装なのですが、どういうわけか Visual Studio の言語設定で ISO C++ 20 標準 (/std:c++20) を有効にして、 spdlog_setup をリンクしてビルドするとエラーになってしまいます。

ISO C++ 17 標準 (/std:c++17) または ISO C++ 14 標準 (/std:c++14) であれば問題ありません。

一応、issue として C++ 20 compilation problem が上がっていますが、こちらで遭遇した現象とは違う気がします。

が、放置されているところを見ると的を得ていないのかもしれません。

Source Code

https://github.com/takuya-takeuchi/Demo/tree/master/Logging/spdlog/01_configuration_by_toml