• C++写日志操作


    使用C++语言编写写日志类,支持写日志级别设置、支持多线程、支持可变形参表写日志。
    主要提供以下接口:
    1、设置写日志的级别
    2、写关键日志信息
    3、写错误日志信息
    4、写警告日志信息
    5、写一般日志信息

    [1].[代码] 共有变量的定义

    #ifndef COMMAND_DEFINE_H
    #define COMMAND_DEFINE_H
    //日志级别的提示信息
    static const char * KEYINFOPREFIX    = " Key: ";
    static const char * ERRORPREFIX    = " Error: ";
    static const char * WARNINGPREFIX    = " Warning: ";
    static const char * INFOPREFIX        = " Info: ";

    static const int MAX_STR_LEN = 1024;
    //日志级别枚举
    typedef enum EnumLogLevel
    {
        LogLevelAll = 0,    //所有信息都写日志
        LogLevelMid,        //写错误、警告信息
        LogLevelNormal,        //只写错误信息
        LogLevelStop        //不写日志
    };

    #endif

    [2].[文件] Logger.h

    #ifndef LOGGER_H_
    #define LOGGER_H_
    #include <Windows.h>
    #include <stdio.h>
    #include "CommandDefine.h"
    /*
        * 类名:Logger
        * 作用:提供写日志功能,支持多线程,支持可变形参数操作,支持写日志级别的设置
        * 接口:SetLogLevel:设置写日志级别
                TraceKeyInfo:忽略日志级别,写关键信息
                TraceError:写错误信息
                TraceWarning:写警告信息
                TraceInfo:写一般信息
    */
    class Logger
    {
    public:
        //默认构造函数
        Logger();
        //构造函数
        Logger(const char * strLogPath, EnumLogLevel nLogLevel = EnumLogLevel::LogLevelNormal);
        //析构函数
        virtual ~Logger();
    public:
        //写关键信息
        void TraceKeyInfo(const char * strInfo, ...);
        //写错误信息
        void TraceError(const char* strInfo, ...);
        //写警告信息
        void TraceWarning(const char * strInfo, ...);
        //写一般信息
        void TraceInfo(const char * strInfo, ...);
        //设置写日志级别
        void SetLogLevel(EnumLogLevel nLevel);
    private:
        //写文件操作
        void Trace(const char * strInfo);
        //获取当前系统时间
        char * GetCurrentTime();
        //创建日志文件名称
        void GenerateLogName();
        //创建日志路径
        void CreateLogPath();
    private:
        //写日志文件流
        FILE * m_pFileStream;
        //写日志级别
        EnumLogLevel m_nLogLevel;
        //日志的路径
        char m_strLogPath[MAX_STR_LEN];
        //日志的名称
        char m_strCurLogName[MAX_STR_LEN];
        //线程同步的临界区变量
        CRITICAL_SECTION m_cs;
    };

    #endif

    [3].[文件] Logger.cpp

    #include "Logger.h"
    #include <imagehlp.h>
    #include <time.h>
    #include <string.h>
    #include <stdarg.h>

    #pragma comment(lib, "DbgHelp.lib")

    //默认构造函数
    Logger::Logger()
    {
        //初始化
        memset(m_strLogPath, 0, MAX_STR_LEN);
        memset(m_strCurLogName, 0, MAX_STR_LEN);
        m_pFileStream = NULL;
        //设置默认的写日志级别
        m_nLogLevel = EnumLogLevel::LogLevelNormal;
        //初始化临界区变量
        InitializeCriticalSection(&m_cs);
        //创建日志文件名
        GenerateLogName();
    }

    //构造函数
    Logger::Logger(const char * strLogPath, EnumLogLevel nLogLevel):m_nLogLevel(nLogLevel)
    {
        //初始化
        m_pFileStream = NULL;
        strcpy(m_strLogPath, strLogPath);
        InitializeCriticalSection(&m_cs);
        CreateLogPath();
        GenerateLogName();
    }

    //析构函数
    Logger::~Logger()
    {
        //释放临界区
        DeleteCriticalSection(&m_cs);
        //关闭文件流
        if(m_pFileStream)
            fclose(m_pFileStream);
    }

    //写关键信息接口
    void Logger::TraceKeyInfo(const char * strInfo, ...)
    {
        if(!strInfo)
            return;
        char pTemp[MAX_STR_LEN] = {0};
        strcpy(pTemp, GetCurrentTime());
        strcat(pTemp, KEYINFOPREFIX);
        //获取可变形参
        va_list arg_ptr = NULL;
        va_start(arg_ptr, strInfo);
        vsprintf(pTemp + strlen(pTemp), strInfo, arg_ptr);
        va_end(arg_ptr);
        //写日志文件
        Trace(pTemp);
        arg_ptr = NULL;

    }

    //写错误信息
    void Logger::TraceError(const char* strInfo, ...)
    {
        //判断当前的写日志级别,若设置为不写日志则函数返回
        if(m_nLogLevel >= EnumLogLevel::LogLevelStop)
            return;
        if(!strInfo)
            return;
        char pTemp[MAX_STR_LEN] = {0};
        strcpy(pTemp, GetCurrentTime());
        strcat(pTemp, ERRORPREFIX);
        va_list arg_ptr = NULL;
        va_start(arg_ptr, strInfo);
        vsprintf(pTemp + strlen(pTemp), strInfo, arg_ptr);
        va_end(arg_ptr);
        Trace(pTemp);
        arg_ptr = NULL;
    }

    //写警告信息
    void Logger::TraceWarning(const char * strInfo, ...)
    {
        //判断当前的写日志级别,若设置为只写错误信息则函数返回
        if(m_nLogLevel >= EnumLogLevel::LogLevelNormal)
            return;
        if(!strInfo)
            return;
        char pTemp[MAX_STR_LEN] = {0};
        strcpy(pTemp, GetCurrentTime());
        strcat(pTemp, WARNINGPREFIX);
        va_list arg_ptr = NULL;
        va_start(arg_ptr, strInfo);
        vsprintf(pTemp + strlen(pTemp), strInfo, arg_ptr);
        va_end(arg_ptr);
        Trace(pTemp);
        arg_ptr = NULL;
    }

    //写一般信息
    void Logger::TraceInfo(const char * strInfo, ...)
    {
        //判断当前的写日志级别,若设置只写错误和警告信息则函数返回
        if(m_nLogLevel >= EnumLogLevel::LogLevelMid)
            return;
        if(!strInfo)
            return;
        char pTemp[MAX_STR_LEN] = {0};
        strcpy(pTemp, GetCurrentTime());
        strcat(pTemp,INFOPREFIX);
        va_list arg_ptr = NULL;
        va_start(arg_ptr, strInfo);
        vsprintf(pTemp + strlen(pTemp), strInfo, arg_ptr);
        va_end(arg_ptr);
        Trace(pTemp);
        arg_ptr = NULL;
    }

    //获取系统当前时间
    char * Logger::GetCurrentTime()
    {
        time_t curTime;
        struct tm * pTimeInfo = NULL;
        time(&curTime);
        pTimeInfo = localtime(&curTime);
        char temp[MAX_STR_LEN] = {0};
        sprintf(temp, "%02d:%02d:%02d", pTimeInfo->tm_hour, pTimeInfo->tm_min, pTimeInfo->tm_sec);
        char * pTemp = temp;
        return pTemp;   
    }

    //设置写日志级别
    void Logger::SetLogLevel(EnumLogLevel nLevel)
    {
        m_nLogLevel = nLevel;
    }

    //写文件操作
    void Logger::Trace(const char * strInfo)
    {
        if(!strInfo)
            return;
        try
        {
            //进入临界区
            EnterCriticalSection(&m_cs);
            //若文件流没有打开,则重新打开
            if(!m_pFileStream)
            {
                char temp[1024] = {0};
                strcat(temp, m_strLogPath);
                strcat(temp, m_strCurLogName);
                m_pFileStream = fopen(temp, "a+");
                if(!m_pFileStream)
                {
                    return;
                }
            }
            //写日志信息到文件流
            fprintf(m_pFileStream, "%s ", strInfo);
            fflush(m_pFileStream);
            //离开临界区
            LeaveCriticalSection(&m_cs);
        }
        //若发生异常,则先离开临界区,防止死锁
        catch(...)
        {
            LeaveCriticalSection(&m_cs);
        }
    }

    //创建日志文件的名称
    void Logger::GenerateLogName()
    {
        time_t curTime;
        struct tm * pTimeInfo = NULL;
        time(&curTime);
        pTimeInfo = localtime(&curTime);
        char temp[1024] = {0};
        //日志的名称如:2013-01-01.log
        sprintf(temp, "%04d-%02d-%02d.log", pTimeInfo->tm_year+1900, pTimeInfo->tm_mon + 1, pTimeInfo->tm_mday);
        if(0 != strcmp(m_strCurLogName, temp))
        {
            strcpy(m_strCurLogName,temp);
            if(m_pFileStream)
                fclose(m_pFileStream);
            char temp[1024] = {0};
            strcat(temp, m_strLogPath);
            strcat(temp, m_strCurLogName);
            //以追加的方式打开文件流
            m_pFileStream = fopen(temp, "a+");
        }

    }

    //创建日志文件的路径
    void Logger::CreateLogPath()
    {
        if(0 != strlen(m_strLogPath))
        {
            strcat(m_strLogPath, "\");
        }
        MakeSureDirectoryPathExists(m_strLogPath);
    }

  • 相关阅读:
    给目录下所有文件与文件夹加权限
    应用程序无法正常启动0xc000007b解决方法
    文件关联修复方法
    xz压缩文件方法
    sharding-jdbc实现水平分库 + 水平分表
    Sharding-jdbc实现水平分表
    批量删除Maven本地仓库中未下载完成的jar包(不完整的jar包)
    分库分表
    尚硅谷 ShardingSphere
    SpringBoot 整合ActiveMQ
  • 原文地址:https://www.cnblogs.com/lizs/p/3642167.html
Copyright © 2020-2023  润新知