概述
Boost库的Log模块用于实现日志,虽然功能强大,但比较复杂,学习起来比较费时。
为此,我将其进行了封装成日志类,以方便日后使用。
该日志类具有多线程安全、可以使用中文字符等优点。
类头文件
#pragma once
#include <string>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/attributes/scoped_attribute.hpp>
#include <boost/log/trivial.hpp>
class Log
{
public:
Log(const std::string &sLogFilePfx = "Log", const unsigned int nRotSize = 5 * 1024 * 1024);
~Log();
void fatalLog(const std::wstring & wsTxt);
void errorLog(const std::wstring & wsTxt);
void warningLog(const std::wstring & wsTxt);
void infoLog(const std::wstring & wsTxt);
void debugLog(const std::wstring & wsTxt);
void traceLog(const std::wstring & wsTxt);
#define M_LOG_USE_TIME_LINE BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", boost::log::attributes::timer());
#define M_LOG_USE_NAMED_SCOPE(named_scope) BOOST_LOG_NAMED_SCOPE(named_scope);
private:
void internLog(const std::wstring & wsTxt, const boost::log::trivial::severity_level eSevLev);
boost::log::sources::wseverity_logger_mt<boost::log::trivial::severity_level> m_oWsLogger;
};
类实现文件
#include "Log.h"
#include <cstddef>
#include <ostream>
#include <fstream>
#include <iomanip>
#include <stdexcept>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/locale/generator.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sources/basic_logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/setup/file.hpp>
namespace logging = boost::log;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace attrs = boost::log::attributes;
namespace keywords = boost::log::keywords;
using std::string;
BOOST_LOG_ATTRIBUTE_KEYWORD(tag_attr, "Tag", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(scope, "Scope", attrs::named_scope::value_type)
BOOST_LOG_ATTRIBUTE_KEYWORD(timeline, "Timeline", attrs::timer::value_type)
BOOST_LOG_ATTRIBUTE_KEYWORD(thread_id, "ThreadID", attrs::current_thread_id::value_type)
Log::Log(const string &sLogFilePfx, const unsigned int nRotSizeInByte)
{
if (sLogFilePfx.empty())
{
throw new std::invalid_argument("日志文件前缀为空");
}
if (0 == nRotSizeInByte)
{
throw new std::invalid_argument("日志文件旋转大小为0");
}
typedef sinks::synchronous_sink< sinks::text_file_backend > text_sink;
boost::shared_ptr< sinks::text_file_backend > backend = boost::make_shared< sinks::text_file_backend >(
keywords::file_name = sLogFilePfx + "_%N.log",
keywords::rotation_size = nRotSizeInByte,
keywords::open_mode = std::ios_base::app
);
boost::shared_ptr< text_sink > sink(new text_sink(backend));
sink->set_formatter
(
expr::stream
<< expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S") << " | "
<< logging::trivial::severity << "\t| "
<< thread_id << " | "
<< "(" << scope << ") "
<< expr::if_(expr::has_attr(tag_attr))
[
expr::stream << "[" << tag_attr << "] "
]
<< expr::if_(expr::has_attr(timeline))
[
expr::stream << "[" << timeline << "] "
]
<< expr::message
);
// The sink will perform character code conversion as needed, according to the locale set with imbue()
std::locale loc = boost::locale::generator()("en_US.UTF-8");
sink->imbue(loc);
logging::core::get()->add_sink(sink);
// Add attributes
logging::add_common_attributes();
logging::core::get()->add_global_attribute("Scope", attrs::named_scope());
}
Log::~Log()
{
}
void Log::fatalLog(const std::wstring & wsTxt)
{
if (wsTxt.empty())
{
return;
}
internLog(wsTxt, logging::trivial::fatal);
}
void Log::errorLog(const std::wstring & wsTxt)
{
if (wsTxt.empty())
{
return;
}
internLog(wsTxt, logging::trivial::error);
}
void Log::warningLog(const std::wstring & wsTxt)
{
if (wsTxt.empty())
{
return;
}
internLog(wsTxt, logging::trivial::warning);
}
void Log::infoLog(const std::wstring & wsTxt)
{
if (wsTxt.empty())
{
return;
}
internLog(wsTxt, logging::trivial::info);
}
void Log::debugLog(const std::wstring & wsTxt)
{
if (wsTxt.empty())
{
return;
}
internLog(wsTxt, logging::trivial::debug);
}
void Log::traceLog(const std::wstring & wsTxt)
{
if (wsTxt.empty())
{
return;
}
internLog(wsTxt, logging::trivial::trace);
}
void Log::internLog(const std::wstring & wsTxt, const logging::trivial::severity_level eSevLev)
{
if (wsTxt.empty())
{
return;
}
BOOST_LOG_SEV(m_oWsLogger, eSevLev) << wsTxt;
}
测试代码
#include <future>
#include <thread>
#include "Log.h"
void useTimeLine(Log &oLog)
{
M_LOG_USE_TIME_LINE;
oLog.infoLog(L"Time line 1");
oLog.infoLog(L"Time line 2");
}
void named_scope_logging(Log &oLog)
{
M_LOG_USE_NAMED_SCOPE("named_scope_logging");
oLog.infoLog(L"Hello from the function named_scope_logging!");
}
int main(int, char*[])
{
Log oLog;
auto result1 = std::async([&] {
for (size_t i = 0; i < 10; i++)
{
oLog.infoLog(L"async fun");
}
});
oLog.infoLog(L"info log");
useTimeLine(oLog);
oLog.infoLog(L"info log1");
named_scope_logging(oLog);
oLog.fatalLog(L"致命错误日志");
oLog.errorLog(L"错误日志");
oLog.warningLog(L"警告日志");
oLog.infoLog(L"信息日志");
oLog.debugLog(L"调试日志");
oLog.traceLog(L"跟踪日志");
result1.get();
return 0;
}
测试结果
2019-10-07 12:54:16 | info | 0x000017bc | () async fun
2019-10-07 12:54:16 | info | 0x000017bc | () async fun
2019-10-07 12:54:16 | info | 0x000017bc | () async fun
2019-10-07 12:54:16 | info | 0x000017bc | () async fun
2019-10-07 12:54:16 | info | 0x000017bc | () async fun
2019-10-07 12:54:16 | info | 0x000017bc | () async fun
2019-10-07 12:54:16 | info | 0x000017bc | () async fun
2019-10-07 12:54:16 | info | 0x00001c90 | () info log
2019-10-07 12:54:16 | info | 0x000017bc | () async fun
2019-10-07 12:54:16 | info | 0x00001c90 | () [00:00:00.000063] Time line 1
2019-10-07 12:54:16 | info | 0x000017bc | () async fun
2019-10-07 12:54:16 | info | 0x000017bc | () async fun
2019-10-07 12:54:16 | info | 0x00001c90 | () [00:00:00.002959] Time line 2
2019-10-07 12:54:16 | info | 0x00001c90 | () info log1
2019-10-07 12:54:16 | info | 0x00001c90 | (named_scope_logging) Hello from the function named_scope_logging!
2019-10-07 12:54:16 | fatal | 0x00001c90 | () 致命错误日志
2019-10-07 12:54:16 | error | 0x00001c90 | () 错误日志
2019-10-07 12:54:16 | warning | 0x00001c90 | () 警告日志
2019-10-07 12:54:16 | info | 0x00001c90 | () 信息日志
2019-10-07 12:54:16 | debug | 0x00001c90 | () 调试日志
2019-10-07 12:54:16 | trace | 0x00001c90 | () 跟踪日志
其他
Nuget安装Boost库Log模块命令
Install-package boost -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_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_system-vc141 -version 1.68.0
Install-package boost_thread-vc141 -version 1.68.0
Install-package boost_locale-vc141 -version 1.68.0