当前位置: 首页 > article >正文

Boost之log日志使用

不讲理论,直接上在程序中可用代码:
一、引入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");
}


http://www.kler.cn/a/454537.html

相关文章:

  • CCF-GESP 等级考试 2023年12月认证C++五级真题解析
  • Linux网络——TCP的运用
  • Maven项目中不修改 pom.xml 状况下直接运行OpenRewrite的配方
  • STM32开发笔记123:使用STM32CubeProgrammer下载程序
  • Docker部署GitLab服务器
  • 聊一聊 C#前台线程 如何阻塞程序退出
  • Elasticsearch安装和数据迁移
  • [微服务]elasticsearc客服端操作
  • 【从零开始入门unity游戏开发之——C#篇33】C#委托(`Delegate`)和事件(`event` )、事件与委托的区别、Invoke()的解释
  • Spring Boot的开发工具(DevTools)模块中的热更新特性导致的问题
  • Vue3 Suspense:处理异步渲染过程
  • 力扣-数据结构-4【算法学习day.75】
  • EleutherAI/pythia-70m
  • 联通移动大内网如何使用plex流媒体服务器
  • 讲一个自己写的 excel 转 html 的 java 工具
  • 三只脚的电感是什么东西?
  • Unity2021.3.16f1可以正常打开,但是Unity2017.3.0f3却常常打开闪退或者Unity2017编辑器运行起来就闪退掉
  • 更改 pnpm 的全局存储位置
  • User Script Sandboxing作用 及 在iOS项目中获取GitCommitHash
  • MacOS安装Xcode(非App Store)
  • 2-197 基于matlab的生物地理学优化算法(BBO)在无人机三维航迹规划中的应用
  • Nature+Science=ONNs(光学神经网络)
  • html文件通过script标签引入外部js文件,但没正确加载的原因
  • 1_H5视频播放器-1 -- [前端开发之道:通过实例掌握编程思维]
  • Centos7配置webrtc-streamer环境
  • 识别后端返回的字符串中携带的空格 以及换行 要在前端展示 v-html