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

news2025/4/20 9:52:08

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

目录

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

设计思路:

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

  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 2

    const 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也是可以的。

完~

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

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

相关文章

是否掌握数据结构对于IT职业发展至关重要?

算法跟代码实现有时候是两回事&#xff0c;在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「数据结构的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#…

Cesium 限高分析

Cesium 限高分析 原理&#xff1a;ClassificationPrimitive贴模型的运用 效果图

兼容性最好的模拟器,主要为高端平板设计

一、简介 1、蓝叠安卓模拟器是BlueStacks公司推出的全球知名Android模拟器。它可能是兼容性最好的模拟器&#xff0c;主要为高端平板设计&#xff0c;加入了图形硬件加速&#xff0c;并与AMD合作。 二、下载 1、文末有下载链接,不明白可以私聊我哈&#xff08;麻烦咚咚咚&#…

新迪天工CAD,国际水平的国产三维CAD软件

新迪数字 定位&#xff1a;国际领先的三维CAD软件厂商 使命&#xff1a;掌握核心技术&#xff0c;推动中国创造 愿景&#xff1a;让每个工程师使用中国CAD 上海新迪数字技术有限公司是一家拥有国际先进水平三维CAD核心技术的国产工业软件厂商&#xff0c;由国际工业软件领域知…

今日头条爬虫(zhanzhang.toutiao.com)IP及UA,真实采集数据

​ 一、数据来源&#xff1a; 1、这批今日头条爬虫(zhanzhang.toutiao.com)IP来源于尚贤达猎头网站采集数据&#xff1b; ​ 2、数据采集时间段&#xff1a;2023年10月-2024年7月&#xff1b; 3、判断标准&#xff1a;主要根据用户代理是否包含“zhanzhang.toutiao.com”和…

职场进阶还是智商税?一文看六西格玛绿带培训的真面目

随着企业对精细化管理需求的日益增长&#xff0c;六西格玛绿带培训逐渐成为职场人士争相追逐的热门课程。它不仅能够帮助学员掌握先进的质量管理工具&#xff0c;还能培养逻辑思维、数据分析能力以及团队合作精神&#xff0c;这些都是现代职场不可或缺的软实力。 职场助力or智商…

小程序商品图片有什么要求

在当今信息化的社会中&#xff0c;无论是组织活动、培训课程还是社交聚会&#xff0c;高效、准确地收集报名信息并进行有效匹配显得尤为重要。为此&#xff0c;我们开发了一款全新的报名匹配工具&#xff0c;旨在帮助活动组织者轻松管理报名流程&#xff0c;同时确保参与者能够…

机器学习 第8章-集成学习

机器学习 第8章-集成学习 8.1 个体与集成 集成学习(ensemble learning)通过构建并结合多个学习器来完成学习任务&#xff0c;有时也被称为多分类器系统(multi-classifersystem)、基于委员会的学习(committee-based learning)等。 图8.1显示出集成学习的一般结构:先产生一组“…

day15 Java基础——包机制

day15 Java基础——包机制 Java包机制是一种组织和管理类和接口的方式&#xff0c;通过将相关的类和接口放入同一个包中&#xff0c;可以避免命名冲突&#xff0c;提高代码的可重用性和可维护性。包采用层次化的命名空间&#xff0c;以点号分隔&#xff0c;如java.util。使用i…

标题:组合式API:优化Vue代码结构的艺术

摘要&#xff1a; 在Vue 3中&#xff0c;引入了组合式API&#xff0c;它提供了一种新的方式来组织组件逻辑。虽然组合式API带来了更高的灵活性和可维护性&#xff0c;但开发者也面临着代码组织和可读性的挑战。本文将探讨如何有效地利用组合式API&#xff0c;优化Vue代码结构&a…

深化理解电子商务领域的“二清”风险与合规路径

在电子商务的快速发展中&#xff0c;“二清”风险成为了不容忽视的话题。这一现象不仅触及金融监管红线&#xff0c;还潜藏诸多风险&#xff0c;包括资金安全、信息泄露、合规性挑战以及监管盲点。鉴于“二清”问题的复杂性与潜在危害&#xff0c;电商平台必须采取有效措施&…

FPGA知识基础之--500ms计数器,边沿检测,按键消抖

目录 前言一、边沿检测1.1 使用背景1.2 方法&#xff1a;打拍法1.2.1 背景1.2.2 原理1.2.3 上升沿 二、计数器2.1 原理2.2 RTL代码 三、按键消抖 前言 一、边沿检测 1.1 使用背景 在我们设计电路时&#xff0c;经常会遇到需要继续检测上升沿和下降沿的电路&#xff0c;因此需…

劳动仲裁经验篇【赶紧收藏】

【劳动仲裁】纯经验干货分享&#xff0c;点个关注防止需要时找不到&#xff01; 当公司决定搞你心态&#xff0c;变相逼退你时&#xff0c;无非就那么些手段&#xff0c;只要你能正确应对&#xff0c;并做好收集证据的准备&#xff0c;就不住畏惧。合理利用法律的武器维护自身…

大模型书籍电子书上新 |《图技术与大模型在多领域的应用》

资料目录及介绍&#xff1a; GraphGPT: 大语言模型的图结构指令微调 GraphGPT旨在使大语言模型理解图结构数据&#xff0c;执行图相关任务如节点分类和链接预测。面对图数据多样性和大模型能力迁移的挑战&#xff0c;GraphGPT探讨了图输入方法、模型对齐及推理能力增强等解决…

重生奇迹MU 从不孤军奋战

重生奇迹MU的世界里&#xff0c;每个职业都有自己的独特魅力和优势。本文将讲述圣导师和弓箭手在游戏中的表现&#xff0c;他们不仅拥有强大的个人实力&#xff0c;更擅长与队友协作奋战&#xff0c;成为团队推进的重要力量。无论你选择哪个职业&#xff0c;与他们一起并肩作战…

【pikachu靶场】之ITOver Permission越权漏洞

一、水平越权&#xff1a; 查看一下提示 里面有用户名和密码&#xff0c;&#xff0c;后面要用。。 登录一个用户 在地址栏里可以看到lili用户名直接被显示到了里面&#xff0c;可以直接在这里修改切换到其他的用户。 修改用户 我修改用户为lucy后&#xff0c;就看到了lucy…

【教程】Python语言的地球科学常见数据——MODIS土地利用数据的处理

读取多年土地利用数据、裁剪长江流域土地利用、分析长时间序列长江流域土地利用变化。 地覆盖动态产品包括标志着季节性周期的植被生长、成熟和衰老的时间层。MODISTerraAqua 组合土地覆盖产品包含了五个不同的士地覆盖分类方案&#xff0c;通过监督决策树分类方法得出。主要的…

Maven下载和安装(详细版)

前言 Maven 的含义 Maven 是一个 java 项目管理 和构建工具&#xff0c;他可以定义项目结构&#xff0c;项目依托&#xff0c;并使用统一的方式进行自动化构建&#xff0c;是 java项目不可或缺的工具。 Maven 的 优点 1 提供 标准化的项目结构&#xff08;具体规定了文件的…

公司重要文件怎么保护

一、文件加密 采用加密算法&#xff1a;将重要文件转换成无法直接阅读的代码形式&#xff0c;只有在经过授权解密后才能恢复原始内容。这可以显著降低数据泄密的风险。 使用专业加密软件&#xff1a;如金刚钻信息防泄密系统等&#xff0c;这些软件提供多种加密模式&#xff0…

microsoft远程桌面,windows云电脑如何使用microsoft远程桌面

Microsoft远程桌面&#xff08;RemoteDesktop&#xff09;是一项强大的功能&#xff0c;允许用户从任何支持的设备&#xff08;如PC、Mac、iOS、Android设备&#xff09;远程访问和控制Windows电脑&#xff0c;尤其是Windows专业版或企业版系统。这对于远程办公、技术支持或访问…