【封装一个日志库(linux)】【转载】

原文链接:

工具库1:封装一个日志库(linux)-CSDN博客

一、,需求
(1)封装一个c/c++日志库,提供格式打印接口,编写程序代码时方便使用;
(2) 格式打印接口支持可变参数;
(3)格式打印接口封装成可变参数宏,便于使用;

二,实现
(1)提供格式打印接口;
(2)日志等级分成三个级别,分别是错误、警告、普通信息;
(3)支持输出到终端,同时支持输出到指定日志文件;
(4)格式打印接口支持可变参数;
(5)打印字符串长度无限制;

三,源码
(1)messages.h
 

/**
*****************************************************************************
*  Copyright (C), 2023-2024
*
*  @file    messages.h
*  @brief   printf pretty
*
*
*  @author  sbinhuang
*  @date    2023-06-28
*  @version v1.0.0 20230628
*----------------------------------------------------------------------------
*  @note 历史版本   修改人员    修改日期      修改内容
*  @note v1.0    sbinhuang   2023-06-28   1.创建
*
*****************************************************************************
*/
#ifndef _SELF_UTILITY_MESSAGES_H_
#define _SELF_UTILITY_MESSAGES_H_
#include <iostream>
#include <fstream>namespace SelfUtility {
// message type
enum MessageType {NONE  = 0,ERROR = 1,WARN  = 2,INFO  = 3
};class Messages {public:// default close file and enable terminal outputstatic bool Init();// open log file// mode = true, open or create file and clear file content// mode = false, open or create file, doesn't clear file contentstatic bool OpenLogFile(const char *file_name, bool mode = 0);// close log filestatic bool CloseLogFile();// enable terminal outputstatic bool EnableTerminalOutput();// disable terminal outputstatic bool DisableTerminalOutput();// print message for variable argumentstatic bool Message(const MessageType &type, const char *file_name,int line_number, const char *format, ...);// print message for determine argumentstatic bool Message(const MessageType &type, const char *file_name,int line_number, const char *format);private:static std::ofstream _os;static bool _terminal_output;static bool _write_file;
};}  // namespace SelfUtility#define LOG_ERROR(format, ...) do { \SelfUtility::Messages::Message(SelfUtility::MessageType::ERROR, \__FILE__, __LINE__, format, __VA_ARGS__); \
} while (0)#define LOG_WARN(format, ...) do { \SelfUtility::Messages::Message(SelfUtility::MessageType::WARN, \__FILE__, __LINE__, format, __VA_ARGS__); \
} while (0)#define LOG_INFO(format, ...) do { \SelfUtility::Messages::Message(SelfUtility::MessageType::INFO, \__FILE__, __LINE__, format, __VA_ARGS__); \
} while (0)#define LOG_PRINT(format, ...) do { \SelfUtility::Messages::Message(SelfUtility::MessageType::NONE, \__FILE__, __LINE__, format, __VA_ARGS__); \
} while (0)#define LOG_INIT() do { \SelfUtility::Messages::Init(); \
} while (0)#endif  // _SELF_UTILITY_MESSAGES_H_

(2) messages.cpp

/**
*****************************************************************************
*  Copyright (C), 2023-2024
*
*  @file    messages.cpp
*  @brief   printf pretty
*
*
*  @author  sbinhuang
*  @date    2023-06-28
*  @version v1.0.0 20230628
*----------------------------------------------------------------------------
*  @note 历史版本   修改人员    修改日期      修改内容
*  @note v1.0    sbinhuang   2023-06-28   1.创建
*
*****************************************************************************
*/
#include "messages.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <iostream>
#include <fstream>
#include <string>using SelfUtility::MessageType;
using SelfUtility::Messages;// static variable define for class Messages
std::ofstream Messages::_os;
bool Messages::_write_file;
bool Messages::_terminal_output;// initial log print, default output terminal
bool Messages::Init() {if (_os.is_open()) _os.close();_terminal_output = true;_write_file = false;return true;
}// Open log file
// mode = true, open or create file and clear file content
// mode = false, open or create file, doesn't clear file content
bool Messages::OpenLogFile(const char *file_name, bool mode) {if (!file_name) {std::cout << "Log file name is null pointer!" << std::endl;return false;}// open fileif (true == mode) {_os.open(file_name, std::ios::out);} else {_os.open(file_name, std::ios::app);}if (!_os.is_open()) {std::cout << "File open failed!" << "(" << file_name<< ")" << std::endl;return false;}_write_file = true;return true;
}// close log file
bool Messages::CloseLogFile() {if (_os.is_open()) _os.close();_write_file = false;return true;
}// enable terminal output
bool Messages::EnableTerminalOutput() {_terminal_output = true;return true;
}// disable terminal output
bool Messages::DisableTerminalOutput() {_terminal_output = false;return true;
}// print message for variable argument
bool Messages::Message(const MessageType &type, const char *file_name,int line_number, const char *format, ...) {// print titleif (MessageType::ERROR == type) {if (true == _terminal_output) {if (file_name) {std::cout << "[" << file_name << ": "<< line_number << "]";}std::cout << "ERROR: ";}if (true == _write_file) {if (file_name) {_os << "[" << file_name << ": "<< line_number << "]";}_os << "ERROR: ";}} else if (MessageType::WARN == type) {if (true == _terminal_output) {if (file_name) {std::cout << "[" << file_name << ": "<< line_number << "]";}std::cout << "WARN: ";}if (true == _write_file) {if (file_name) {_os << "[" << file_name << ": "<< line_number << "]";}_os << "WARN: ";}} else if (MessageType::INFO == type) {if (true == _terminal_output) std::cout << "INFO: ";if (true == _write_file) std::cout << "INFO: ";}// print messagechar *buf = NULL;va_list arg_ptr;va_start(arg_ptr, format);vasprintf(&buf, format, arg_ptr);va_end(arg_ptr);if (true == _terminal_output) {std::cout << buf;}if (true == _write_file) {_os << buf;}free(buf);buf = NULL;return true;
}// print message for determine argument
bool Messages::Message(const MessageType &type, const char *file_name,int line_number, const char *format) {// print titleif (MessageType::ERROR == type) {if (true == _terminal_output) {if (file_name) {std::cout << "[" << file_name << ": "<< line_number << "]";}std::cout << "ERROR: ";}if (true == _write_file) {if (file_name) {_os << "[" << file_name << ": "<< line_number << "]";}_os << "ERROR: ";}} else if (MessageType::WARN == type) {if (true == _terminal_output) {if (file_name) {std::cout << "[" << file_name << ": "<< line_number << "]";}std::cout << "WARN: ";}if (true == _write_file) {if (file_name) {_os << "[" << file_name << ": "<< line_number << "]";}_os << "WARN: ";}} else if (MessageType::INFO == type) {if (true == _terminal_output) std::cout << "INFO: ";if (true == _write_file) std::cout << "INFO: ";}// print messageif (true == _terminal_output) std::cout << format;if (true == _write_file) _os << format;return true;
}

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

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

相关文章

Mybatis----面向接口

让mybatis自动生成dao层接口的实现类 这是dao层接口的实现类&#xff0c;在mybatis中我们可以省略这种实现接口的方式&#xff0c;直接面向接口操作数据库&#xff0c;mybatis可以帮我们自动生成接口的实现类&#xff0c;也就是下面这个实现类mybatis帮我们生成了。 1、修改se…

检测射线与边界盒AABB相交(C#代码Unity环境下测试通过)

说明&#xff1a;如果仅仅是再Unity环境下使用的话&#xff0c;直接使用Bounds.IntersectRay方法就好了&#xff0c;这里仅仅探索其算法。 上代码&#xff1a; bool RayCrossBounds(Ray ray, Bounds bounds) {if (bounds.Contains(ray.origin)) return true;//float tMinX fl…

P3952 [NOIP2017 提高组] 时间复杂度————C++

目录 [NOIP2017 提高组] 时间复杂度题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 解题思路Code运行结果 [NOIP2017 提高组] 时间复杂度 题目背景 NOIP2017 提高组 D1T2 题目描述 小明正在学习一种新的编程语言 A&#xff0c;刚学会循环语句的他激动…

openssl3.2 - 官方demo学习 - guide - tls-client-block.c

文章目录 openssl3.2 - 官方demo学习 - guide - tls-client-block.c概述记录问题server和client IP都为localhostserver和client IP都为127.0.0.1想到解决问题的方法1想到解决问题的方法2笔记END openssl3.2 - 官方demo学习 - guide - tls-client-block.c 概述 tls 客户端 官…

QT5构建套件检测不到MSVC2017解决方法

文章目录 前言一、本地环境二、现象三、解决办法 前言 记录一下 QT5 构建套件检测不到 MSVC2017 解决方法 。Qt Creator MSVC开发环境搭建&#xff08;Qt Creator 集成工具 MSVC编译&#xff09; 一、本地环境 电脑操作系统&#xff1a;Win11Qt 版本&#xff1a;Qt 5.14.2 …

linux基础学习(2):磁盘管理、分区、格式化

1.一些基本概念 一块磁盘从加入到可使用&#xff0c;需要经过3个阶段&#xff1a;分区-格式化-挂载。 1.1分区方式 linux有2种分区方式&#xff1a; &#xff08;1&#xff09;mbr&#xff1a;最大支持2.1T硬盘&#xff0c;最多支持4个分区。这4个分区可以全部为主分区&…

77、avx2 向量寄存器介绍

本节带大家简单了解下计算机内的存储器,了解了存储器之后,对于后面的优化就会有更深刻的认识。 我们最熟悉的存储器就是电脑的内存,或者硬盘。在计算机系统中,我们可以把所有可以存储数据的部件都叫做存储器。 只不过很多是用户可见并熟悉的,如硬盘和内存条,GPU 的显存…

【elementUI】el-select相关问题

官方使用DEMO <template><el-select v-model"value" placeholder"请选择"><el-optionv-for"item in options":key"item.value":label"item.label":value"item.value"></el-option></…

鸿蒙开发笔记(三):页面和自定义组件生命周期

先明确自定义组件和页面的关系&#xff1a; 自定义组件&#xff1a;Component装饰的UI单元&#xff0c;可以组合多个系统组件实现UI的复用。 页面&#xff1a;即应用的UI页面。可以由一个或者多个自定义组件组成&#xff0c;Entry装饰的自定义组件为页面的入口组件&#xff0c…

QEMU与KVM基本概述

一些术语 汇总在虚拟化世界里经常会涉及到的术语或缩写等。 术语含义VMVirtual Machine&#xff0c;虚拟机VMM在系统虚拟化中&#xff0c;管理全局物理资源的软件叫作虚拟机监控器&#xff08;Virtual MachineMonitor&#xff0c;VMM&#xff09;&#xff0c;VMM之于虚拟机就…

一篇文章掌握WebService服务、工作原理、核心组件、主流框架

目录 1、WebService定义 解决问题&#xff1a; 2、WebService的工作原理 2.1 实现一个完整的Web服务包括以下步骤 2.2 调用方式 3、Web Service的核心组件 3.1 XML 3.2 SOAP 3.3 WSDL 3.4 UDDI 4、主流框架 4.1 AXIS(已淘汰) 4.2 XFire 4.3 CXF 5、Soap协议详解…

从DETR到Mask2former(2): 损失函数loss function

DETR的损失函数包括几个部分&#xff0c;如果只看论文或者代码&#xff0c;比较难理解&#xff0c;最好是可以打断点调试&#xff0c;对照着论文看。但是现在DETR模型都已经被集成进各种框架中&#xff0c;很难进入内部打断掉调试。与此同时&#xff0c;数据的label的前处理也比…

《动手学深度学习》学习笔记 第8章 循环神经网络

本系列为《动手学深度学习》学习笔记 书籍链接&#xff1a;动手学深度学习 笔记是从第四章开始&#xff0c;前面三章为基础知识&#xff0c;有需要的可以自己去看看 关于本系列笔记&#xff1a; 书里为了让读者更好的理解&#xff0c;有大篇幅的描述性的文字&#xff0c;内容很…

Vue3中动态组件使用

一&#xff0c;动态组件使用&#xff1a; 应用场景&#xff1a;动态绑定或切换组件 应用Vue3碎片&#xff1a; is 1.使用 a.组件A <div class"layout-base"><Button>红茶</Button> </div>a.组件B <div class"layout-base"&g…

python基础教程九 抽象一(函数初步)

1. 懒惰是种美德 前面编写的程序都很小&#xff0c;但如果要编写大型程序&#xff0c;你很快会遇到麻烦。想想看&#xff0c;如果你在一个地方编写了一些代码&#xff0c;但需要在另一个地方再次使用&#xff0c;该如何办?例如&#xff0c;假设你编写了一段代码&#xff0c;他…

Linux 常用的一些命令

目录 一、常用文件管理命令二、tmux 和 vimtmuxvim 三、[Shell语法](https://blog.csdn.net/weixin_43288201/article/details/105643692)四、git五、sshReference 一、常用文件管理命令 (1) ctrl c: 取消命令&#xff0c;并且换行 (2) ctrl u: 清空本行命令 (3) tab键&#x…

【MATLAB】SVMD_LSTM神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 SVMD-LSTM神经网络时序预测算法是一种结合了单变量经验模态分解&#xff08;Singular Value Decomposition&#xff0c;SVD&#xff09;和长短期记忆神经网络&#xff08;LSTM&#xff09…

前端基础:回顾es6相关知识

Author note(题记)&#xff1a; ECMAscript is international standard of javascript。 ECMA 是 js的国际标准版语言。 let and const 为什么之前用var现在需要用let&#xff0c;const呢&#xff1f; 其实就是因为规范作用域的问题。var的作用域无块级 for (var i 0; i <…

第二百七十二回

文章目录 1. 概念介绍2. 方法与类型2.1 使用方法2.2 常见类型 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何加载本地图片"相关的内容&#xff0c;本章回中将介绍如何获取文件类型.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章回…

常用的消息队列和中间件都有哪些

常用的消息队列和中间件有以下几种&#xff1a; RabbitMQ&#xff1a;RabbitMQ是一个开源的消息队列中间件&#xff0c;使用Erlang语言编写。它具有可靠性、灵活性和易用性的特点&#xff0c;支持多种消息协议。 Kafka&#xff1a;Kafka是一个高吞吐量的分布式发布订阅消息系统…