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)
相关推荐
zhangzeyuaaa1 天前
从Windows到Linux:Shell脚本“无法执行:找不到需要的文件”问题深度解析与根治方案
linux·运维·windows
向宇it1 天前
关闭SSH密码登录,SSH 如何使用公钥密钥登录服务器(解决服务器经常被攻击问题)
服务器·网络·ssh
大卡片1 天前
进程间通信
linux·运维·服务器
张小姐的猫1 天前
【Linux】进程信号(上)—— 信号产生 | 保存信号
linux·运维·服务器
石小千1 天前
部署Nextcloud与Onlyoffice(二)安装Onlyofiice
linux·运维
xuanwenchao1 天前
Mac M1/M2/M3/M4/M5芯片-系统安装Ubuntu
linux·ubuntu·macos
白毛大侠1 天前
Docker vs 虚拟机 vs Go 用户态/内核态:这三组概念
运维·docker·golang·kvm
小白勇闯网安圈1 天前
腾讯云服务器部署Dify
服务器·人工智能·云计算·腾讯云
芝士就是力量啊 ೄ೨1 天前
提高服务器安全-采用密钥公钥登录而非密码登录-详细操作步骤
运维·服务器·安全
渠过客1 天前
【运维】PM2 使用完全指南:Node.js 应用进程管理利器
运维·node.js