日志用于记录程序的执行记录包括程序的出错记录,程序致命退出原因,程序的正常执行记录。这样我们就可以很快的察觉程序的错误原因、执行状况等等,因此管理日志信息是非常重要的。
日志一般由以下部分组合:
日志时间、日志等级、日志内容、日志文件的名称
日志等级分为5个:Info:常规信息、Warning:报警信息、Error:发生错误,需要立即处理、Fatal:致命信息、Debug:调试信息
学习一下多参数函数相关的c接口:
#include <iostream>
#include <stdarg.h>
int argfunc(int n, ...)//n是要相加的元素个数,...代表要传入的参数
{
va_list s;//s相当于一个int*类型的指针
va_start(s, n);//s=&n+1
int sum=0;
while(n--)
{
sum += va_arg(s, int);
}
va_end(s);//将s置为空
return sum;
}
int main()
{
int a= argfunc(3,1,2,3);
std::cout<<a<<std::endl;
return 0;
}
vsnprintf函数
利用多参数相关接口,就可以实现对函数进行动态参数传参!
time函数
localtime函数
localtime函数的返回值是一个struct tm结构体类型的指针,struct tm结构体里储存了对应时间戳的年月日时分秒,如下就是struct tm结构体:
具体代码实现如下:
log.hpp
#pragma once
#include <iostream>
#include <string>
#include <ctime>
#include <cstdio>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <unistd.h>
#define Screen 1 // 表示向显示器上打印日志信息
#define Onefile 2 // 表示向logtxt日志文件里写日志信息(没有该日志文件open函数会自动创建)
#define Classfile 3 // 对向指定等级的日志文件写内容,比如:Fatal等级的日志信息写到logtxt.Fatal日志文件中
#define Size 1024
#define Logfile "log.txt"
class Log
{
public:
Log(int n = 1)
: printmethod(n), path("./log/")
{
}
void printLogtxt(const std::string &s, const char *logtxt)
{
switch (printmethod)
{
case Screen:
std::cout << logtxt;
break;
case Onefile:
printOneFile(Logfile, logtxt);
break;
case Classfile:
printClassFile(s, logtxt);
break;
default:
break;
}
}
void printOneFile(const std::string &Logname, const std::string& logtxt)
{
std::string _s = path + Logname; // 给logtxt文件加上我们路径,方便我们以后再该路径里管理日志文件
int fd = open(_s.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
if (fd < 0)
{
perror("open");
return;
}
write(fd, logtxt.c_str(), logtxt.size());
close(fd);
}
void printClassFile(const std::string &s, const char *logtxt)
{
std::string _s(Logfile);
_s+= ".";
_s+= s;
printOneFile(_s, logtxt);
}
void operator()(const std::string &str, const char *format, ...)
{
time_t t = time(nullptr);
struct tm *ctime = localtime(&t);
char str1[Size] = {0};
snprintf(str1, sizeof(str1), "[%s][%d-%d-%d:%d:%d:%d]", str.c_str(), ctime->tm_year + 1900,
ctime->tm_mon + 1, ctime->tm_mday,
ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
va_list s;
va_start(s, format);
char str2[Size] = {0};
vsnprintf(str2, sizeof(str2), format, s); // format是格式字符串 s是多参数...的第一个字符串地址
va_end(s);
char logtxt[2 * Size] = {0};
snprintf(logtxt, sizeof(logtxt), "%s %s\n", str1, str2);
printLogtxt(str, logtxt);
}
private:
int printmethod;
std::string path; // 日志文件将来被创建时所在的路径,更有利于我们管理日志文件
};
testlog.cpp
#include "log.hpp"
#include <errno.h>
#include <cstring>
#include <vector>
int main()
{
Log log(3);
log("Info", "向%s日志文件里写入内容成功!", "log.txt.Info");
std::vector<int> v = {1,2};
if(!v.empty())
log("Debug", "v.size() is %d", v.size());
return 0;
}
在log目录下生成的log.txt.Info文件:
在log目录下生成的log.txt.Debug文件: