Boost之Log: (3)、简单封装

news2024/12/26 10:55:40

设计目标:

        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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1564142.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

不同设备使用同一个Git账号

想要在公司和家里的电脑上用同一个git账号来pull, push代码 1. 查看原设备的用户名和邮箱 第1种方法&#xff0c; 依次输入 git config user.name git config user.email第2种方法&#xff0c; 输入 cat ~/.gitconfig2. 配置新设备的用户名和邮箱 用户名和邮箱与原设备保持…

(十一)RabbitMQ及SpringAMQP

1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要马上回复。 两种方式各有优劣&#xff0c;打电话可以立即得到响应&#xff0c;…

自动驾驶的世界模型:综述

自动驾驶的世界模型&#xff1a;综述 附赠自动驾驶学习资料和量产经验&#xff1a;链接 24年3月澳门大学和夏威夷大学的论文“World Models for Autonomous Driving: An Initial Survey”。 在快速发展的自动驾驶领域&#xff0c;准确预测未来事件并评估其影响的能力对安全性…

桶排序---

1、算法概念 桶排序&#xff1a;一种非比较的排序算法。桶排序采用了一些分类和分治的思想&#xff0c;把元素的值域分成若干段&#xff0c;每一段对应一个桶。在排序的时候&#xff0c;首先把每一个元素放到其对应的桶中&#xff0c;再对每一个桶中的元素分别排序&#xff0c…

跨境运营必看:TikTok账号防封指南

多人在使用TikTok的过程中都会遇到一些问题&#xff0c;比如为什么TikTok没有浏览量&#xff1f;事实上&#xff0c;这很可能是因为你的账号已被禁止。但为什么它会被封呢&#xff1f;你怎样才能解决它&#xff1f; 一、TikTok账号为什么被封&#xff1f; 1、什么是 TikTok 影…

友思特方案 | 构建缤纷:可调谐光源的荧光成像的应用

导读 生物荧光分析常常伴随使用多种荧光染料的需求。结合多通道光源技术与高性能成像设备&#xff0c;友思特可调谐光源荧光检测成像方案&#xff0c;以其灵活的系统组成&#xff0c;满足了丰富的荧光检测应用需求。 生物荧光分析技术 激发荧光成像技术是研究生物学过程的一种…

越南工厂连接中国总部服务器解决方案---案例分享

随着全球化的不断深入&#xff0c;许多中国企业走出国门&#xff0c;在世界各地设立分支机构和生产基地。然而&#xff0c;随之而来的是跨国网络通信的挑战。近期&#xff0c;客户越南的工厂与中国总部之间的网络连接出现了一些问题&#xff0c;这直接影响了企业的日常运营效率…

身份证实名认证接口会返回什么?javascript身份核验接口示例

身份证实名认证接口是通过核验身份证号、姓名、证件头像等一系列的要素信息进行用户身份验证&#xff0c;那么&#xff0c;身份证实名认证接口一般在核验完成后会返回什么参数信息呢&#xff1f;下面翔云API小编为大家答疑解惑&#xff01; 一般情况下&#xff0c;身份核验只会…

索引下推(Index Condition Pushdown,简称 ICP)

Mysql可以分为Server层和存储引擎层 所以&#xff0c;最终进行I/O的是存储引擎对文件系统进行I/O操作 索引下推&#xff08;Index Condition Pushdown&#xff0c;简称 ICP&#xff09; 对应InnoDB&#xff0c;索引下推适用于非聚簇索引&#xff08;二级索引&#xff09;。 …

深度学习理论基础(六)注意力机制

目录 深度学习中的注意力机制&#xff08;Attention Mechanism&#xff09;是一种模仿人类视觉和认知系统的方法&#xff0c;它允许神经网络在处理输入数据时集中注意力于相关的部分。通过引入注意力机制&#xff0c;神经网络能够自动地学习并选择性地关注输入中的重要信息&…

Oracle常用sql命令(新手)

1、备份单张表 创建复制表结构 create table employeesbak as select * from cims.employees 如果只复制表结构&#xff0c;只需要在结尾加上 where 10 插入数据 insert into employeesbak select * from cims.employees 删除一条数据 delete from…

探索数字社交的边界:揭示Facebook如何塑造未来社交媒体的发展趋势

在当今数字化时代&#xff0c;社交媒体已经成为人们生活中不可或缺的一部分。而作为最大的社交媒体平台之一&#xff0c;Facebook一直在前沿探索数字社交的边界&#xff0c;并且不断塑造着未来社交媒体的发展趋势。本文将深入探讨Facebook在数字社交领域的探索与创新&#xff0…

RDGCN阅读笔记

Relation-Aware Entity Alignment for Heterogeneous Knowledge Graphs 面向异质知识图谱的关系感知实体对齐 Abstract 实体对齐是从不同的知识图(KGs)中链接具有相同真实世界实体的任务&#xff0c;最近被基于嵌入的方法所主导。这种方法通过学习KG表示来工作&#xff0c;以…

Redis基本配置及安装

Redis也叫Remote dictionary server,是一个开源的基于内存的数据存储系统。它可以用作数据库、缓存和消息队列等各种场景。它也是目前最热门的NoSQL数据库之一 以下是NoSQL的定义 随着互联网的快速发展&#xff0c;应用系统的访问量越来越大&#xff0c;数据库的性能瓶颈越来越…

vue3鼠标向下滑动,导航条改变背景颜色和logo的封装

代码中使用了element-plus组件&#xff0c;需先安装 向下滑动前 向下滑动后&#xff08;改变了logo 字体 背景颜色&#xff09; <script lang"ts" setup> import router from /router; import { ArrowDown } from element-plus/icons-vue import { ref, …

基于 YOLO V8 Pose Fine-Tuning 训练 15 点人脸关键点检测模型

一、YOLO V8 Pose YOLO V8 在上篇文章中进了简单的介绍&#xff0c;并基于YOLO V8 Fine-Tuning 训练了自定义的目标检测模型&#xff0c;而YOLO V8 Pose 是建立在YOLO V8基础上的关键点检测模型&#xff0c;本文基于 yolov8n-pose 模型实验 Fine-Tuning 训练15 点人脸关键点检…

DHCP原理重磅来袭——走过路过不要错过

目录 一.DHCP来源 &#xff08;1)手工分配缺点 (2)DHCP优点 二.DHCP设备调试 &#xff08;1&#xff09;.基本配置&#xff1a; &#xff08;2&#xff09;接口地址池 1.开启DHCP功能 2.开启DHCP接口地址池功能 3.查看IP地址分配结果 &#xff08;3&#xff09;全局地…

最新AI智能系统ChatGPT网站源码V6.3版本,GPTs、AI绘画、AI换脸、垫图混图+(SparkAi系统搭建部署教程文档)

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GPT…

商品服务 - 三级分类

1.递归查询树形结构 Overridepublic List<CategoryEntity> listWithTree() {//1.查出所有分类List<CategoryEntity> all this.list();//2.组装成父子的属性结构List<CategoryEntity> level1Menus all.stream().filter(c -> c.getParentCid().equals(0L)…

OSError: Can‘t load tokenizer for ‘bert-base-chinese‘

文章目录 OSError: Cant load tokenizer for bert-base-chinese1.问题描述2.解决办法 OSError: Can’t load tokenizer for ‘bert-base-chinese’ 1.问题描述 使用from_pretrained()函数从预训练的权重中加载模型时报错&#xff1a; OSError: Can’t load tokenizer for ‘…