使用Boost库Log模块实现的C++日志类

概述

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

发布了19 篇原创文章 · 获赞 0 · 访问量 985

猜你喜欢

转载自blog.csdn.net/xuyouqiang1987/article/details/102300043