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

【Linux】Linux下的日志(日常级)

日志是日后工作中非常重要的一部分,现在写一份简单的日志项目可以帮助我们熟悉并理解原理。

目录

  • 设计思路:
  • 一些实现细节:
  • 代码:
  • 日志的使用方法:

设计思路:

图示是我们的最终目的。
在这里插入图片描述

  1. 设计一个类,这个类中存放着以上数据。
  2. 设计一个Log类,这个类中有一个Print函数进行按照指定格式(文件或显示器)输出,我们向这个成员函数中传参进行打印。

一些实现细节:

  • 获取时间:可以使用time函数获取时间戳,由localtime进行格式转换为我们指定的样式。
  • printf的格式输出:printf("%02d", 10);代表域宽为2,数字在右边,空余补0。
  • 可变参数的处理:

有很多的方法:
比如自己逐个提取或者利用现有的接口提取。
这并不是重点,会用即可。
可变参数的博客。

我们还是最好使用接口进行提取,避免看很多麻烦的操作,那就是在这里插入图片描述
与snprintf使用方法类似,可以直接将转换后的直接写入指定字符串中!

  • 关于封装:不同功能的函数可以在成员函数与非成员函数之间自由切换(根据对成员变量的需求…)
  • 宏中的可变参数:这个__VA_ARGS__链接包含了一些宏的用法。

代码:

#pragma once#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fstream>
#include <pthread.h>namespace log_ns
{#define SCREE_TYPE 1
#define FILE_TYPE 2const char *gfilename = "log.txt";pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER;enum{DEBUG = 1,INFO,WARNNING,ERROR,FATAL};std::string LevelTostrint(int level){switch (level){case DEBUG:return "DEBUG";break;case INFO:return "INFO";break;case WARNNING:return "WARNING";break;case ERROR:return "ERROR";break;case FATAL:return "FATAL";break;default:return "Unknow";}}class LogMessage{public:std::string _level;pid_t _id;std::string _filaname;int _filenumber;std::string _curr_time;std::string _logmsg;};std::string GetCurTime(){time_t timestamp = time(nullptr);tm *ptm = localtime(&timestamp);char buffer[128];snprintf(buffer, sizeof(buffer), "%d/%02d/%02d %02d:%02d:%02d",ptm->tm_year + 1900,ptm->tm_mon + 1,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec);return buffer;}class Log{public:Log(int type = SCREE_TYPE, std::string FILEName = gfilename): _type(type), _FILEName(gfilename){}~Log(){}void Print(int level, const char *filename, int filenumber, const char *msg, ...){LogMessage lmsg;lmsg._level = LevelTostrint(level);lmsg._id = getpid();lmsg._filaname = filename;lmsg._filenumber = filenumber;lmsg._curr_time = GetCurTime();// 处理可变参数va_list ap;va_start(ap, msg);char buffer[1024];vsnprintf(buffer, sizeof(buffer), msg, ap);lmsg._logmsg = buffer;va_end(ap);// 打印到指定文件pthread_mutex_lock(&gmutex);Flush(lmsg);pthread_mutex_unlock(&gmutex);}void Enable(int type){_type = type;}void FlushScree(const LogMessage &logMsg){printf("[%s][%d][%s][%d][%s] %s",logMsg._level.c_str(),logMsg._id,logMsg._filaname.c_str(),logMsg._filenumber,logMsg._curr_time.c_str(),logMsg._logmsg.c_str());}void FlushFILE(const LogMessage &logMsg){std::ofstream out(_FILEName.c_str(), std::fstream::app | std::fstream::out);if (!out.is_open()){perror("open fail");return;}char buffer[2048];snprintf(buffer, sizeof(buffer), "[%s][%d][%s][%d][%s] %s",logMsg._level.c_str(),logMsg._id,logMsg._filaname.c_str(),logMsg._filenumber,logMsg._curr_time.c_str(),logMsg._logmsg.c_str());out << buffer;out.close();}void Flush(const LogMessage &logMsg){switch (_type){case SCREE_TYPE:FlushScree(logMsg);break;case FILE_TYPE:FlushFILE(logMsg);break;}}private:int _type;std::string _FILEName;};Log lg;
#define LOG(LEVEL, format, ...)                                     \do                                                              \{                                                               \lg.Print(LEVEL, __FILE__, __LINE__, format, ##__VA_ARGS__); \} while (0)#define EnableScree()          \do                         \{                          \lg.Enable(SCREE_TYPE); \} while (0)#define EnableFILE()          \do                        \{                         \lg.Enable(FILE_TYPE); \} while (0)
}

整体来说并不是很难,但是这里的一些知识点对于有些同学过于偏僻,导致了整个处理过程有点无措。

日志的使用方法:

我们定义了宏,就避免了一些繁琐的步骤,比如创建一个对象再去调用。

另外,我们的宏也提供了改变输出文件的,使用也更方便。

#include "Log.hpp"using namespace log_ns;int main()
{EnableScree();LOG(DEBUG, "hello world%d\n", 666);EnableFILE();LOG(DEBUG, "hello world%d\n", 666);LOG(DEBUG, "hello world%d\n", 666);LOG(DEBUG, "hello world%d\n", 666);return 0;
}

当然,创建对象去调用Print也是可以的。

完~

相关文章:

【Linux】Linux下的日志(日常级)

日志是日后工作中非常重要的一部分&#xff0c;现在写一份简单的日志项目可以帮助我们熟悉并理解原理。 目录 设计思路&#xff1a;一些实现细节&#xff1a;代码&#xff1a;日志的使用方法&#xff1a; 设计思路&#xff1a; 图示是我们的最终目的。 设计一个类&#xff0…...

手把手教你如何在Linux上轻松安装Python,告别编程入门难题

导语&#xff1a; Python作为当下最热门的编程语言之一&#xff0c;受到了越来越多人的喜爱。对于Linux用户来说&#xff0c;掌握如何在Linux上安装Python至关重要。今天&#xff0c;就让我带领大家一步步在Linux上安装Python&#xff0c;让你轻松迈入编程世界&#xff01; 一…...

XSS-labs靶场(超详解)1-20关——附原码

level1 原码 <!DOCTYPE html><!--STATUS OK--><html> <head> <meta http-equiv"content-type" content"text/html;charsetutf-8"> <script> window.alert function() { confirm("完成的不错&#xff0…...

【网络安全】LockBit病毒入侵揭秘:如何防范与应对

文章目录 前言 主要特征攻击手段演进历程主要威胁防范与对策 如何入门学习网络安全【黑客】 【----帮助网安学习&#xff0c;以下所有学习资料文末免费领取&#xff01;----】 大纲学习教程面试刷题 资料领取 前言 在数字时代&#xff0c;随着科技的飞速发展&#xff0c;网络…...

《开源大模型食用指南》适合中国宝宝的部署教程,基于Linux环境快速部署开源大模型

本项目是一个围绕开源大模型、针对国内初学者、基于 AutoDL 平台的中国宝宝专属大模型教程&#xff0c;针对各类开源大模型提供包括环境配置、本地部署、高效微调等技能在内的全流程指导&#xff0c;简化开源大模型的部署、使用和应用流程&#xff0c;让更多的普通学生、研究者…...

体验教程:通义灵码陪你备战求职季

本场景将带大家体验在技术面试准备场景下&#xff0c;如何通过使用阿里云通义灵码实现高效的编程算法题练习 、代码优化、技术知识查询等工作&#xff0c;帮助开发者提升实战能力&#xff0c;更加从容地应对面试挑战。主要包括&#xff1a; 1、模拟题练习&#xff1a;精心挑选…...

(070)爬楼梯

思路&#xff1a;一次爬一个或者一次爬两个楼梯,终止条件&#xff0c;即是当n1或n2时&#xff0c;完成操作&#xff0c;当n>2时&#xff0c;总方法就等于一次爬一个楼梯的方法数加上一次爬两个楼梯的方法数。 解法一&#xff1a;递归解法 if(n 1)return 1;if(n 2)return 2…...

el-table 表格序号列前端实现递增,切换分页不从头开始

<el-table-column type"index" width"55" label"序号" :index"hIndex"> </el-table-column> 分页 <el-pagination size-change"handleSizeChange" current-change"handleCurrentChange"> <…...

NSSCTF-Web题目27(Nginx漏洞、php伪协议、php解析绕过)

目录 [HNCTF 2022 WEEK2]easy_include 1、题目 2、知识点 3、思路 [NSSRound#8 Basic]MyDoor 4、题目 5、知识点 6、思路 [HNCTF 2022 WEEK2]easy_include 1、题目 2、知识点 nginx日志漏洞执行系统命令 3、思路 打开题目&#xff0c;出现源码 题目要我们上传一个fi…...

分割损失:Dice vs. IoU

NSDT工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 对于医学影像分割&#xf…...

SpringBoot整合Juint,ssm框架

目录 SpringBoot整合Juint 1.导入相关的依赖 2.创建测试类&#xff0c;使用注解SpringBootTest SpringBoot整合ssm框架 1.使用脚手架创建Spring项目 2.修改pom.xml 我先修改了SpringBoot的版本&#xff0c;修改为2.3.10.RELEASE&#xff0c;因为SpringBoot版本太高会出现…...

基于supervisor制作基于环境变量配置的redis

背景&#xff1a; redis 的镜像很多很多&#xff0c;但都需要直接修改配置文件&#xff0c;不符合我们公司当前环境变量解决一切容易配置的思路。 材料&#xff1a; 1、CentOS-Base.repo [base] nameCentOS-$releasever enabled1 failovermethodpriority baseurlhttp://mirr…...

动态规划part01 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯

509. 斐波那契数 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n) F(n - 1) F(n - 2)&#xff0c;其中 …...

CSS实现图片边框酷炫效果

一、前言 我们在浏览一些网页时&#xff0c;经常会看到一些好看酷炫的元素边框效果&#xff08;如下图&#xff09;&#xff0c;那么这些效果是怎么实现的呢&#xff1f;我们知道&#xff0c;一般的边框&#xff0c;要么是实线&#xff0c;要么是虚线&#xff08;点状&#xf…...

遇到 MySQL 死锁问题如何解决?

终于来到死锁检查线程的第三步&#xff0c;可以解决死锁了。 作者&#xff1a;操盛春&#xff0c;爱可生技术专家&#xff0c;公众号『一树一溪』作者&#xff0c;专注于研究 MySQL 和 OceanBase 源码。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0…...

Pyinstaller打包OSError: could not get source code【终极解决】

pyinstaller 打包的时候&#xff0c;发现只要是torch.jit.script装饰的函数&#xff0c;会报以下错误&#xff1a; Traceback (most recent call last):File "torch/_sources.py", line 25, in get_source_lines_and_fileFile "inspect.py", line 1123, i…...

【计算机毕业设计】707高校宿舍管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…...

从C++看C#托管内存与非托管内存

进程的内存 一个exe文件&#xff0c;在没有运行时&#xff0c;其磁盘存储空间格式为函数代码段全局变量段。加载为内存后&#xff0c;其进程内存模式增加为函数代码段全局变量段函数调用栈堆区。我们重点讨论堆区。 托管堆与非托管堆 C# int a10这种代码申请的内存空间位于函…...

Linux进程间通信--IPC之无名管道

进程间通信&#xff08;IPC&#xff0c;InterProcess Communication&#xff09;是指在不同进程之间传播或交换信息。 IPC的方式通常有管道&#xff08;包括无名管道和命名管道&#xff09;、消息队列、信号量、共享存储、Socket、Streams支持不同主机上的两个进程的IPC。...

Oracle19c数据库system密码锁定

一、在oracle 19c数据库中&#xff0c;cdb中system用户被锁定&#xff0c;locked 二、所在的pdb中的system用户状态是正常的&#xff0c;但不可用&#xff0c;连接的时候提示账号已锁定 三、解决 在cdb中将system用户解锁。 alter user system account unlock;...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…...

微服务通信安全:深入解析mTLS的原理与实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言&#xff1a;微服务时代的通信安全挑战 随着云原生和微服务架构的普及&#xff0c;服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...