C++语言编写写日志类

 更新时间:2020年4月25日 17:36  点击:1608

使用C++语言编写写日志类,支持写日志级别设置、支持多线程、支持可变形参表写日志。
主要提供以下接口:

  • 1、设置写日志的级别
  • 2、写关键日志信息
  • 3、写错误日志信息
  • 4、写警告日志信息
  • 5、写一般日志信息

#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

#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

#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);
}

以上就是本文的全部内容,希望对大家的学习C++有所帮助。

[!--infotagslink--]

相关文章

  • C++ STL标准库std::vector的使用详解

    vector是表示可以改变大小的数组的序列容器,本文主要介绍了C++STL标准库std::vector的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2022-03-06
  • C++中取余运算的实现

    这篇文章主要介绍了C++中取余运算的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • 详解C++ string常用截取字符串方法

    这篇文章主要介绍了C++ string常用截取字符串方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • C++中四种加密算法之AES源代码

    本篇文章主要介绍了C++中四种加密算法之AES源代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...2020-04-25
  • Laravel 调试工具 laravel-debugbar 打印日志消息

    laravel-debugbar 调试工具的教程小编整理了几篇不错的教程,今天我们来看一篇Laravel 调试工具 laravel-debugbar 打印日志消息例子,希望文章对各位有帮助。 其实不...2016-11-25
  • C++ 整数拆分方法详解

    整数拆分,指把一个整数分解成若干个整数的和。本文重点给大家介绍C++ 整数拆分方法详解,非常不错,感兴趣的朋友一起学习吧...2020-04-25
  • C++中 Sort函数详细解析

    这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
  • C++万能库头文件在vs中的安装步骤(图文)

    这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • 详解C++ bitset用法

    这篇文章主要介绍了C++ bitset用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • 浅谈C++中的string 类型占几个字节

    本篇文章小编并不是为大家讲解string类型的用法,而是讲解我个人比较好奇的问题,就是string 类型占几个字节...2020-04-25
  • Powershell 查询 Windows 日志的方法

    这篇文章主要介绍了Powershell 查询 Windows 日志的方法,需要的朋友可以参考下...2020-06-30
  • 对MySQL日志操作的一些基本命令总结

    MySQL日志主要包含:错误日志、查询日志、慢查询日志、事务日志、二进制日志;日志是mysql数据库的重要组成部分。日志文件中记录着mysql数据库运行期间发生的变化;也就是说用来记录mysql数据库的客户端连接状况、SQL语句...2015-11-24
  • C++ Eigen库计算矩阵特征值及特征向量

    这篇文章主要为大家详细介绍了C++ Eigen库计算矩阵特征值及特征向量,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • C++ pair的用法实例详解

    这篇文章主要介绍了C++ pair的用法实例详解的相关资料,需要的朋友可以参考下...2020-04-25
  • VSCode C++多文件编译的简单使用方法

    这篇文章主要介绍了VSCode C++多文件编译的简单使用方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-29
  • C++中的循环引用

    虽然C++11引入了智能指针的,但是开发人员在与内存的斗争问题上并没有解放,如果我门实用不当仍然有内存泄漏问题,其中智能指针的循环引用缺陷是最大的问题。下面通过实例代码给大家介绍c++中的循环引用,一起看看吧...2020-04-25
  • C++随机点名生成器实例代码(老师们的福音!)

    这篇文章主要给大家介绍了关于C++随机点名生成器的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • C++如何删除map容器中指定值的元素详解

    map容器是C++ STL中的重要一员,删除map容器中value为指定元素的问题是我们经常与遇到的一个问题,下面这篇文章主要给大家介绍了关于利用C++如何删除map容器中指定值的元素的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。...2020-04-25
  • C++ 约瑟夫环问题案例详解

    这篇文章主要介绍了C++ 约瑟夫环问题案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...2021-08-15