Linux:日志的编写及使用

cpp 复制代码
#pragma once
#include <iostream>
#include <fstream>
#include <cstdio>
#include <string>
#include <ctime>
#include <cstdarg>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include "LockGuard.hpp"

bool gIsSave=false;//默认false是向显示器进行打印,true是向文件进行写入
const std::string logname="log.txt";

//1.日志是有等级的
enum Level
{
    DEBUG=0,//调试
    INFO,//正常
    WARNING,//警告
    ERROR,//错误
    FATAL//严重的错误
};

void SaveFile(const std::string &filename,const std::string &message)//改变日志的打印目标
{
    std::ofstream out(filename,std::ios::app);
    if(!out.is_open())
    {
        return;
    }
    out<<message;
    out.close();
}

std::string LevelToString(int level)//将等级转换成字符串
{
    switch(level)
    {
        case DEBUG:
            return "Debug";
        case INFO:
            return "INFO";
        case WARNING:
            return "Warning";
        case ERROR:
            return "Error";
        case FATAL:
            return "Fatal";
        default:
            return "Unknown";
    }
}

std::string GetTimeString()//以字符串形式获取当前时间
{
    time_t curr_time=time(nullptr);
    struct tm *format_time=localtime(&curr_time);//tm是time库函数中的一个结构体类型,内部可以存储日期时间等信息
    if(format_time==nullptr)
    {
        return "None";
    }
    char time_buffer[1024];
    snprintf(time_buffer,sizeof(time_buffer),"%d-%d-%d %d:%d:%d",
            format_time->tm_year+1900,
            format_time->tm_mon+1,
            format_time->tm_mday,
            format_time->tm_hour,
            format_time->tm_min,
            format_time->tm_sec);
    return time_buffer;
}

pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
//2.日志是有格式的
//日志等级 时间 代码所在的文件名/行数 日志的内容
//filename 需要写入的目标文件名
//line 写入该条日志信息的所在行数
//issave 是否向文件进行写入
//level 日志等级
//
void LogMessage(std::string filename,int line,bool issave,int level,const char*format)
{

    std::string levelstr=LevelTostring(level);//等级
    std::string timestr=GetTimeString();//时间信息
    pid_t selfid=getpid();//当前线程PID

    char buffer[1024];
    va_list arg;//本质上是一个指针
    va_start(arg,format);//用format的地址来初始化arg(即让其指向可变参数部分),arg本质上是一个    
    //void类型的指针

    vsnprintf(buffer,sizeof(buffer),format,arg);
    va_end(arg);//将arg进行清空

    std::string message="["+timestr+"]"+"["+levelstr+"]"+
                        "["+std::to_string(selfid)+"]"+
                        "["+filename+"]"+"["+std::to_string(line)+"]"+buffer+"\n";
    LockGuard lockguard(&lock);
    if(!issave)
    {
        std::cout<<message;
    }
    else
    {
        SaveFile(logname,message);
    }
}

// C99新特性__VA_ARGS__
#define LOG(level,format,...)
    do
    {
        LogMessage(__FILE__,__LINE__,gIsSave,level,format,##__VA_ARGS__);
    }while(0)

#define EnableFile()
    do
    {
        gIsSave=true;
    }while(0)
#define EnableScreen()
    do
    {
        gIsSave=false;
    }while(0)

va_start和va_arg

cpp 复制代码
va_start(arg,num);
va_arg(arg,int);

1、arg指针可以根据num的地址然后减去num类型的大小指向num之后一个元素的地址。

2、data进行读取数据时将arg强转成int*然后进行解引用,重复以上的操作,这样就可以将可变参数全部读取完毕。

vsprintf/vsnprintf

将内容printf到第一个参数所指向的字符串中,长度为第二个参数size,

将指向可变部分ap以format格式,将格式化完成后的字符串存入第一个参数,str字符串中。vsnprintf则是更安全的方式,按照用户要求的长度将其放到str中。

宏替换的使用及C++14语法的使用

考虑到用户便捷和使用的方便,可以使用宏的方式对日志的调用以及传参进行替换,结合C++14的语法特性对其进行do while操作。

cpp 复制代码
#define LOG(level,format,...)
    do
    {
        LogMessage(__FILE__,__LINE__,gIsSave,level,format,##__VA_ARGS__);
    }while(0)

//通过宏来直接对gIs进行修改
#define EnableFile()//向文件写入日志
    do
    {
        gIsSave=true;
    }while(0)
#define EnableScreen()//向显示器写入日志
    do
    {
        gIsSave=false;
    }while(0)
相关推荐
HalvmånEver3 小时前
Linux:命名管道实现IPC(进程间通信七)
linux·运维·服务器·ipc·命名管道·管道pipe
正在学习前端的---小方同学8 小时前
Harbor部署教程
linux·运维
牛奔9 小时前
Docker Compose 两种安装与使用方式详解(适用于 Docker 19.03 版本)
运维·docker·云原生·容器·eureka
翼龙云_cloud9 小时前
阿里云渠道商:如何手动一键扩缩容ECS实例?
运维·服务器·阿里云·云计算
Sean X10 小时前
Ubuntu24.04安装向日葵
linux·ubuntu
墨风如雪10 小时前
拒绝被找回!MJJ必修课:Outlook邮箱交易后的“防回手”安全设置全攻略
服务器
DX_水位流量监测11 小时前
大坝安全监测之渗流渗压位移监测设备技术解析
大数据·运维·服务器·网络·人工智能·安全
电商API&Tina11 小时前
京东 API 数据采集接口接入与行业分析
运维·服务器·网络·数据库·django·php
IT 乔峰11 小时前
脚本部署MHA集群
linux·shell
dz小伟11 小时前
execve() 系统调用深度解析:从用户空间到内核的完整加载过程
linux