spdlog 日志库学习,简易封装

spdlog 日志库学习,简易封装spdlogwiki:https://github.com/gabime/spdlog/wiki别人的学习笔记:https://www.cnblogs.com/oucsheep/p/8426548.html别人的学习笔记:https://github.com/gabime/spdlog/wiki百度搜spdlog封装可以看到很多写的差不多的单例类,我看公司遗留的代码也是借鉴这些写的。最常见的是一开头就写上:#ifdef_WIN32#define__FILENAME__(s

大家好,又见面了,我是你们的朋友全栈君。

spdlog wiki:https://github.com/gabime/spdlog/wiki

别人的学习笔记:https://www.cnblogs.com/oucsheep/p/8426548.html

别人的学习笔记:https://github.com/gabime/spdlog/wiki

百度搜 spdlog 封装可以看到很多写的差不多的单例类,我看公司遗留的代码也是借鉴这些写的。

最常见的是一开头就写上:

#ifdef _WIN32
#define __FILENAME__ (strrchr(__FILE__, '\\') ? (strrchr(__FILE__, '\\') + 1):__FILE__)
#else
#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1):__FILE__)
#endif
 
//定义一个在日志后添加 文件名 函数名 行号 的宏定义
#ifndef suffix
#define suffix(msg)  std::string(msg).append("  <")\
        .append(__FILENAME__).append("> <").append(__func__)\
        .append("> <").append(std::to_string(__LINE__))\
        .append(">").c_str()
//#define suffix(msg)  std::string().append(" File:")\
//        .append(__FILENAME__).append("\", Func:\"").append(__func__)\
//        .append("()\", Line:\"").append(std::to_string(__LINE__)).append("\"").append(msg).c_str()
#endif

这种文件行号之类的 spdlog 本身也自带,可以参见 SPDLOG_LOGGER_CALL 宏定义,用这个还得加上宏:

#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE

不过它自带的函数用的 __FUNCTION__ 在 VS 下会显示类名,我自定义改成了 __func__ 只保留了函数名。

代码如下:

#pragma once

//定义宏使输出文件名和行号
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE
#define SPDLOG_TRACE_ON
//#define SPDLOG_DEBUG_ON

#include "spdlog/spdlog.h"
#include "spdlog/sinks/easy_file_sink.h"
//#include "spdlog/sinks/daily_file_sink.h"

//spdlog 简易封装
//龚建波 2021-1-27 修改
//''' 示例
// Qt使用时 CONFIG += utf8_source
// INITLOG(QString("日志.log").toLocal8Bit().toStdString());
// ERRORLOG("测试下 {0} {1} {2} {3}",123,true,"测试下",QString("测试下").toStdString());
// WARNLOG("测试下 {0} {1} {2} {3}",123,true,"测试下",QString("测试下").toStdString());
// INFOLOG("测试下 {0} {1} {2} {3}",123,true,"测试下",QString("测试下").toStdString());
// DEBUGLOG("测试下 {0} {1} {2} {3}",123,true,"测试下",QString("测试下").toStdString());
// TRACELOG("测试下 {0} {1} {2} {3}",123,true,"测试下",QString("测试下").toStdString());
//'''
//spdlog讲解参见博客 https://www.cnblogs.com/oucsheep/p/8426548.html
class BaseLog
{
private:
    BaseLog()=default;
public:
    static BaseLog* getInstance() {
        static BaseLog instance;
        return &instance;
    }

    //初始化日志,路径使用locale编码
    //如: QString("日志.log").toLocal8Bit().toStdString()
    void init(const std::string& path){
        //自定义的sink
        logPtr = spdlog::easy_logger_mt("easy",path,1024*1024*25);

        //可以配置多个sink
        //std::make_shared<spdlog::logger>
        //spdlog::register_logger(logPtr); 配合 spdlog::drop_all();

        //设置日志记录级别
        logPtr->set_level(spdlog::level::trace);
        //设置格式
        //参见文档 https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
        //[%Y-%m-%d %H:%M:%S.%e] 时间
        //[%l] 日志级别
        //[%t] 线程
        //[%s] 文件
        //[%#] 行号
        //[%!] 函数
        //[%v] 实际文本
        logPtr->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [%t] [%s %!:%#] %v");
        //设置当出发 err 或更严重的错误时立刻刷新日志到  disk
        logPtr->flush_on(spdlog::level::trace);

        //spdlog::flush_every(std::chrono::seconds(3));
    }

    auto logger() {
        return logPtr;
    }

private:
    std::shared_ptr<spdlog::logger> logPtr;
};

#define INITLOG(path)     BaseLog::getInstance()->init(path)
//参见SPDLOG_LOGGER_CALL
#define SPDLOG_BASE(logger, level, ...) (logger)->log(spdlog::source_loc{__FILE__, __LINE__, __func__}, level, __VA_ARGS__)
#define TRACELOG(...)     SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::trace, __VA_ARGS__)
#define DEBUGLOG(...)     SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::debug, __VA_ARGS__)
#define INFOLOG(...)      SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::info, __VA_ARGS__)
#define WARNLOG(...)      SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::warn, __VA_ARGS__)
#define ERRORLOG(...)     SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::err, __VA_ARGS__)
#define CRITICALLOG(...)  SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::critical, __VA_ARGS__)

再贴一个百度出来的:https://blog.csdn.net/et_endeavoring/article/details/86109121

#pragma once
#include "Util.h"
 
#ifdef _WIN32
#define __FILENAME__ (strrchr(__FILE__, '\\') ? (strrchr(__FILE__, '\\') + 1):__FILE__)
#else
#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1):__FILE__)
#endif
 
//定义一个在日志后添加 文件名 函数名 行号 的宏定义
#ifndef suffix
#define suffix(msg)  std::string(msg).append("  <")\
        .append(__FILENAME__).append("> <").append(__func__)\
        .append("> <").append(std::to_string(__LINE__))\
        .append(">").c_str()
//#define suffix(msg)  std::string().append(" File:")\
//        .append(__FILENAME__).append("\", Func:\"").append(__func__)\
//        .append("()\", Line:\"").append(std::to_string(__LINE__)).append("\"").append(msg).c_str()
#endif
 
//在  spdlog.h   之前定义,才有效
#ifndef SPDLOG_TRACE_ON
#define SPDLOG_TRACE_ON
#endif
 
#ifndef SPDLOG_DEBUG_ON
#define SPDLOG_DEBUG_ON
#endif
 
#include <spdlog\spdlog.h>
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"
#include <spdlog\sinks\daily_file_sink.h>
 
class Logger
{
 
public:
	static Logger& GetInstance() {
		static Logger m_instance;
		return m_instance;
	}
 
	auto GetLogger() { return nml_logger; }
 
private:
	Logger() {
		util::MakeSureDirExist("logs");
 
		//设置为异步日志
		//spdlog::set_async_mode(32768);  // 必须为 2 的幂
		std::vector<spdlog::sink_ptr> sinkList;
//#ifdef _CONSOLE
#ifdef _DEBUG
		auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
		consoleSink->set_level(spdlog::level::debug);
		//consoleSink->set_pattern("[multi_sink_example] [%^%l%$] %v");
		consoleSink->set_pattern("[%m-%d %H:%M:%S.%e][%^%L%$]  %v");
		sinkList.push_back(consoleSink);
#endif
		auto basicSink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/basicSink.txt");
		basicSink->set_level(spdlog::level::debug);
		basicSink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%5l%$]  %v");
		sinkList.push_back(basicSink);
		nml_logger = std::make_shared<spdlog::logger>("both", begin(sinkList), end(sinkList));
		//register it if you need to access it globally
		spdlog::register_logger(nml_logger);
 
		// 设置日志记录级别
#ifdef _DEBUG
		nml_logger->set_level(spdlog::level::trace);
#else
		nml_logger->set_level(spdlog::level::err);
#endif
		//设置 logger 格式[%^%L%$]
		//nml_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%5l]  %v");
		//nml_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%5l%$]  %v");
		//设置当出发 err 或更严重的错误时立刻刷新日志到  disk 
		nml_logger->flush_on(spdlog::level::err);
 
		spdlog::flush_every(std::chrono::seconds(3));
	}
 
	~Logger() {
		spdlog::drop_all();
	}
 
	Logger(const Logger&) = delete;
	Logger& operator=(const Logger&) = delete;
 
private:
	std::shared_ptr<spdlog::logger> nml_logger;
};
 
//Logger& operator<<(Logger& log, const char* s);
//Logger& operator<<(Logger& log, const std::string& s);
 
//#define DEBUG Logger::GetInstance() 
#define LTrace(msg,...) Logger::GetInstance().GetLogger()->trace(suffix(msg),__VA_ARGS__)
//#define LDebug(msg,...) Logger::GetInstance().GetLogger()->debug(suffix(msg),__VA_ARGS__)
#define LDebug(...) Logger::GetInstance().GetLogger()->debug(__VA_ARGS__)
#define LInfo(...) Logger::GetInstance().GetLogger()->info(__VA_ARGS__)
#define LWarn(...) Logger::GetInstance().GetLogger()->warn(__VA_ARGS__)
#define LError(...) Logger::GetInstance().GetLogger()->error(__VA_ARGS__)
#define LCritical(...) Logger::GetInstance().GetLogger()->critical(__VA_ARGS__)
 
#define criticalif(b, ...)                        \
    do {                                       \
        if ((b)) {                             \
           Logger::GetInstance().GetLogger()->critical(__VA_ARGS__); \
        }                                      \
    } while (0)
 
#ifdef WIN32  
#define errcode WSAGetLastError()
#endif

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/152325.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • aero是什么意思啊_自动驾驶视觉算法

    aero是什么意思啊_自动驾驶视觉算法数据集介绍aeroscapes数据集下载链接AeroScapes航空语义分割基准包括使用商用无人机在5到50米的高度范围内捕获的图像。该数据集提供3269张720p图像和11个类别的真实掩码。数据加载dataloder写法(基于pytorch)由于该数据集提供了掩码图,因此不需要进行掩码图转换。下载完成后,文件结构如下:ImageSets文件夹:存放了两个txt文件,划分了训练集和验证集。JPEGImages文件夹:存放了RGB图像。SegmentationClass

    2022年8月15日
    5
  • 如何清除网上浏览痕迹?清除缓存

    如何清除网上浏览痕迹?清除缓存

    2021年9月20日
    40
  • Python range 函数 – Python零基础入门教程

    Python range 函数 – Python零基础入门教程目录一.Pythonrange函数简介二.Pythonrange函数使用1.Pythonrange函数常规使用2.Pythonrange函数在for循环中使用三.猜你喜欢

    2022年7月5日
    22
  • POSIX 螺纹具体解释(1-概要)

    POSIX 螺纹具体解释(1-概要)

    2022年1月9日
    44
  • c语言输出整型量格式符,C语言输出格式(详细)

    c语言输出整型量格式符,C语言输出格式(详细)C语言格式化输出一、printf()函数printf()函数是格式化输出函数,一般用于向标准输出设备按规定格式输出信息。在编写程序时经常会用到此函数。printf()函数的调用格式为:printf(“”,);其中格式化字符串包括两部分内容:一部分是正常字符,这些字符将按原样输出,另一部分是格式化规定字符,以”%”开始,后跟一个或几个规定字符用来确定输出内容格式。参量表是需要输出的一系列参数…

    2022年7月24日
    12
  • 软件开发项目管理经验总结

    软件开发项目管理经验总结这是我从事软件外包工作以来的项目管理经验的总结,编写文章的目的是为了回顾和总结自己的一些想法,如果其中有不足的地方大家可以一起讨论交流。项目经理的职责关于项目经理的工作职责有很多种说法,我自己是这样理解的作为一名项目经理第一目标就是合理利用公司资源组织设计、开发、测试等各种资源完成项目的高质量交付,并保证项目的盈利。这是衡量一个项目失败或者成功的唯…

    2022年5月12日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号