代码拉取完成,页面将自动刷新
#pragma once
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <ctime>
#include <stdarg.h>
#include <fstream>
#include <cstring>
#include <pthread.h>
namespace log_ns
{
// 日志消息等级
enum
{
DEBUG = 1, // 调试信息
INFO, // 常规信息
WARNING, // 警告信息
ERROR, // 错误信息
FATAL // 致命信息
};
// 日志消息类
class logmessage
{
public:
std::string _level; // 日志等级
pid_t _id; // 进程id
std::string _filename; // 文件名
int _filenumber; // 文件行号
std::string _curr_time; // 时间
std::string _message_info; // 日志内容
};
// 将日志等级转化为字符串
std::string LevelToString(int level)
{
switch (level)
{
case DEBUG:
return "DEBUG";
case INFO:
return "INFO";
case WARNING:
return "WARNING";
case ERROR:
return "ERROR";
case FATAL:
return "FATAL";
default:
return "UNKNOWN";
}
}
std::string GetCurrTime()
{
time_t now = time(nullptr); // 获取当前时间戳,time_t为时间戳类型
struct tm *curr_time = localtime(&now); // 将时间戳转化为struct tm类型,其成员变量为年月日时分秒
char buffer[128];
snprintf(buffer, sizeof(buffer), "%d-%02d-%02d %02d:%02d:%02d",
curr_time->tm_year + 1900,
curr_time->tm_mon + 1,
curr_time->tm_mday,
curr_time->tm_hour,
curr_time->tm_min,
curr_time->tm_sec);
return buffer;
}
#define SCREEN_TYPE 1 // 日志消息向显示器输出
#define FILE_TYPE 2 // 日志消息向文件输出
const std::string glogfile = "./log.txt"; // 默认向该文件中输出日志消息
pthread_mutex_t glock = PTHREAD_MUTEX_INITIALIZER; // 全局锁,防止多线程输出日志消息时出错
// 日志类
class Log
{
private:
int _type; // 决定日志消息向显示器/文件输出
std::string _logfile; // 日志文件路径
public:
// 有参构造函数
Log(const std::string logfile = glogfile) : _logfile(logfile), _type(SCREEN_TYPE) // 默认向显示器输出
{
}
// 改变日志消息输出位置
void Enable(int type)
{
_type = type;
}
// 日志消息向显示器输出
void FlushLogToScreen(const logmessage &lg)
{
printf("[%s][%d][%s][%d][%s] %s",
lg._level.c_str(),
lg._id,
lg._filename.c_str(),
lg._filenumber,
lg._curr_time.c_str(),
lg._message_info.c_str());
}
// 日志消息向文件输出
void FlushLogToFile(const logmessage &lg)
{
std::ofstream out(_logfile, std::ios::app); // 打开日志文件并追加输入
if (!out.is_open())
return; // 打开文件失败
char logtxt[2048];
snprintf(logtxt, sizeof(logtxt), "[%s][%d][%s][%d][%s] %s", // 将日志消息格式化输入到logtxt缓冲区
lg._level.c_str(),
lg._id,
lg._filename.c_str(),
lg._filenumber,
lg._curr_time.c_str(),
lg._message_info.c_str());
out.write(logtxt, strlen(logtxt)); // 向日志文件中输出
out.close(); // 关闭文件
}
// 刷新日志消息
void FlushLog(const logmessage &lg)
{
pthread_mutex_lock(&glock);
switch (_type)
{
case SCREEN_TYPE:
FlushLogToScreen(lg);
break;
case FILE_TYPE:
FlushLogToFile(lg);
break;
}
pthread_mutex_unlock(&glock);
}
void logMessage(std::string filename, int filenumber, int level, const char *format, ...)
{
logmessage lg; // 日志消息对象
lg._level = LevelToString(level); // 初始化日志消息:日志等级
lg._id = getpid(); // 初始化日志消息:进程id
lg._filename = filename; // 初始化日志消息:日志文件名
lg._filenumber = filenumber; // 初始化日志消息:日志文件行号
lg._curr_time = GetCurrTime(); // 初始化日志消息:时间
// 将可变参数中的内容格式化为日志消息内容
va_list ap;
va_start(ap, format);
char log_info[1024];
vsnprintf(log_info, sizeof(log_info), format, ap); // 自动提取可变参数,并将其填入log_info缓冲区中
va_end(ap);
lg._message_info = log_info;
// 打印日志消息(刷新日志消息)
FlushLog(lg);
}
// 析构函数
~Log()
{
}
};
Log lg; // 定义一个全局的日志类对象
// 宏,使得日志消息输出时,可以不用带__FILE__和__LINE__,其中__VA_ARGS__用于接受可变参数部分
/*__VA_ARGS__加上##如果没有可变参数,可以自动去掉__VA_ARGS__*/
#define LOG(Level, Format, ...) \
do \
{ \
lg.logMessage(__FILE__, __LINE__, Level, Format, ##__VA_ARGS__); \
} while (0)
// 同时定义切换日志消息输出位置的宏
#define EnableScreen() do{lg.Enable(SCREEN_TYPE);} while (0)
#define EnableFILE() do{lg.Enable(FILE_TYPE);} while (0)
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。