spdlog
C++向けの超高速ロギングライブラリ。ヘッダーオンリーで依存関係なし、優秀なfmtライブラリを使用した豊富なフォーマット機能を提供。マルチスレッド対応、ローテーション・日次ログファイル、カラーコンソール出力、バックトレースサポートを搭載。
GitHub概要
スター26,769
ウォッチ444
フォーク4,838
作成日:2014年11月1日
言語:C++
ライセンス:Other
トピックス
cppcpp11header-onlyloggingspdlog
スター履歴
データ取得日時: 2025/7/17 08:20
ロギングライブラリ
spdlog
概要
spdlogは、C++向けの高速ロギングライブラリです。ヘッダーオンリーの設計により簡単に導入でき、非同期ロギングやマルチスレッド対応、豊富なシンク(出力先)の選択肢を提供します。fmt ライブラリを基盤とした強力なフォーマット機能と、パフォーマンスを重視した設計により、本格的なアプリケーションでの使用に適しています。
詳細
spdlogは2014年にGabriel Imeによって開発されたC++ロギングライブラリで、シンプルな統合と高性能を重視して設計されています。ヘッダーオンリーアプローチにより、別途ビルドする必要がなく、プロジェクトへの統合が非常に簡単です。
技術的特徴
- 高速非同期ロギング: バックグラウンドスレッドプールによる高速処理
- マルチシンクサポート: コンソール、ファイル、日次ローテーション、カスタムシンク等
- fmt統合: 現代的なフォーマット構文による型安全な出力
- スレッドセーフ: マルチスレッド環境での安全な並行利用
- カスタマイズ可能: フォーマッタ、コンバータ、カスタムフラグの拡張
- C++11対応: モダンC++機能の活用
アーキテクチャ
- Logger: 中央制御とシンク管理
- Sink: 出力先の抽象化(ファイル、コンソール、ネットワーク等)
- Formatter: ログメッセージの書式設定
- Thread Pool: 非同期ロギング用のワーカースレッド
メリット・デメリット
メリット
- 優れたパフォーマンス: 最速クラスのC++ロギングライブラリ
- ヘッダーオンリー: ビルド設定不要の簡単統合
- 豊富なシンクオプション: 多様な出力先への対応
- 型安全なフォーマット: fmtライブラリによる現代的な書式設定
- 柔軟な設定: プログラムまたは設定ファイルでの構成
- マルチプラットフォーム: Windows、Linux、macOS対応
- メモリ効率: 最適化されたメモリ使用量
デメリット
- ヘッダーサイズ: 大きなヘッダーファイルによるコンパイル時間増加
- fmtライブラリ依存: 外部依存関係(内蔵版もあり)
- 学習コスト: 高度な機能には設定の理解が必要
- デバッグ情報: 最適化により詳細なデバッグ情報が制限される場合あり
参考ページ
- 公式サイト: https://github.com/gabime/spdlog
- ドキュメント: https://spdlog.docsforge.com/
- fmt ライブラリ: https://fmt.dev/
- C++ Reference: https://en.cppreference.com/
- パフォーマンス比較: GitHub Issues内のベンチマーク結果
書き方の例
基本的な使用方法
#include "spdlog/spdlog.h"
int main() {
spdlog::info("spdlogへようこそ!");
spdlog::error("エラーメッセージ: {}", 404);
spdlog::warn("数値のパディング: {:08d}", 12);
spdlog::critical("整数: {0:d}; 16進: {0:x}; 8進: {0:o}; 2進: {0:b}", 42);
spdlog::info("浮動小数点: {:03.2f}", 1.23456);
spdlog::info("位置指定: {1} {0}", "です", "こんにちは");
// ログレベル設定
spdlog::set_level(spdlog::level::debug);
spdlog::debug("このメッセージが表示されます");
// パターン変更
spdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v");
return 0;
}
ファイルロギング
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
// 基本ファイルログ
void basic_file_logging() {
try {
auto logger = spdlog::basic_logger_mt("basic_logger", "logs/basic-log.txt");
logger->info("基本ファイルログメッセージ");
}
catch (const spdlog::spdlog_ex &ex) {
std::cout << "ログ初期化エラー: " << ex.what() << std::endl;
}
}
// ローテーションファイルログ
void rotating_file_logging() {
// 5MBサイズで最大3ファイルまでローテーション
auto max_size = 1048576 * 5;
auto max_files = 3;
auto logger = spdlog::rotating_logger_mt("rotating_logger", "logs/rotating.txt", max_size, max_files);
for (int i = 0; i < 10000; ++i) {
logger->info("ローテーションテストメッセージ {}", i);
}
}
// 日次ログ
void daily_logging() {
// 毎日2:30 AMに新しいファイルを作成
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
logger->info("日次ログメッセージ");
}
マルチシンクロガー
#include "spdlog/sinks/stdout_color_sinks.h"
void multi_sink_example() {
// コンソールシンク(警告以上)
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
console_sink->set_level(spdlog::level::warn);
console_sink->set_pattern("[multi_sink] [%^%l%$] %v");
// ファイルシンク(全てのレベル)
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/multisink.txt", true);
file_sink->set_level(spdlog::level::trace);
// マルチシンクロガー作成
spdlog::logger logger("multi_sink", {console_sink, file_sink});
logger.set_level(spdlog::level::debug);
logger.warn("コンソールとファイル両方に出力");
logger.info("ファイルのみに出力(コンソールには表示されない)");
}
非同期ロギング
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
void async_logging_example() {
// デフォルトのスレッドプール設定を変更(初期化前)
spdlog::init_thread_pool(8192, 1); // キューサイズ8K、バックグラウンドスレッド1個
// 非同期ファイルロガー作成
auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
// または別の書き方
// auto async_file = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("async_file_logger", "logs/async_log.txt");
for (int i = 0; i < 100; ++i) {
async_file->info("非同期ログメッセージ {}", i);
}
}
// 複数シンク非同期ロガー
void multi_sink_async_example() {
spdlog::init_thread_pool(8192, 1);
auto stdout_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("mylog.txt", 1024*1024*10, 3);
std::vector<spdlog::sink_ptr> sinks {stdout_sink, rotating_sink};
auto logger = std::make_shared<spdlog::async_logger>("async_multi", sinks.begin(), sinks.end(),
spdlog::thread_pool(), spdlog::async_overflow_policy::block);
spdlog::register_logger(logger);
logger->info("マルチシンク非同期ログ");
}
カスタムフォーマッタとバックトレース
#include "spdlog/stopwatch.h"
// カスタムフォーマッタフラグ
class my_formatter_flag : public spdlog::custom_flag_formatter {
public:
void format(const spdlog::details::log_msg &, const std::tm &, spdlog::memory_buf_t &dest) override {
std::string custom_text = "custom-flag";
dest.append(custom_text.data(), custom_text.data() + custom_text.size());
}
std::unique_ptr<custom_flag_formatter> clone() const override {
return spdlog::details::make_unique<my_formatter_flag>();
}
};
void custom_formatter_example() {
auto formatter = std::make_unique<spdlog::pattern_formatter>();
formatter->add_flag<my_formatter_flag>('*').set_pattern("[%n] [%*] [%^%l%$] %v");
spdlog::set_formatter(std::move(formatter));
spdlog::info("カスタムフラグ付きメッセージ");
}
// バックトレース機能
void backtrace_example() {
// 最新32メッセージをバッファに保存
spdlog::enable_backtrace(32);
for(int i = 0; i < 100; i++) {
spdlog::debug("バックトレースメッセージ {}", i); // まだログされない
}
// エラー発生時にダンプ
spdlog::dump_backtrace(); // 最新32メッセージを表示
}
// ストップウォッチ機能
void stopwatch_example() {
spdlog::stopwatch sw;
// 重い処理のシミュレーション
std::this_thread::sleep_for(std::chrono::milliseconds(100));
spdlog::debug("経過時間 {}", sw);
spdlog::debug("経過時間(3桁精度) {:.3}", sw);
}
高度な機能
#include "spdlog/sinks/callback_sink.h"
#include "spdlog/mdc.h"
// コールバックシンク
void callback_sink_example() {
auto callback_sink = std::make_shared<spdlog::sinks::callback_sink_mt>([](const spdlog::details::log_msg &msg) {
// エラー発生時にメール通知などの処理
if (msg.level >= spdlog::level::err) {
// アラート処理
std::cout << "アラート: 重要なエラーが発生しました!" << std::endl;
}
});
callback_sink->set_level(spdlog::level::err);
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
spdlog::logger logger("custom_callback_logger", {console_sink, callback_sink});
logger.info("通常の情報ログ");
logger.error("重要な問題"); // アラート通知される
}
// MDC(Mapped Diagnostic Context)
void mdc_example() {
spdlog::mdc::put("user_id", "12345");
spdlog::mdc::put("session_id", "abcdef");
// パターンに %& を含めてMDCデータを表示
spdlog::set_pattern("[%H:%M:%S] [%^%L%$] [%&] %v");
spdlog::info("ユーザー操作ログ");
spdlog::error("セッション関連エラー");
}
// 定期的なフラッシュ
void flush_example() {
// 全ての登録済みスレッドセーフロガーを3秒毎にフラッシュ
spdlog::flush_every(std::chrono::seconds(3));
// 手動フラッシュ
spdlog::info("重要なメッセージ");
spdlog::get("default")->flush(); // 即座にフラッシュ
}
// エラーハンドラー
void error_handler_example() {
spdlog::set_error_handler([](const std::string &msg) {
spdlog::get("console")->error("*** ロガーエラー ***: {}", msg);
});
// 意図的にエラーを発生
spdlog::get("console")->info("無効なメッセージでエラー発生 {}{}{}{}", 3);
}