日志的介绍及简单实现

news2024/9/17 7:17:36

个人主页:Lei宝啊 

愿所有美好如期而遇


目录

日志是什么?

为什么需要日志?

实现一个简单日志

时间戳

clock_gettime

time & localtime

可变模板参数(使用C语言),va_start & va_end &  vsprintf

宏  __LINE__ & __FILE__ & ##__VA_ARGS__

小技巧

代码实现


日志是什么?

日志(Log) 是记录系统、应用或设备在运行过程中产生的各种事件、状态、错误等信息的文件或数据流。这些日志信息对于了解系统的运行状况、排查问题、优化性能以及安全审计等方面都非常重要。

为什么需要日志?

  1. 问题排查:当系统或应用出现故障时,通过查看日志可以快速定位问题发生的原因和位置,从而加快故障解决的速度。
  2. 性能监控:通过分析日志,可以了解系统的运行状况,包括请求量、响应时间、资源使用情况等,从而发现性能瓶颈并进行优化。
  3. 安全审计:日志中记录了用户的操作行为、系统的访问情况等信息,这些信息可以用于安全审计,检查是否有异常操作或入侵行为。
  4. 合规性要求:在某些行业或地区,法律法规要求企业或组织必须保留一定期限的日志记录,以便在需要时进行审计或调查。
  5. 系统恢复:在某些情况下,如系统崩溃或数据丢失时,可以通过日志中的信息来恢复系统或数据。
  6. 版本追踪:对于软件来说,日志可以记录软件的版本变化、功能更新等信息,方便开发人员进行版本追踪和回滚。
  7. 用户行为分析:通过分析用户的操作日志,可以了解用户的使用习惯、喜好等信息,从而优化产品设计和提高用户体验

实现一个简单日志

实现日志前,我们先介绍几个函数以及几个小技巧:

时间戳

时间戳(Timestamp) 是一个表示特定时间点的数字或字符串。它通常表示从某个固定时间点(1970年1月1日00:00:00 UTC,也被称为Unix纪元或Unix时间戳)到特定事件发生时经过的秒数。

我们在Linux系统中有这样几个函数:

clock_gettime

第一个参数我们填CLOCK_REALTIME即可,表示系统实时时间。

#include <stdio.h>  
#include <time.h>  
  
int main() 
{  
    struct timespec ts;  

    if (clock_gettime(CLOCK_REALTIME, &ts) == 0) 
    {  
        printf("Current time: %ld.%09ld\n", ts.tv_sec, ts.tv_nsec);  
    } 
    else 
    {  
        perror("clock_gettime");  
        return 1;  
    }  

    return 0;  
}
time & localtime

time函数获取当前时间的时间戳。

locltime函数将时间戳转换成我们平时使用的年月日时分秒。 

可变模板参数(使用C语言),va_start & va_end &  vsprintf
void message(const char* format, ...){}  //可变模板参数

我们如何获取可变模板参数中的参数呢?

使用vsprintf函数:

这个函数用来将可变模板参数以format格式,将其写入到str指向的char类型数组中。 

而可变模板参数,将会使用va_list类型变量指向,实际上他是一个void*类型指针,我们定义后,还需要使用函数初始化以及销毁。

va_list args;
va_start(&args, format);
//...
va_end(&args);

va_start,初始化va_list类型变量,last就是可变模板参数左边第一个参数,这样这个函数就可以将args初始化为指向可变模板参数的指针。

va_end,将va_list类型变量清空。

char buffer[1024];
vsprintf(buffer, format, args); 
//这样就将可变模板参数中的内容以我们希望的格式获取到
//类似于printf("%d %s", xx,xx); "%d %s"就是格式,后面就是可变模板参数
宏  __LINE__ & __FILE__ & ##__VA_ARGS__
  • __LINE__ 当前代码所在行数
  • __FILE__ 当前代码所在文件
  • __VA_ARGS__    C99及C++支持的宏可变模板参数

 //##__VA_ARGS__ 中的 ## 操作符。当 __VA_ARGS__ 为空时(即没有额外的参数),
  ## 操作符会将其前面的逗号去掉,以防止在编译时产生语法错误。

简单来说,就是没有可变模板参数,只有格式,那么格式后面还有个逗号,##操作符会将其去掉。

小技巧

在宏替换中,关于语句的替换,以及多语句的替换,我们可以将其写在do{}while(0)中。

如果上述讲解没有理解,那么可以在下面的代码中进行理解,所有讲解都会在下面代码中有体现。

代码实现

#include <iostream>
#include <string>
#include <ctime>
#include <cstdarg>
#include <pthread.h>
#include <fstream>
using namespace std;

//##__VA_ARGS__ 中的 ## 操作符。当 __VA_ARGS__ 为空时(即没有额外的参数),
  ## 操作符会将其前面的逗号去掉,以防止在编译时产生语法错误。
#define Log(level, format, ...) do{LogMessage(__FILE__, __LINE__, level, 
                                  format, ##__VA_ARGS__);}while(0)
#define YSave do{IsSave = true;}while(0)
#define NSave do{IsSave = false;}while(0)

pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
string file_name_path = "log.txt";
bool IsSave = false; 

enum Level
{
    Debug = 0,
    Info,
    Warning,
    Error,
    Fatal
};

string LevelToString(int level)
{
    string name;
    switch (level)
    {
    case Debug   : return "Debug";
    case Info    : return "Info";
    case Warning : return "Warning";
    case Error   : return "Error";
    case Fatal   : return "Fatal";
    default: return "阿西吧";
    }
}

string TimeToString()
{
    time_t Time; time(&Time);
    struct tm* attr = localtime(&Time);

    char buffer[1024];
    sprintf(buffer,"%4d-%2d-%2d %2d:%2d:%2d",
                    attr->tm_year+1900,
                    attr->tm_mon+1,
                    attr->tm_mday,
                    attr->tm_hour,
                    attr->tm_min,
                    attr->tm_sec);
    
    return buffer;
}

void Save(string ret)
{
    fstream out(file_name_path.c_str(), ios::app); 
    if(out.is_open())
    {
        out << ret;
    }
    else
    {
        std::cerr << "无法打开文件: " << file_name_path << std::endl;
    }
    out.close();
}

// 2. 日志是有格式的
// 日志等级 时间 代码所在的文件名/行数 日志的内容
void LogMessage(string filename, int line, int level, const char* format, ...)
{
    string levelname = LevelToString(level);
    string timename = TimeToString();

    va_list args;           //一个void*指针
    va_start(args, format); //将args初始化,指向可变参数列表
    char buffer[1024]; vsprintf(buffer, format, args);
    va_end(args);

    string ret = "[" + filename + "]" + "[" + "line: " + to_string(line)
                   + "]" + "[" + levelname + "]" + "[" + timename + "]" 
                   + "[" + buffer + "]" + "\n";
    
    pthread_mutex_lock(&log_mutex);
    if(IsSave)
    {
        Save(ret);
    }
    else
    {
        cout << ret;
    }
    pthread_mutex_unlock(&log_mutex);
}




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

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

相关文章

推荐一款媒体影音嗅探神器—Chrome扩展插件(猫抓cat-catch)

目录 1.1、前言1.2、下载地址1.3、github Releases 版本说明1.4、安装步骤1.5、猫抓插件常规设置1.5.1、设置抓取文件的类型1.5.2、设置抓取文件的后缀名 1.1、前言 我们在日常上网的过程中&#xff0c;很多音频、视频网站下载资源都非常不方便&#xff0c;要么需要安装客户端&…

【高阶数据结构】AVL树的旋转与底层(C++实现)

1.AVL树的概念及作用 2.AVL树插入数据的规则 1.按照搜索树的规则插入&#xff0c;然后更新父亲的平衡因子 2.更新父亲的平衡因子后&#xff0c;如果出现一下三种情况需要进行相应处理 3.AVL树的旋转 3.1右单旋 右单旋的所有情况可以抽象为上图&#xff1a;图中&#xff0c;a,…

【识人】感情与交友中,如何判断一个人的性格,以及是否值得交往和相处

【识人】感情与交友中&#xff0c;如何判断一个人的性格&#xff0c;以及是否值得交往和相处 文章目录 序言正文1、学会筛选&#xff0c;贴标签&#xff0c;学会区别对待&#xff0c;2、男生女生一定要在年轻的时候学会对外在祛魅3、培养付出意识&#xff0c;学会顶风相见。4、…

protobuf —— 认识和安装

protobuf —— 认识和安装 什么是序列化和反序列化有哪些常见的什么是序列化和反序列化工具Protobuf安装安装依赖开始安装 连接动态库一些遗留问题 我们今天来看一个序列化和反序列化的工具&#xff1a;protobuf。 什么是序列化和反序列化 序列化&#xff08;Serialization&a…

Yolov9调用COCOAPI生成APs,APm,APl

最近在做小目标检测的东西&#xff0c;因为后期毕业论文需要&#xff0c;所以开始使用Yolov9模型&#xff0c;运行val.py的时候不会自己产生小目标的AP指标&#xff0c;所以研究了一下&#xff0c;步骤非常简单&#xff1a; 第一步&#xff1a; 在数据集中生成json格式的Annota…

【LLM多模态】综述Visual Instruction Tuning towards General-Purpose Multimodal Model

note 文章目录 note论文1. 论文试图解决什么问题2. 这是否是一个新的问题3. 这篇文章要验证一个什么科学假设4. 有哪些相关研究&#xff1f;如何归类&#xff1f;谁是这一课题在领域内值得关注的研究员&#xff1f;5. 论文中提到的解决方案之关键是什么&#xff1f;6. 论文中的…

AIGC时代算法工程师的面试秘籍(2024.4.29-5.12第十三式) |【三年面试五年模拟】

写在前面 【三年面试五年模拟】旨在整理&挖掘AI算法工程师在实习/校招/社招时所需的干货知识点与面试方法&#xff0c;力求让读者在获得心仪offer的同时&#xff0c;增强技术基本面。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&#x1f4aa; 欢迎大家关注Rocky…

LVS精益价值管理系统 DownLoad.aspx 任意文件读取漏洞复现

0x01 产品简介 LVS精益价值管理系统是杭州吉拉科技有限公司研发的一款专注于企业精益化管理和价值流优化的解决方案。该系统通过集成先进的数据分析工具、可视化的价值流映射技术和灵活的流程改善机制&#xff0c;帮助企业实现高效、低耗、高质量的生产和服务。 0x02 漏洞概述…

【数据库】基于PyMySQL连接并使用数据库(代码示例)

这里写目录标题 前言1、安装PyMySQL2、打开要连接的数据库3、创建数据库连接4、获取数据库版本5、新建数据库表6、向表中插入数据7、查询表中的相关记录8、更新表中的相关记录9、删除表中的相关记录10、关闭游标和连接完整代码 前言 本文演示了如何基于PyMySQL使用代码来创建数…

异步获取线程执行结果,JDK中的Future、Netty中的Future和Promise对比

JDK中的Future和Netty中的Future、Promise的关系 三者源头追溯 Netty中的Future与JDK中的Future同名&#xff0c;但是是两个不同的接口。Netty中的Future继承自JDK的Future&#xff0c;而Promise又对Netty中的Future进行了扩展。 JDK中的Future源自JUC并发包&#xff1a; Net…

打卡信奥刷题(19)用Scratch图形化工具信奥B3972 [语言月赛 202405] 二进制 题解

进制转换是经典的编程题&#xff0c;尤其是10进制转换为2进制。方法是拿给定的数&#xff0c;不断地除2&#xff0c;将余数放在对应的位置&#xff0c;剩下的数为对应数除2向下取整 [语言月赛 202405] 二进制 题目描述 在介绍十进制转二进制的篇目中&#xff0c;我们总会看到…

一文读懂:http免费升级https

背景&#xff1a; 随着现在全民网络安全意识的日益提升&#xff0c;各个网站需要实现的https数量也随之提升&#xff0c;那么如何将原本网站的http访问方式升级为https呢&#xff1f; 该内容为如何免费将网站的http访问升级为https访问 论https的加密逻辑&#xff1a; 步骤 …

【计算机网络】初识Tcp协议

&#x1f4bb;文章目录 &#x1f4c4;前言Tcp基础概念Tcp 的报文格式三次握手四次挥手 Tcp的滑动窗口机制概念超时重传机制高速重传 TCP传输控制机制流量控制拥堵控制慢启动 Tcp的性能优化机制延迟应答捎带应答 &#x1f4d3;总结 &#x1f4c4;前言 TCP三次握手、四次挥手&…

element-ui 实现输入框下拉树组件(2024-05-23)

用element-ui的 el-input&#xff0c;el-tree&#xff0c;el-popover组件组合封装 import url("//unpkg.com/element-ui2.15.14/lib/theme-chalk/index.css"); <script src"//unpkg.com/vue2/dist/vue.js"></script> <script src"//…

SEO之核心关键词(一)

初创企业需要建站的朋友看这篇文章&#xff0c;谢谢支持&#xff1a; 我给不会敲代码又想搭建网站的人建议新手上云 选择关键词的第一步是确定网站核心关键词。 核心关键词通常就是网站首页的目标关键词。一般来说&#xff0c;整个网站会有很多目标关键词&#xff0c;这些关键…

记一次MySQL执行修改语句超时问题

异常问题 原因分析 这个问题发生在开发环境&#xff0c;怀疑是提交事务时终止项目运行&#xff0c;没有提交该事务&#xff0c;造成死锁 调试该事务时时间太长&#xff0c;为什么说有这个原因呢&#xff0c;因为通过查找日志显示 The client was disconnected by the server …

【二叉树算法题记录】236. 二叉树的最近公共祖先

题目链接 题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个…

Day04-Maven,SpringBoot,Tomcat下载及相关配置

1. maven 2. MaVen是一款管理和构建java项目的工具 2.1 概述 mvn -v2.1 配置Maven环境&#xff08;当前工程&#xff09; 全局配置maven 3. SpringBoot 3.1 SpringBoot入门 package com.jingwei.controller;import org.springframework.web.bind.annotation.…

一个和蔼可亲的Python库,用Gooey为你的程序添加GUI

大家好&#xff0c;你有没有遇到过这样的情况&#xff1a;你写了一个非常棒的命令行程序&#xff0c;但当你分享给朋友或同事时&#xff0c;他们却因为害怕命令行而不愿意使用&#xff1f;这时候&#xff0c;一个简洁美观的图形用户界面&#xff08;GUI&#xff09;就派上用场了…

产品经理-需求分析(三)

1. 需求分析 从业务的需要出发&#xff0c;确定业务目的和目标&#xff0c;将业务需求转为产品需求 1.1 业务需求 业务需求 业务动机 业务目标 就是最根本的动机和目标成果&#xff0c;通过这个需求解决特定的问题 1.2 产品需求 产品需求 解决方案 产品结构 产品流程…