【Linux】第三十三站:日志

这篇具有很好参考价值的文章主要介绍了【Linux】第三十三站:日志。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、实现一个简单的日志

1.简介

我们运行代码的时候,我们希望有各种各样的运行时候的一些信息。这也就是日志

它一半有日志时间,日志的等级,日志的内容,文件的名称和行号。

对于日志等级一半有如下的

Info : 常规消息

Warning : 报警信息

Error : 比较严重了,可能需要立即处理

Fatal : 致命的

Debug : 调试

2.可变参数

关于可变参数我们主要用下面四个中的前三个

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

我们用如下代码来简单的介绍一下

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 = NULL
    return SUM;
}

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

在这段代码中,这个va_list其实就是一个char*类型的指针。

我们这个可变参数的函数至少需要带有一个参数。

因为我们传递参数的时候是从右向左传递的,所以我们是可以确定出栈顶的元素就是我们所确定的一个元素的地址

这个va_start是一个宏,代表着让s这个指针指向n。也就是栈顶

然后我们va_arg也是一个宏,它的作用是让s指针往栈里面移动第二个参数的类型大小,并解引用

va_end这个宏的作用是让指针置为空

最终我们就可以计算出这个sum的大小了。这个第一个参数我们一般是用作确定后面的参数有几个

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

像我们所谓的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.时间

接下是时间,我们可以使用时间戳,不过其实还有其他的系统调用接口

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

#include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);

第一个参数是一个结构体,里面的两个参数它可以获取秒,微秒。

第二个参数与时区相关,我们可以不用管,直接置为NULL即可

还有一个接口是这样的

#include <time.h>
struct tm *localtime(const time_t *timep);

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

这个函数的功能是将时间戳转化为一个结构体,这个结构体里面有时分秒月年等信息

我们可以简单的应用一下

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

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

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

如下所示就正确了

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);
}

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

5.打印每一条参数

我们可以用vsnprintf函数

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

最终我们的代码为如下

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;
}  

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

6.与前面的一些代码搭配使用

如下所示,这里我们就引进了我们刚刚使用的日志

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

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

【Linux】第三十三站:日志,【Linux】,linux,运维,服务器,restful,数据库,c++,c语言

二、完整代码

如下代码所示,我们再将前面的日志给封装成一个类,然后实现一下分类打印,向文件打印,向显示屏打印等等功能。文章来源地址https://www.toymoban.com/news/detail-815408.html

#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】第三十三站:日志的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 学C的第三十三天【C语言文件操作】

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 学C的第三十二天【动态内存管理】_高高的胖子的博客-CSDN博客  =====================================

    2024年02月13日
    浏览(32)
  • 【从零开始学习JAVA | 第三十三篇】File类

    目录 前言: File类: 构造方法: 常见成员方法: 总结:         本文我们将为大家介绍JAVA中一个比较使用的类:File类,他为我们提供了存储数据的功能,使得程序的数据不至于在运行结束之后就丢失,是一个很好的类。         File类是Java标准库中用于操作文件和目录

    2024年02月15日
    浏览(37)
  • 第三十三章:RPA与自然语言处理的安全保障

    RPA(Robotic Process Automation)和自然语言处理(NLP)是两种不同的技术领域,但它们在现实生活中的应用中有很多相互关联和相互影响的地方。在这篇文章中,我们将讨论RPA与自然语言处理的安全保障,以及如何在实际应用中保障数据安全和系统安全。 自然语言处理(NLP)是一种通过计

    2024年02月22日
    浏览(43)
  • Linux运维:系统日志篇

    您可以将系统日志理解为记录系统运行情况的一种日记。它包含了各种级别的信息,从调试信息和错误报告到警告和系统事件等。通过对系统日志进行分析,管理员可以了解系统的状态和运行情况,发现并解决问题,确保系统的正常运行。因此,系统日志是管理和维护 Linux

    2024年02月05日
    浏览(95)
  • 第三十二章:MySQL事务日志

    事物有4种特性:原子性、一致性、隔离性和持久性。那么事务的四种特性到底是基于什么机制实现呢? 事物的隔离性有锁机制实现。 而事物的原子性、一致性和持久性由事物的 redo 日志和 undo 日志来保证。 REDO LOG 称为重做日志,提供再写入操作,恢复提交事物修改的页操作

    2024年02月15日
    浏览(31)
  • ChatGPT 与生成式 AI 的崛起:第二十六章到第三十三章

    原文:Rise of Generative AI and ChatGPT 译者:飞龙 协议:CC BY-NC-SA 4.0 恐怖分子、罪犯、警察、国防、执法机构、工程师、作家和学生等都在使用 ChatGPT,这是来自 OpenAI 的强大自然语言人工智能工具,作为他们日常工作的重要组成部分。自去年 11 月底发布以来,这种生成式人工智

    2024年01月24日
    浏览(193)
  • 【Linux深造日志】运维工程师必会Linux常见命令以及周边知识!

    🎬 鸽芷咕 :个人主页  🔥 个人专栏 : 《linux深造日志》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活!   哈喽各位宝子们好啊!我是博主鸽芷咕。日志这个东西我相信大家都不陌生,在 linxu/Windows 系统中每天运行都会产生各种系统日志。而咱们每天学习知识也是一

    2024年04月17日
    浏览(50)
  • 【数据结构】第十三站:排序(中)快速排序

    快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,

    2024年02月01日
    浏览(36)
  • 小白到运维工程师自学之路 第三十九集 (HAproxy 负载均衡) 一、概述

            HAProxy是一款高性能的负载均衡软件,可以将来自客户端的请求分发到多个服务器上,以提高系统的可用性和性能。HAProxy支持多种负载均衡算法,包括轮询、加权轮询、最少连接数等。同时,HAProxy还支持会话保持、健康检查、SSL终止等功能,可以满足不同场景下的

    2024年02月09日
    浏览(44)
  • 第三十四回 石将军村店寄书 小李广梁山射雁-FreeBSD Linux下做图软件GIMP

    宋江花荣并燕顺王矮虎与秦明黄信汇合,攻打清风寨南寨,把刘高一家都喀嚓了。一行人回到山寨聚义厅,燕顺一刀砍了刘高夫人。王矮虎急了,想和燕顺打,被宋江劝道:我救了她,她都叫她丈夫害我,留在你身边只会害了你,并答应以后介绍一个好的。 大家决定去梁山泊

    2024年02月19日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包