【C++】Spdlog日志库
一、Spdlog介绍
参考文献:
- Github: https://github.com/gabime/spdlog
- https://blog.csdn.net/tutou_gou/article/details/121284474
二、 日志封装
#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <time.h>
#include <chrono>
#include <assert.h>
#include "spdlog/spdlog.h"
#include "spdlog/async.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"#ifndef LOG_LEVEL
#define LOG_LEVEL "info"
#endif#define LOG_DIR "./log"#ifndef LOG_DIR
#define LOG_CONSOLE true
#else
#define LOG_CONSOLE false
#endifstatic inline int NowDateToInt()
{time_t now;time(&now);tm p;
#ifdef _WIN32localtime_s(&p, &now);
#elselocaltime_r(&now, &p);
#endifint now_date = (1900 + p.tm_year) * 10000 + (p.tm_mon + 1) * 100 + p.tm_mday;return now_date;
}static inline int NowTimeToInt()
{time_t now;time(&now);tm p;
#ifdef _WIN32localtime_s(&p, &now);
#elselocaltime_r(&now, &p);
#endifint now_int = p.tm_hour * 10000 + p.tm_min * 100 + p.tm_sec;return now_int;
}class XLogger
{public:static XLogger* getInstance(){static XLogger xlogger;return &xlogger;}std::shared_ptr<spdlog::logger> getLogger(){return m_logger;}private:// make constructor private to avoid outside instanceXLogger(){// hardcode log pathconst std::string log_dir = LOG_DIR;const std::string logger_name_prefix = "tvcore_";// decide print to console or log filebool console = LOG_CONSOLE;// decide the log levelstd::string level = LOG_LEVEL;try{int date = NowDateToInt();int time = NowTimeToInt();const std::string logger_name = logger_name_prefix + std::to_string(date) + "_" + std::to_string(time);if (console)m_logger = spdlog::stdout_color_st(logger_name); // single thread console output fasterelsem_logger = spdlog::create_async<spdlog::sinks::rotating_file_sink_mt>(logger_name,log_dir + "/" + logger_name + ".log", 100 * 1024 * 1024, 10); // 10 * 100M// custom formatm_logger->set_pattern("%Y-%m-%d %H:%M:%S.%f <thread %t> [%l] [%@] %v");if (level == "debug"){m_logger->set_level(spdlog::level::debug);m_logger->flush_on(spdlog::level::debug);}else if (level == "info"){m_logger->set_level(spdlog::level::info);m_logger->flush_on(spdlog::level::info);}else if (level == "warn"){m_logger->set_level(spdlog::level::warn);m_logger->flush_on(spdlog::level::warn);}else if (level == "error"){m_logger->set_level(spdlog::level::err);m_logger->flush_on(spdlog::level::err);}else if (level == "off"){m_logger->set_level(spdlog::level::off);m_logger->flush_on(spdlog::level::off);}}catch (const spdlog::spdlog_ex& ex){std::cout << "Log initialization failed: " << ex.what() << std::endl;}}~XLogger(){spdlog::drop_all(); // must do this}XLogger(const XLogger&) = delete;XLogger& operator=(const XLogger&) = delete;private:std::shared_ptr<spdlog::logger> m_logger;
};// use embedded macro to support file and line number
#define LOG_DEBUG(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger().get(), spdlog::level::debug, __VA_ARGS__)
#define LOG_INFO(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger().get(), spdlog::level::info, __VA_ARGS__)
#define LOG_WARN(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger().get(), spdlog::level::warn, __VA_ARGS__)
#define LOG_ERROR(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger().get(), spdlog::level::err, __VA_ARGS__)#define DBG_ASSERT(x) do {\\if (!(x)) {\\LOG_ERROR("Assert Error!");\\}\\} while(0)
1. 终端日志
m_logger = spdlog::stdout_color_st(logger_name); // single thread console output faster
2. 单一文件日志
auto my_logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
basic log 日志文件会一直被写入,不断变大。使用较少。
- mt 多线程异步,速度慢一点
- st 单线程,速度较快
3. 循环日志文件
- 当日志条数在一个文件中足够大时,必须分割为多个文件
- 保证日志文件的数量不会无限增长
auto file_logger = spdlog::rotating_logger_mt("file_logger", "myfilename", 1024 * 1024 * 5, 10);
- 日志产生者的名字,自定义即可
- 日志文件路径
- 单一日志文件的最大值。超过则会产生新的文件。第三个参数指定,如上面指定的5M
- 保留文件数量,超过数量的文件会直接删除以节省空间。
4. daily log
每天会新建一个日志文件,新建日志文件的时间可以自己设定
auto daily_logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
- 每天 2点 30会创建新文件。
5. 异步文件日志
auto file_logger = spdlog::rotating_logger_mt<spdlog::async_factory>("file_logger", "mylogs", 1024 * 1024 * 5, 100);
- 在初始化的时候使用异步工厂 spdlog::async_factory 即可。