【Linux】第三十三站:日志
文章目录
- 一、实现一个简单的日志
- 1.简介
- 2.可变参数
- 3.错误等级
- 4.时间
- 5.打印每一条参数
- 6.与前面的一些代码搭配使用
- 二、完整代码
一、实现一个简单的日志
1.简介
我们运行代码的时候,我们希望有各种各样的运行时候的一些信息。这也就是日志
它一半有日志时间,日志的等级,日志的内容,文件的名称和行号。
对于日志等级一半有如下的
Info : 常规消息
Warning : 报警信息
Error : 比较严重了,可能需要立即处理
Fatal : 致命的
Debug : 调试
2.可变参数
关于可变参数我们主要用下面四个中的前三个

我们用如下代码来简单的介绍一下
int sum(int n, ...)
{//char* 可以去提取一个一个的参数va_list s;va_start(s, n);int SUM = 0;for(int i = 0; i < n; i++){SUM += va_arg(s,int);}va_end(s); //s = NULLreturn SUM;
}

在这段代码中,这个va_list其实就是一个char*类型的指针。
我们这个可变参数的函数至少需要带有一个参数。
因为我们传递参数的时候是从右向左传递的,所以我们是可以确定出栈顶的元素就是我们所确定的一个元素的地址
这个va_start是一个宏,代表着让s这个指针指向n。也就是栈顶
然后我们va_arg也是一个宏,它的作用是让s指针往栈里面移动第二个参数的类型大小,并解引用
va_end这个宏的作用是让指针置为空
最终我们就可以计算出这个sum的大小了。这个第一个参数我们一般是用作确定后面的参数有几个

像我们所谓的printf里面也是类似的方法,不过要注意的时候,因为第一个参数是字符串参数,它是可以通过解析字符串里面的%s等格式化控制来确定后面有几个参数的,从而完成依次的替换的。
3.错误等级
我们现在来设计我们的日志的函数
只需要下面这样即可
void logmessage(int level, char* format, ...)
{}
首先对于等级,我们可以直接用宏来表示
#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4
4.时间
接下是时间,我们可以使用时间戳,不过其实还有其他的系统调用接口

#include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
第一个参数是一个结构体,里面的两个参数它可以获取秒,微秒。
第二个参数与时区相关,我们可以不用管,直接置为NULL即可
还有一个接口是这样的
#include <time.h>
struct tm *localtime(const time_t *timep);

这个函数的功能是将时间戳转化为一个结构体,这个结构体里面有时分秒月年等信息
我们可以简单的应用一下

我们会注意到时间存在一定的问题,这是因为它是从1900年开始计时的,这个月是从0开始的,所以我们可以进行一下调整

如下所示就正确了
void logmessage(int level, char* format, ...)
{time_t t = time(nullptr);struct tm* ctime = localtime(&t);printf("%d-%d-%d %d:%d:%d\n",ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday, ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
}

5.打印每一条参数
我们可以用vsnprintf函数

最终我们的代码为如下
void logmessage(int level, char* format, ...)
{char leftbuffer[SIZE];time_t t = time(nullptr);struct tm* ctime = localtime(&t);snprintf(leftbuffer, SIZE,"[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(), ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday, ctime->tm_hour, ctime->tm_min, ctime->tm_sec);char rightbuffer[SIZE];va_list s;va_start(s, format);vsnprintf(rightbuffer, SIZE, format, s);va_end(s);char logtxt[2*SIZE];snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);std::cout << logtxt << std::endl;
}

6.与前面的一些代码搭配使用
如下所示,这里我们就引进了我们刚刚使用的日志

运行结果如下,我们现在可以看到,这样子就规范多了

二、完整代码
如下代码所示,我们再将前面的日志给封装成一个类,然后实现一下分类打印,向文件打印,向显示屏打印等等功能。
#pragma once#include <stdarg.h>
#include <iostream>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>#define SIZE 1024#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4#define Screen 1
#define Onefile 2
#define Classfile 3#define LogFile "log.txt"class Log
{
public:Log(){printMethod = Screen;path = "./log/";}void Enable(int method){printMethod = method;}std::string levelToString(int level){switch(level){case Info : return "Info";case Debug : return "Debug";case Warning : return "Warning";case Error : return "Error";case Fatal : return "Fatal";default : return "None";}}void operator()(int level, char* format, ...){char leftbuffer[SIZE];time_t t = time(nullptr);struct tm* ctime = localtime(&t);snprintf(leftbuffer, SIZE,"[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(), ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday, ctime->tm_hour, ctime->tm_min, ctime->tm_sec);char rightbuffer[SIZE];va_list s;va_start(s, format);vsnprintf(rightbuffer, SIZE, format, s);va_end(s);char logtxt[2*SIZE];snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);//std::cout << logtxt << std::endl;PrintLog(level, logtxt);} // void logmessage(int level, char* format, ...)// {// char leftbuffer[SIZE];// time_t t = time(nullptr);// struct tm* ctime = localtime(&t);// snprintf(leftbuffer, SIZE,// "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(), // ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday, ctime->tm_hour, ctime->tm_min, ctime->tm_sec);// char rightbuffer[SIZE];// va_list s;// va_start(s, format);// vsnprintf(rightbuffer, SIZE, format, s);// va_end(s);// char logtxt[2*SIZE];// snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);// //std::cout << logtxt << std::endl;// PrintLog(level, logtxt);// } void PrintLog(int level, const std::string& logtxt){switch(printMethod){case Screen:std::cout << logtxt << std::endl;break;case Onefile:PrintOnefile(LogFile , logtxt);break;case Classfile:PrintClassfile(level, logtxt);break;default: break;}}void PrintOnefile(const std::string& filename, const std::string& logtxt){std::string logname = path + filename;int fd = open(logname.c_str(), O_WRONLY|O_CREAT|O_APPEND, 0666);if(fd < 0){return;}write(fd, logtxt.c_str(), logtxt.size());close(fd);}void PrintClassfile(int level, const std::string& logtxt){std::string filename = LogFile;filename += ".";filename += levelToString(level);PrintOnefile(filename, logtxt);}~Log(){}
private:int printMethod;std::string path;
};
相关文章:
【Linux】第三十三站:日志
文章目录 一、实现一个简单的日志1.简介2.可变参数3.错误等级4.时间5.打印每一条参数6.与前面的一些代码搭配使用 二、完整代码 一、实现一个简单的日志 1.简介 我们运行代码的时候,我们希望有各种各样的运行时候的一些信息。这也就是日志 它一半有日志时间&…...
MVC和MVVM区别和VUE关系
MVC(Model-View-Controller)和 MVVM(Model-View-ViewModel)是两种常见的前端架构模式,它们的主要区别在于处理业务逻辑和数据操作的方式。 MVC中,View(视图)可以直接访问Model&…...
vue3自定义按钮点击变颜色实现(多选功能)
实现效果图: 默认选中第一个按钮,未选中按钮为粉色,点击时颜色变为红色 利用动态类名,当定义isChange数值和下标index相同时,赋予act类名,实现变色效果 <template><div class"page"&…...
Redis的key过期策略是怎么实现的
这是一道经典的Redis面试题,一个Redis中可能存在很多很多的key,这些key中可能有很大一部分都有过期时间,此时Redis服务器咋知道哪些key已经过期,哪些还没过期呢? 如果直接遍历所有的key,这显然是行不通的&…...
vue+elenemt分页+springboot
目录 1、编写模板 2、发请求调接口 3、后端返回数据 1.编写实体类 2、UserController 3、Userservice接口 4、(mapper接口)UserMapper 5、xml 1、编写模板 <!-- 搜素框 --><el-input placeholder"请输入姓名" v-model"ke…...
C++ :命名空间域
目录 冲突与命名: 举个例子: 全局与局部: 域作用限定符: 命名空间域: 冲突与命名: 在C语言中,我们通常会使用stdlib.h 而stdlib.h 本质上是一个函数的库,在程序中使用的大多数…...
提升网站关键词排名的工具
随着互联网的蓬勃发展,网站的关键词排名成为衡量网站流量和曝光度的重要指标。在这个竞争激烈的数字时代,站在搜索引擎结果的前列变得至关重要。为了实现这一目标,合理利用关键词排名优化工具是必不可少的。本文将重点介绍147SEO软件…...
ICMP控制消息 汇总
控制消息由 类型 字段中的值标识。代码 字段给出了消息的附加上下文信息。自协议首次引入以来,一些控制消息已被弃用。 重要的ICMP Control Message控制信息 类型码状态描述0 –回声回复:140回声回复(用于ping)1和2未分配已预留3 …...
C#,入门教程(22)——函数的基础知识
上一篇: C#,入门教程(21)——命名空间(namespace)与程序结构的基础知识https://blog.csdn.net/beijinghorn/article/details/124140653 一、函数的基本概念 一个软件的结构大体如下: 大厦application: a plaza { --…...
已经30了,5年多,只会功能测试的怎么办?
🍅 视频学习:文末有免费的配套视频可观看 🍅 关注公众号【互联网杂货铺】,回复 1 ,免费获取软件测试全套资料,资料在手,涨薪更快 这两天一直在和网易的朋友聊软件测试的发展,这一行的…...
什么是UML?有什么用?
2、什么是UML?有什么用? UML 是 Unified Model Language的缩写,中文是统一建模语言,是由一整套图表组成的标准化建模语言。 UML 是一种统一建模语言,一种图标式语言(画图的) UML 不是只有 Java 中使用&…...
盘点好用内容合规监测工具
网页敏感内容监测 Web Purify 由 WebPurify 提供,这是一个专门从事内容审核和过滤服务的公司。 核心功能 ● 文本审核:加强脏话过滤,标记仇恨言论、偏执、性挑逗等 ● 图片审核:让个人资料照片、社交应用程序、产品定制远离令…...
CC工具箱使用指南:【查找锐角】
一、简介 在面要素中,尖锐角往往是有问题的地方。 在一系列空间分析后,通常会遗留下来部分尖锐角,需要手动处理。 但是人工去找出这些尖锐角又比较麻烦,这个工具的目的就是找出面要素边界的尖锐角。 二、工具参数介绍 右键点击…...
kafka消费相关问题(GPT回答版本)
kafka消费相关问题(GPT回答版本) 在Java中,要避免重复消费Kafka消息,可以使用以下方法 1. 使用消费者组: 在设置Kafka消费者时,可以指定一个消费者组。一个消费者组中可以有多个消费者实例,每…...
【C++】string的基本使用二
我们接着上一篇的迭代器说起,迭代器不只有正向的,还有反向的,就是我们下边的这两个 它的迭代器类型也是不同的 rbegin就是末尾,rend就是开头,这样我们想遍历一个string对象的话就可以这样做 int main() {string s1(…...
MATLAB解决考研数学一题型(上)
闲来无事,情感问题和考研结束后的戒断反应比较严重,最近没有什么写博文的动力,抽空来整理一下考研初试前一直想做的工作——整理一下MATLAB解决数学一各题型的命令~ 本贴的目录遵循同济版的高数目录~ 目录 一.函数与极限 1.计算双侧极限 2…...
Vue以弹窗形式实现导入功能
目录 前言正文 前言 由于个人工作原因,偏全栈,对于前端的总结还有些初出茅庐,后续会进行规整化的总结 对应的前端框架由:【vue】avue-crud表单属性配置(表格以及列) 最终实现的表单样式如下:…...
分布式锁原理及实现
目录 一、锁的使用场景 二、如何实现控制? 三、单台服务器使用锁的场景 四、分布式锁 五、Redis 实现分布式锁及存在问题 六、Redisson 实现分布式锁 七、定时任务+锁 一、锁的使用场景 1. 控制定时任务执行 定时任务多次执行浪费资源ÿ…...
蓝桥杯官网填空题(海盗与金币)
题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 12名海盗在一个小岛上发现了大量的金币,后统计一共有将近5万枚。 登上小岛是在夜里,天气又不好。由于各种原因,有的海盗偷拿了很…...
JavaScript 中JSON 字符串和对象之间的转换。
JSON.stringify() 方法(对象转换为 JSON 字符串) 用于将 JavaScript 对象转换为 JSON 字符串。 它接受一个 JavaScript 对象作为参数,并返回对应的 JSON 字符串表示。例如: const obj { name: John, age: 25 }; const jsonStr…...
在数字记忆成为个人财富的时代,如何让微信对话成为永恒珍藏?
在数字记忆成为个人财富的时代,如何让微信对话成为永恒珍藏? 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_…...
别再让CPU干苦力了!手把手教你用John The Ripper的GPU加速命令,破解效率翻倍
解锁GPU潜能:John The Ripper高效破解实战指南 在安全测试领域,哈希破解速度往往决定着项目的成败。传统CPU破解方式在面对复杂加密算法时显得力不从心,而现代GPU凭借其并行计算能力,能将破解效率提升数十倍甚至上百倍。本文将带…...
大模型求职避坑指南:收藏这份三层准备路径,轻松拿下高薪Offer!
本文针对大模型求职者,揭示了常见误区并提供了清晰的三层准备路径:基础能力、核心竞争力、差异化优势。文章强调刷题和背概念只是入门,真正重要的是项目经历,要能深入回答五个关键问题:项目背景、技术选型、难点解决、…...
如何在Inkscape中快速实现专业级光线追踪?终极免费光学设计指南
如何在Inkscape中快速实现专业级光线追踪?终极免费光学设计指南 【免费下载链接】inkscape-raytracing An extension for Inkscape that makes it easier to draw optical diagrams. 项目地址: https://gitcode.com/gh_mirrors/in/inkscape-raytracing Inks…...
告别黑盒渲染!用Nvdiffrast手把手教你从零搭建可微渲染管线(PyTorch版)
从零构建可微渲染管线:Nvdiffrast深度实践指南 在计算机图形学与深度学习交叉领域,可微渲染技术正掀起一场革命。传统渲染管线如同黑盒,输入3D场景参数,输出2D图像,但反向路径却被阻断——这正是Nvdiffrast要解决的痛点…...
从OBD到功能安全:聊聊Autosar Dem模块里故障数据的‘生老病死’与内存管理策略
从OBD到功能安全:Autosar Dem模块中故障数据的生命周期与内存博弈 当一辆现代汽车在道路上飞驰时,它的电子控制单元(ECU)内部正上演着无数微观的"生存游戏"。在Autosar Dem模块的内存空间中,每一个故障数据都如同有生命的个体&…...
Taskbar11完全指南:解锁Windows 11任务栏自定义的终极解决方案
Taskbar11完全指南:解锁Windows 11任务栏自定义的终极解决方案 【免费下载链接】Taskbar11 Change the position and size of the Taskbar in Windows 11 项目地址: https://gitcode.com/gh_mirrors/ta/Taskbar11 还在为Windows 11任务栏的严格限制感到困扰吗…...
终极 Node.js 路径管理神器:module-alias 完全指南
终极 Node.js 路径管理神器:module-alias 完全指南 【免费下载链接】module-alias Register aliases of directories and custom module paths in Node 项目地址: https://gitcode.com/gh_mirrors/mo/module-alias 你是否厌倦了在 Node.js 项目中看到像 requ…...
LabVIEW 2021生成EXE后报表报错?手把手教你添加NIReport.llb和LVClass文件
LabVIEW报表生成避坑指南:从源码到EXE的完整解决方案 在LabVIEW开发过程中,报表生成功能是许多工程师不可或缺的工具。然而,当我们将精心编写的程序打包成可执行文件(EXE)时,常常会遇到一个令人头疼的问题&…...
面向对象分析(OOA)的第一个步骤是**识别问题域中的对象和类**(也称为“识别对象与类”或“确定问题域中的概念类”)
面向对象分析(OOA)的第一个步骤是识别问题域中的对象和类(也称为“识别对象与类”或“确定问题域中的概念类”)。 这一步要求分析师深入理解用户需求和现实世界的问题背景,通过用例分析、领域建模、名词提取等方法&…...
