不讲理论,直接上在程序中可用代码:
一、引入Boost模块
开发环境:Visual Studio 2017
Boost库版本:1.68.0
安装方式:Nuget
安装命令:
#只安装下面几个即可
Install-package boost -version 1.68.0
Install-package boost_filesystem-vc141 -version 1.68.0
Install-package boost_log_setup-vc141 -version 1.68.0
Install-package boost_log-vc141 -version 1.68.0
#这里是其他模块,可不安装
Install-package boost_atomic-vc141 -version 1.68.0
Install-package boost_chrono-vc141 -version 1.68.0
Install-package boost_date_time-vc141 -version 1.68.0
Install-package boost_system-vc141 -version 1.68.0
Install-package boost_thread-vc141 -version 1.68.0
Install-package boost_locale-vc141 -version 1.68.0
调用Nuget控制台:
二、引入下面两个hpp文件
boost_logger.hpp
#pragma once
#include <string>
#include <fstream>
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/core/null_deleter.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/async_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/attributes/current_thread_id.hpp>
#include <boost/log/attributes/current_process_name.hpp>
#include <boost/log/attributes/attribute.hpp>
#include <boost/log/attributes/attribute_cast.hpp>
#include <boost/log/attributes/attribute_value.hpp>
#include <boost/log/sinks/async_frontend.hpp>
// Related headersQDebug
#include <boost/log/sinks/unbounded_fifo_queue.hpp>
#include <boost/log/sinks/unbounded_ordering_queue.hpp>
#include <boost/log/sinks/bounded_fifo_queue.hpp>
#include <boost/log/sinks/bounded_ordering_queue.hpp>
#include <boost/log/sinks/drop_on_overflow.hpp>
#include <boost/log/sinks/block_on_overflow.hpp>
//这里是logger的头文件,后面根据实际路径引入
#include "logger.hpp"
//引入各种命名空间
namespace logging = boost::log;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace keywords = boost::log::keywords;
namespace attrs = boost::log::attributes;
//建立日志源,支持严重属性
thread_local static boost::log::sources::severity_logger<log_level> lg;
#define BOOST_LOG_Q_SIZE 1000
//创建输出槽:synchronous_sink是同步前端,允许多个线程同时写日志,后端无需考虑多线程问题
typedef sinks::asynchronous_sink<sinks::text_file_backend, sinks::bounded_fifo_queue<BOOST_LOG_Q_SIZE, sinks::block_on_overflow>> sink_t;
static std::ostream &operator<<(std::ostream &strm, log_level level)
{
static const char *strings[] =
{
"debug",
"info",
"warn",
"error",
"critical"};
if (static_cast<std::size_t>(level) < sizeof(strings) / sizeof(*strings))
strm << strings[level];
else
strm << static_cast<int>(level);
return strm;
}
class boost_logger : public logger_iface
{
public:
boost_logger(const std::string& dir) : m_level(log_level::error_level), dir(dir)
{
}
~boost_logger()
{
}
/**
* 日志初始化
*/
void init() override
{
//判断日志文件所在路径是否存在
if (boost::filesystem::exists(dir) == false)
{
boost::filesystem::create_directories(dir);
}
//添加公共属性
logging::add_common_attributes();
//获取日志库核心
core = logging::core::get();
//创建后端,并设值日志文件相关控制属性
boost::shared_ptr<sinks::text_file_backend> backend = boost::make_shared<sinks::text_file_backend>(
keywords::open_mode = std::ios::app, // 采用追加模式
keywords::file_name = dir + "/%Y%m%d_%N.log", //归档日志文件名
keywords::rotation_size = 10 * 1024 * 1024, //超过此大小自动建立新文件
keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0), //每隔指定时间重建新文件
keywords::min_free_space = 100 * 1024 * 1024 //最低磁盘空间限制
);
if (!_sink)
{
_sink.reset(new sink_t(backend));
//向日志源添加槽
core->add_sink(_sink);
}
//添加线程ID公共属性
core->add_global_attribute("ThreadID", attrs::current_thread_id());
//添加进程公共属性
core->add_global_attribute("Process", attrs::current_process_name());
//设置过滤器
_sink->set_filter(expr::attr<log_level>("Severity") >= m_level);
// 如果不写这个,它不会实时的把日志写下去,而是等待缓冲区满了,或者程序正常退出时写下
// 这样做的好处是减少IO操作,提高效率
_sink->locked_backend()->auto_flush(true); // 使日志实时更新
//这些都可在配置文件中配置
_sink->set_formatter(
expr::stream
<< "["
<< expr::attr<std::string>("Process") << ":" << expr::attr<attrs::current_thread_id::value_type>("ThreadID") << ":"
<< expr::attr<unsigned int>("LineID") << "]["
<< expr::format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << "]["
<< expr::attr<log_level>("Severity") << "] "
<< expr::smessage);
}
/**
* 停止记录日志
*/
void stop() override
{
warn_log("boost logger stopping");
_sink->flush();
_sink->stop();
core->remove_sink(_sink);
}
/**
* 设置日志级别
*/
void set_log_level(log_level level) override
{
m_level = level;
if (_sink)
{
_sink->set_filter(expr::attr<log_level>("Severity") >= m_level);
}
}
log_level get_log_level() override
{
return m_level;
}
void debug_log(const std::string &msg) override
{
BOOST_LOG_SEV(lg, debug_level) << msg << std::endl;
}
void info_log(const std::string &msg) override
{
BOOST_LOG_SEV(lg, info_level) << blue << msg << normal << std::endl;
}
void warn_log(const std::string &msg) override
{
BOOST_LOG_SEV(lg, warn_level) << yellow << msg << normal << std::endl;
}
void error_log(const std::string &msg) override
{
BOOST_LOG_SEV(lg, error_level) << red << msg << normal << std::endl;
}
void critical_log(const std::string &msg) override
{
BOOST_LOG_SEV(lg, critical_level) << red << msg << normal << std::endl;
}
private:
log_level m_level;
boost::shared_ptr<logging::core> core;
boost::shared_ptr<sink_t> _sink;
//日志文件路径
const std::string& dir;
};
logger.hpp
#pragma once
#define BOOST_ALL_DYN_LINK
#include <string> // std::string
#include <iostream> // std::cout
#include <fstream>
#include <sstream> // std::ostringstream
#include <memory>
typedef std::basic_ostringstream<char> tostringstream;
static const char black[] = {0x1b, '[', '1', ';', '3', '0', 'm', 0};
static const char red[] = {0x1b, '[', '1', ';', '3', '1', 'm', 0};
static const char yellow[] = {0x1b, '[', '1', ';', '3', '3', 'm', 0};
static const char blue[] = {0x1b, '[', '1', ';', '3', '4', 'm', 0};
static const char normal[] = {0x1b, '[', '0', ';', '3', '9', 'm', 0};
#define ACTIVE_LOGGER_INSTANCE (*activeLogger::getLoggerAddr())
// note: this will replace the logger instace. If this is not the first time to set the logger instance.
// Please make sure to delete/free the old instance.
#define INIT_LOGGER(loggerImpPtr) \
{ \
ACTIVE_LOGGER_INSTANCE = loggerImpPtr; \
ACTIVE_LOGGER_INSTANCE->init(); \
}
#define CHECK_LOG_LEVEL(logLevel) (ACTIVE_LOGGER_INSTANCE ? ((ACTIVE_LOGGER_INSTANCE->get_log_level() <= log_level::logLevel##_level) ? true : false) : false)
#define SET_LOG_LEVEL(logLevel) \
{ \
if (ACTIVE_LOGGER_INSTANCE) \
(ACTIVE_LOGGER_INSTANCE->set_log_level(log_level::logLevel##_level)); \
}
#define DESTROY_LOGGER \
{ \
if (ACTIVE_LOGGER_INSTANCE) \
{ \
ACTIVE_LOGGER_INSTANCE->stop(); \
delete ACTIVE_LOGGER_INSTANCE; \
} \
}
enum log_level
{
debug_level = 0,
info_level,
warn_level,
error_level,
critical_level
};
class logger_iface
{
public:
logger_iface(void) = default;
virtual ~logger_iface(void) = default;
logger_iface(const logger_iface &) = default;
logger_iface &operator=(const logger_iface &) = default;
public:
virtual void init() = 0;
virtual void stop() = 0;
virtual void set_log_level(log_level level) = 0;
virtual log_level get_log_level() = 0;
virtual void debug_log(const std::string &msg) = 0;
virtual void info_log(const std::string &msg) = 0;
virtual void warn_log(const std::string &msg) = 0;
virtual void error_log(const std::string &msg) = 0;
virtual void critical_log(const std::string &msg) = 0;
};
class activeLogger
{
public:
static logger_iface **getLoggerAddr()
{
static logger_iface *activeLogger;
return &activeLogger;
}
};
#define __LOGGING_ENABLED
#ifdef __LOGGING_ENABLED
#define __LOG(level, msg) \
\
{ \
tostringstream var; \
var << "[" << __FILE__ << ":" << __LINE__ << ":" << __func__ << "] \n" \
<< msg; \
if (ACTIVE_LOGGER_INSTANCE) \
ACTIVE_LOGGER_INSTANCE->level##_log(var.str()); \
}
#else
#define __LOG(level, msg)
#endif /* __LOGGING_ENABLED */
三、使用样例
#include "logger/boost_logger.hpp"
#include "logger/simpleLogger.hpp"
void testCustomLogger() {
//初始化日志对象:日志路径后期从配置文件读取
const std::string logDir = "E:\\log";
INIT_LOGGER(new boost_logger(logDir));
//设置过滤级别(可以读取配置文件)
SET_LOG_LEVEL(debug);
//输出各级别日志,(void *)ACTIVE_LOGGER_INSTANCE:代表激活的日志实例(可不写)
__LOG(critical, "hello logger!"
<< "this is critical log" << (void *)ACTIVE_LOGGER_INSTANCE);
__LOG(debug, "hello logger!!!!!!!!!!!!!!!"
<< "this is debug log");
}