C++写日志操作

转载于:https://blog.csdn.net/zhwm9521/article/details/65947104

使用C++语言编写写日志类,支持写日志级别设置、支持多线程、支持可变形参表写日志。

主要提供以下接口:

①设置写日志的级别

②写关键日志信息

③写错误日志信息

④写警告日志信息

⑤写一般日志信息


1.共有变量的定义CommandDefine.h

#ifndef COMMAND_DEFINE_H

#define COMMAND_DEFINE_H

//日志级别的提示信息

static const char * KEYINFOPREFIX   = " Key: \n";

static const char * ERRORPREFIX = " Error: \n";

static const char * WARNINGPREFIX   = " Warning: \n";

static const char * INFOPREFIX      = " Info: \n";

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\n", 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);

}

猜你喜欢

转载自blog.csdn.net/pingfan2014/article/details/81389056