C++如何写日志文件(含源码 可直接套用)

简介

我们平常自己在写项目的过程中,经常把程序运行的信息打印在控制台上,但是真正实际在工作过程中,特别是在一些已经运行起来的服务器上,我们不可能一直盯着控制台在那边查看程序的运行情况吧。

针对这样的情况,我们一般会将需要打印出来的信息写在一个文件里面,即使隔了很多天,我们依旧可以回过头来查看程序的运行状况,这就是日志的作用。

日志的等级

首先,我们要明确,日志是分等级的。有些事情很重要,比方说程序的运行发生错误,我们一般会把错误信息存进日志里面。但是频繁的IO操作是非常消耗程序性能的,所以我们一般把那些无关痛痒的事情设定为低等级的日志,这些信息我们可以不写进文档里面。

日志的等级划分并没有什么非常官方的规定,大家可以根据实际需要进行判断。

这里介绍一些比较常规的划分(级别从低到高)。

  • ALL: 这是最低等级的日志,会把所有信息全都打印出来,一般不会使用。
  • TRACE:也是非常低等级的日志,几乎等同于ALL也不太使用。
  • DEBUG:这种信息一般是指在调试过程中,程序运行的一些细节信息,对开发阶段有所帮助。
  • WARN:这是警告信息,不是错误,但是存在着潜在的危险,值得开发者注意。
  • ERROR:这个属于错误,但是我们在实际的项目运行过程中,很少会因为程序出了一点错误就讲程序停止运行,一般都是报个异常,然后该怎样就怎样。这种信息我们一般都会打印进日志里面。
  • FATAL:这个直接是重大错误了,这个会直接影响到程序的正常运行。出了这种级别的错误基本上就要把程序停下来进行调整了。
  • OFF:这个是最高级别的日志,相当于什么都不要写。

日志的配置文件

文件名:log.h:

#ifndef _LOG_H__
#define _LOG_H__

#include <stdio.h>
#include <time.h>
extern FILE* pLogFile;

int get_loglevel();

enum LOG_LEVEL{
	ALL,
	DEBUG,
	WARN,
	ERROR,
	FATAL,
	OFF
};
#define LOG_DEBUG(fmt, args...) if(get_loglevel()<=DEBUG){time_t t = time(NULL);fprintf(pLogFile,"%s [debug] %s,%s():%d,"fmt,ctime(&t), __FILE__, __func__, __LINE__, ##args);}
#define LOG_WARN(fmt, args...) if(get_loglevel()<=WARN){time_t t = time(NULL);fprintf(pLogFile,"%s [warn ] %s,%s():%d, "fmt,ctime(&t), __FILE__, __func__, __LINE__, ##args);}
#define LOG_ERROR(fmt, args...) if(get_loglevel()<=ERROR){time_t t = time(NULL);fprintf(pLogFile,"%s [error] %s,%s():%d, "fmt,ctime(&t), __FILE__, __func__, __LINE__, ##args);}
#define LOG_FATAL(fmt, args...)  if(get_loglevel()<=FATAL){time_t t = time(NULL);fprintf(pLogFile,"%s [fatal] %s,%s():%d, "fmt,ctime(&t), __FILE__, __func__, __LINE__, ##args);}

#endif 

这里面的知识点其实还是蛮多的。

枚举

在log.h中,对日志的等级进行了枚举,相当于对每一种情况赋值0~5。

这样的做法是为了在之后设定日志等级的时候,可以直接申明一个string log_level的值,凡是低于这个等级的信息,一律不用写进文件里面。

宏函数

在之后的程序使用过程中,如果我们要打印某些信息,就可以直接调用这些宏函数,这些宏函数会先去调用get_loglevel()函数,获取我们设定的日志等级,决定是否要进行打印。

这里可能有一点难理解,我们慢慢来。

首先,我们会在某个文件中设置一下 FILE* pLogFile ,志向写日志的那个文件,这个文件指针一般在其他的文件中定义,这里只是进行调用。宏函数在调用 fprintf() 函数的时候,会找到这个文件指针,把文件写进去。

LOG_DEBUG(fmt, args…)中的参数有三个点,表示这是不定长的参数,这就是我们希望打印的程序里面的具体的数据,可以打印任意多。

fprintf(pLogFile,"%s [debug] %s,%s():%d,"fmt,ctime(&t)); 中:fmt代表着我们传进去的所有参数,到args为止。t是我们获取到的时间,这里要将它转化为C语言可以识别的时间类型。

##表示会将这些参数拼接为一个合法的字符串。

__FILE__及 __func__和 __LINE__分别代表当前所在文件、所在函数、第几行。这些信息将按照格式填入要打印的字符串中。

调用日志配置文件

文件名log.cpp:

#include "log.h"
#include <string>
#include <cstring>
#include <iostream>
using namespace std;
extern string log_level;
int get_loglevel(){
	if(strcasecmp(log_level.c_str(),"all")==0){
		return ALL;	
	}
	if(strcasecmp(log_level.c_str(),"debug")==0){
		return DEBUG;	
	}	
	if(strcasecmp(log_level.c_str(),"warn")==0){
		return WARN;	
	}
	if(strcasecmp(log_level.c_str(),"error")==0){
		return ERROR;	
	}
	if(strcasecmp(log_level.c_str(),"fatal")==0){
		return FATAL;	
	}
	return OFF;
}

strcasecmp()表示忽略大小写比较字符串。

如果在实际使用过程中,需要些日志,就可以通过以下代码对日志信息进行打印:

int main(){
	FILE* pLogFile = fopen("log.txt", "w+");
	string log_level;
	a = 2020;
	b = 3.14;
	c = "lalala";
	LOG_WARN("%d %f %s", a, b, c);
	fclose(pLogFile);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Nire_Yeyu/article/details/106357380