因项目需要导入日志系统,所以需要对SPDLOG进行评测,具体的github地址:
https://github.com/gabime/spdlog
提示:这里可以添加本文要记录的大概内容:
SPDLOG是一个快速的,并且只需要头文件编译的十分好用的日志系统,
具备以下特性
十分快速
仅仅需要头文件被编译
丰富的格式, 使用fmt库
异步模式 (可选)
定制化格式
单/多线程日志
多种日志功能:
日志分割;
每日日志文件
控制台日志输出(支持不同颜色)
系统日志
Windows事件记录
Windows调试器
容易扩展至自定义的log系统
日志筛选 - 日志级别可以在运行中和编译中进行更改
支持Backtrace - 可以将消息存储在环形缓冲中,并后续根据需要显示
同步模式
[info] **************************************************************
[info] Single thread, 1,000,000 iterations
[info] **************************************************************
[info] basic_st Elapsed: 0.17 secs 5,777,626/sec
[info] rotating_st Elapsed: 0.18 secs 5,475,894/sec
[info] daily_st Elapsed: 0.20 secs 5,062,659/sec
[info] empty_logger Elapsed: 0.07 secs 14,127,300/sec
[info] **************************************************************
[info] C-string (400 bytes). Single thread, 1,000,000 iterations
[info] **************************************************************
[info] basic_st Elapsed: 0.41 secs 2,412,483/sec
[info] rotating_st Elapsed: 0.72 secs 1,389,196/sec
[info] daily_st Elapsed: 0.42 secs 2,393,298/sec
[info] null_st Elapsed: 0.04 secs 27,446,957/sec
[info] **************************************************************
[info] 10 threads, competing over the same logger object, 1,000,000 iterations
[info] **************************************************************
[info] basic_mt Elapsed: 0.60 secs 1,659,613/sec
[info] rotating_mt Elapsed: 0.62 secs 1,612,493/sec
[info] daily_mt Elapsed: 0.61 secs 1,638,305/sec
[info] null_mt Elapsed: 0.16 secs 6,272,758/sec
异步模式
[info] -------------------------------------------------
[info] Messages : 1,000,000
[info] Threads : 10
[info] Queue : 8,192 slots
[info] Queue memory : 8,192 x 272 = 2,176 KB
[info] -------------------------------------------------
[info]
[info] *********************************
[info] Queue Overflow Policy: block
[info] *********************************
[info] Elapsed: 1.70784 secs 585,535/sec
[info] Elapsed: 1.69805 secs 588,910/sec
[info] Elapsed: 1.7026 secs 587,337/sec
[info]
[info] *********************************
[info] Queue Overflow Policy: overrun
[info] *********************************
[info] Elapsed: 0.372816 secs 2,682,285/sec
[info] Elapsed: 0.379758 secs 2,633,255/sec
[info] Elapsed: 0.373532 secs 2,677,147/sec
spdlog集成进自己的项目十分方便,具体如下:
#include "spdlog/spdlog.h"
int main()
{
//Use the default logger (stdout, multi-threaded, colored)
spdlog::info("Hello, {}!", "World");
}
spdlog是一个头文件库,如果想使用,需要将include文件下的文件复制到项目中,并使用C++11编译器
库提供了一个类似phython形式的API,API使用fmt库
logger->info("Hello {} {} !!", "param1", 123.4);
spdlog使用了类似于"需要什么就include什么"的方式,工程代码中只需要include那些你需要的功能
例如:
如果你需要日志分割功能,只需要include"spdlog/sinks/rotating_file_sink.h"
如果你需要异步记录功能,需要include"spdlog/async.h"
提供一个基本范例,使用方法
#include <iostream>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h" // support for basic file logging
#include "spdlog/sinks/rotating_file_sink.h" // support for rotating file logging
int main(int, char* [])
{
try
{
// Create basic file logger (not rotated)
auto my_logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
// create a file rotating logger with 5mb size max and 3 rotated files
auto file_logger = spdlog::rotating_logger_mt("file_logger", "myfilename", 1024 * 1024 * 5, 3);
}
catch (const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
使用工厂模式-生成异步记录
#include <iostream>
#include "spdlog/spdlog.h"
#include "spdlog/async.h" //support for async logging.
#include "spdlog/sinks/basic_file_sink.h"
int main(int, char* [])
{
try
{
auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
for (int i = 1; i < 101; ++i)
{
async_file->info("Async message #{}", i);
}
// Under VisualStudio, this must be called before main finishes to workaround a known VS issue
spdlog::drop_all();
}
catch (const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
生成异步日志文件并改变线程池设置
#include "spdlog/async.h" //support for async logging
#include "spdlog/sinks/daily_file_sink.h"
int main(int, char* [])
{
try
{
auto daily_sink = std::make_shared<spdlog::sinks::daily_file_sink_mt>("logfile", 23, 59);
// default thread pool settings can be modified *before* creating the async logger:
spdlog::init_thread_pool(10000, 1); // queue with 10K items and 1 backing thread.
auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
spdlog::drop_all();
}
catch (const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
在include"spdlog.h"q前,可通过配置SPDLOG_ACTIVE_LEVEL到相应的日志级别
这可以在编译时打开/关闭日志,例如
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG
spdlog::set_level(spdlog::level::debug); // or spdlog::set_level(spdlog::level::trace);
SPDLOG_LOGGER_TRACE(file_logger , "Some trace message that will not be evaluated.{} ,{}", 1, 3.23);
SPDLOG_LOGGER_DEBUG(file_logger , "Some Debug message that will be evaluated.. {} ,{}", 1, 3.23);
SPDLOG_DEBUG("Some debug message to default logger that will be evaluated");
自定义日志(重要,用于自定义)
#include "spdlog/spdlog.h"
#include "spdlog/fmt/ostr.h" // must be included
#include "spdlog/sinks/stdout_sinks.h"
class some_class {};
std::ostream& operator<<(std::ostream& os, const some_class& c)
{
return os << "some_class";
}
void custom_class_example()
{
some_class c;
auto console = spdlog::stdout_logger_mt("console");
console->info("custom class with operator<<: {}..", c);
}
或者使用fmt库来使用高级格式
#include <iterator>
#include "spdlog/spdlog.h"
#include "spdlog/fmt/ostr.h" // must be included
#include "spdlog/sinks/stdout_sinks.h"
class some_class {
int code;
};
template<typename OStream>
friend OStream &operator<<(OStream &os, const some_class& to_log)
{
fmt::format_to(std::ostream_iterator<char>(os), "{:04X}", to_log.code);
return os;
}
void custom_class_example()
{
some_class c; c.code = 17;
auto console = spdlog::stdout_logger_mt("console");
console->info("custom class with operator<< using fmt: {}..", c);
}
spdlog默认格式:
[2014-10-31 23:46:59.678] [my_loggername] [info] Some message
2种方式来设置log模式,建议设置
1.建议:
set_pattern(pattern_string);
2.或使用以下:
set_formatter(std::make_unique<my_custom_formatter>());
根据介绍,目前在项目中这样使用,用来显示级别,等以后再更改
Log.h
class Log
{
public:
static void Init();
inline static std::shared_ptr<spdlog::logger>& GetCoreLogger() { return s_CoreLogger; }
inline static std::shared_ptr<spdlog::logger>& GetClientLogger() { return s_ClientLogger; }
private:
static std::shared_ptr<spdlog::logger> s_CoreLogger;
static std::shared_ptr<spdlog::logger> s_ClientLogger;
};
// Core log macros
#define LOG_TRACE(...) ::AutoSimulate::Log::GetCoreLogger()->trace(__VA_ARGS__)
#define LOG_INFO(...) ::AutoSimulate::Log::GetCoreLogger()->info(__VA_ARGS__)
#define LOG_WARN(...) ::AutoSimulate::Log::GetCoreLogger()->warn(__VA_ARGS__)
#define LOG_ERROR(...) ::AutoSimulate::Log::GetCoreLogger()->error(__VA_ARGS__)
#define LOG_FATAL(...) ::AutoSimulate::Log::GetCoreLogger()->fatal(__VA_ARGS__)
Log.cpp(用来自定义日志)
std::shared_ptr<spdlog::logger> Log::s_CoreLogger;
std::shared_ptr<spdlog::logger> Log::s_ClientLogger;
void Log::Init()
{
spdlog::set_pattern("%^[%T] %n: %v%$");
s_CoreLogger = spdlog::stdout_color_mt("HAZEL");
s_CoreLogger->set_level(spdlog::level::trace);
s_ClientLogger = spdlog::stdout_color_mt("APP");
s_ClientLogger->set_level(spdlog::level::trace);
}