设计目标:
1、每个Logging source对应一个目录,可以设置日志文件数,日志大小,目录名,文件名等
2、所有logging source日志目录都在一个根目录下。
3、可以动态创建和删除logging source
4、打印出日期时间和日志严重等级
示例代码:
#include <libs/Core/LogMananger.h>
int main(){
LogManager::instance().setRootPath("logs");
LogManager::instance().addLogger("network", "network", 1024*100, 10);
LogManager::instance().addLogger("db", "db", 1024*100, 10);
for(int i = 0; i < 10000; i++){
LOG(network, info) << "hello world aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
LOG(network, trace) << "hello world aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
LOG(network, warning) << "hello world aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
LOG(network, fatal) << "hello world ";
LOG(network, debug) << "hello world";
LOG(db, info) << "hello world aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
LOG(db, trace) << "hello world aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
LOG(db, warning) << "hello world aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
LOG(db, fatal) << "hello world";
LOG(db, debug) << "hello world";
}
return 0;
}
生成的日志目录结构:
日志格式:
LogManager.h
#pragma once
#include <boost/log/trivial.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/sources/basic_logger.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/core.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/sinks.hpp>
#include <boost/core/null_deleter.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/attributes/constant.hpp>
#include <boost/log/exceptions.hpp>
#include <boost/log/keywords/format.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/expressions/formatters/date_time.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <memory>
#include <map>
#include <fstream>
#include <iostream>
#include <string>
#include <mutex>
using namespace std;
namespace sources = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace expressions = boost::log::expressions;
namespace trivial = boost::log::trivial;
namespace keywords = boost::log::keywords;
namespace attributes = boost::log::attributes;
class LogManager
{
struct LoggerInfo{
string m_strName;
string m_strPath;
int m_nMaxSize;
int m_nMaxCount;
boost::shared_ptr<sources::severity_logger_mt<trivial::severity_level>> m_pLogger;
boost::shared_ptr<sinks::synchronous_sink<sinks::text_file_backend>> m_pSink;
};
public:
~LogManager();
static LogManager& instance();
void setRootPath(const string& strRootPath = "");
void addLogger(const string& strName, const string& strPath, int nMaxSize, int nMaxCount);
void removeLogger(const string& strName);
boost::log::sources::severity_logger_mt<trivial::severity_level>& getLogger(const string& strName);
private:
LogManager();
private:
string m_strRootPath;
map<string, LoggerInfo> m_mapLogger;
mutex m_oLock;
};
#define LOG(name, level) BOOST_LOG_SEV(LogManager::instance().getLogger(#name), boost::log::trivial::severity_level::level)
LogManager.cpp
#include "LogMananger.h"
LogManager::LogManager()
{
}
LogManager::~LogManager()
{
}
LogManager& LogManager::instance()
{
static LogManager t;
return t;
}
void LogManager::setRootPath(const string& strRootPath)
{
m_strRootPath = strRootPath;
}
void LogManager::addLogger(const string& strName, const string& strPath, int nMaxSize, int nMaxCount)
{
lock_guard<mutex> lk(m_oLock);
if(m_mapLogger.contains(strName))
return;
m_mapLogger[strName] = LoggerInfo();
m_mapLogger[strName].m_strName = strName;
m_mapLogger[strName].m_strPath = strPath;
m_mapLogger[strName].m_nMaxSize = nMaxSize;
m_mapLogger[strName].m_nMaxCount = nMaxCount;
m_mapLogger[strName].m_pLogger = boost::make_shared<sources::severity_logger_mt<trivial::severity_level>>();
m_mapLogger[strName].m_pLogger->add_attribute("LoggerName", attributes::constant<string>(strName));
m_mapLogger[strName].m_pLogger->add_attribute("DateTime", attributes::local_clock());
boost::shared_ptr<sinks::text_file_backend> pTxtFileBackend = boost::make_shared<sinks::text_file_backend>(
keywords::file_name = m_strRootPath + "/" + strPath + "/" + strName + ".log", //是日志文件大小没达到最大值时,日志写的文件
keywords::target_file_name = strName + "_%2N.log", //当日志文件达到最大值时,日志文件名会被改写,这里的%2N,表示用两位数字表示
keywords::rotation_size = nMaxSize, //单个日志文件最大值,这里是5M
keywords::open_mode = std::ios_base::out | std::ios_base::app, //添加模式
keywords::time_based_rotation = sinks::file::rotation_at_time_point(12, 0, 0)); //每天12点会重新生成一个日志文件,不管日志文件是否到了最大值
m_mapLogger[strName].m_pSink = boost::make_shared<sinks::synchronous_sink<sinks::text_file_backend>>(pTxtFileBackend);
m_mapLogger[strName].m_pSink->locked_backend()->set_file_collector(
sinks::file::make_collector(
keywords::max_files = nMaxCount, //最多N个日志文件
keywords::max_size = nMaxSize*(1+nMaxCount), //正目录最大占用多少磁盘空间
keywords::target = m_strRootPath + "/" + strPath //日志保存的目录,前面target_file_name所在的目录
));
m_mapLogger[strName].m_pSink->locked_backend()->auto_flush(true);
m_mapLogger[strName].m_pSink->locked_backend()->scan_for_files();
m_mapLogger[strName].m_pSink->set_formatter(
expressions::stream
<< expressions::if_(expressions::has_attr<boost::posix_time::ptime>("DateTime"))
[
expressions::stream << "[" << expressions::format_date_time< boost::posix_time::ptime >("DateTime", "%Y-%m-%d %H:%M:%S.%f") << "] "
]
<< "[" << trivial::severity << "] "
<< expressions::smessage
);
m_mapLogger[strName].m_pSink->set_filter(
expressions::has_attr("LoggerName") && expressions::attr<string>("LoggerName") == strName
);
boost::log::core::get()->add_sink(m_mapLogger[strName].m_pSink);
}
void LogManager::removeLogger(const string& strName)
{
lock_guard<mutex> lk(m_oLock);
if(m_mapLogger.contains(strName))
boost::log::core::get()->remove_sink(m_mapLogger[strName].m_pSink);
}
sources::severity_logger_mt<trivial::severity_level>& LogManager::getLogger(const string& strName)
{
lock_guard<mutex> lk(m_oLock);
return *m_mapLogger[strName].m_pLogger;
}