このページの内容

各ロガーは、1個以上の std::shared_ptr<spdlog::sink> を格納したvectorを持ちます。

ログ呼び出しのたびに、ログレベルが条件を満たしていれば、ロガーはそれぞれの sink(log_msg) 関数を呼び出します。

spdlogのsinkは、スレッドセーフかどうかを示すため、_mt(マルチスレッド)または _st(シングルスレッド)の接尾辞を持ちます。シングルスレッドのsinkは複数のスレッドから同時に使用できませんが、ロックを行わないため、より高速になる場合があります。

ファクトリ関数を使ったロガーの作成

//Create and return a shared_ptr to a multithreaded console logger.
#include "spdlog/sinks/stdout_color_sinks.h"
auto console = spdlog::stdout_color_mt("some_unique_name");

このコードはコンソールロガーを作成し、"some_unique_name"をIDとしてspdlogのグローバルレジストリに登録し、shared_ptrとして返します。

spdlog::get("...")を使ったロガーへのアクセス

スレッドセーフな spdlog::get("logger_name") を使うと、どこからでもロガーへアクセスできます。共有ポインターを返します。

注意: spdlog::get はmutexをロックするため、コードを遅くする可能性があります。注意して使用してください。少なくとも頻繁に実行されるコード経路では、返された shared_ptr<spdlog::logger> を保存して直接使うことを推奨します。

コンストラクターで設定する、shared_ptr<spdlog::logger> 型のprivateメンバーを持たせる方法が有効です。

class MyClass
{
private:
   std::shared_ptr<spdlog::logger> _logger;
public:
   MyClass()
   {
     //set _logger to some existing logger
     _logger = spdlog::get("some_logger");
     //or create directly
     //_logger = spdlog::rotating_file_logger_mt("my_logger", ...);
   }
};

注意2: 手動で作成したロガー(直接構築するもの。下記のロガーの手動作成を参照)は自動登録されず、get("...") の呼び出しでは見つかりません。

そのようなロガーを登録するには、register_logger(...) 関数を使います。

spdlog::register_logger(my_logger);
...
auto the_same_logger = spdlog::get("mylogger");

ローテーションするファイルロガーの作成

//Create rotating file multi-threaded logger
#include "spdlog/sinks/rotating_file_sink.h"
auto file_logger = spdlog::rotating_logger_mt("file_logger", "logs/mylogfile", 1048576 * 5, 3);
...
auto same_logger= spdlog::get("file_logger");

非同期ロガーの作成

#include "spdlog/async.h"
void async_example()
{
    // default thread pool settings can be modified *before* creating the async logger:
    // spdlog::init_thread_pool(8192, 1); // queue with 8k items and 1 backing thread.
    auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
    // alternatively:
    // auto async_file = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("async_file_logger", "logs/async_log.txt");
   
}

非同期ログでは、spdlogは専用のメッセージキューを持つ、共有のグローバルスレッドプールを使います。

そのために、メッセージキュー内に固定数の事前割り当て済みスロットを作成します(64ビット環境で1スロット約256バイト)。この設定は spdlog::init_thread_pool(queue_size, backing_threads_count) で変更できます。

メッセージを記録しようとしたときにキューが満杯であれば、呼び出し元は空きスロットができるまでブロックします(デフォルトの動作)。または、ロガーを async_overflow_policy==overrun_oldest で構築した場合、キュー内の最も古いメッセージを新しいメッセージで即座に上書きします。

ロガーの手動作成

auto sink = std::make_shared<spdlog::sinks::stdout_sink_mt>();
auto my_logger = std::make_shared<spdlog::logger>("mylogger", sink);

// Optionally register the logger.  This is only needed if you want to access it with spdlog::get("mylogger")
spdlog::register_logger(my_logger);

[!NOTE] ファクトリ関数は内部で、ログレベルなどのグローバルな状態をロガーに設定します。 手動で作成したロガーには、グローバルな状態は設定されません。 ロガーにグローバルな状態を設定したい場合は、spdlog::initialize_logger() を呼び出してください。

複数のsinkを持つロガーの作成

std::vector<spdlog::sink_ptr> sinks;
sinks.push_back(std::make_shared<spdlog::sinks::stdout_sink_st>());
sinks.push_back(std::make_shared<spdlog::sinks::daily_file_sink_st>("logfile", 23, 59));
auto combined_logger = std::make_shared<spdlog::logger>("name", begin(sinks), end(sinks));
//register it if you need to access it globally
spdlog::register_logger(combined_logger);

同じ出力ファイルを使う複数のファイルロガーの作成

異なるロガーから同じ出力ファイルへ書き込みたい場合、すべてのロガーで同じsinkを共有する必要があります。そうしなければ、予期しない結果になる可能性があります。

auto sharedFileSink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("fileName.txt");
auto firstLogger = std::make_shared<spdlog::logger>("firstLoggerName", sharedFileSink);
auto secondLogger = std::make_unique<spdlog::logger>("secondLoggerName", sharedFileSink);