当前位置: 首页 > news >正文

可配日志输出

log.h

#ifndef LOG_H
#define LOG_H#include <iostream>#ifndef LOG_TYPE
#define LOG_TYPE
//日志类型
enum LogType
{ErrorLog = 0,	//错误WarnLog ,       //告警InfoLog,        //信息DebugLog        //调试
};
#endifstd::string getCurrentTime();
void writeLog(int type, const char* format, ...);#define LOG(level, fmt, ...)  writeLog(level,"[%s][%s][%d][%s] " fmt" ", getCurrentTime().c_str(), __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)#define LOG_DEBUG(fmt, ...)  writeLog(DebugLog,"[%s][%s][%d][%s][DEBUG] " fmt" ", getCurrentTime().c_str(),  __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#define LOG_INFO(fmt, ...)  writeLog(InfoLog,"[%s][%s][%d][%s][INFO] " fmt" ", getCurrentTime().c_str(), __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#define LOG_WARN(fmt, ...)  writeLog(WarnLog,"[%s][%s][%d][%s][WARN] " fmt" ", getCurrentTime().c_str(), __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#define LOG_ERROR(fmt, ...)  writeLog(ErrorLog,"[%s][%s][%d][%s][ERROR] " fmt" ", getCurrentTime().c_str(), __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)#endif // LOG_H

log.cpp

#include "log.h"#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>#include <chrono>
#include <iomanip>
#include <ctime>
#include <sstream>
#include <fstream>
#include <string>
#include <algorithm>
#include <mutex>#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <limits.h>
#include<direct.h>    //头文件
#endifenum LogOutType
{OutCmd=0, //输出到终端OutFile,  //输出到文件OutAll    //都输出
};enum LogFileType
{FileAppend=0,//追加FileNew      //重新创建,按序号命名
};#define LOG_CFG "/log.cfg"
#define LOG_DIR "/Logs/"
std::string g_root_path;
std::string g_log_file = "log.txt";
int g_type = WarnLog;
int g_log_file_type = FileAppend;
int g_log_out_type = OutAll;
std::mutex g_mutex;std::string getCurrentTime()
{// 获取系统时钟的当前时间点auto now = std::chrono::system_clock::now();// 转换为time_t(秒级精度)auto now_c = std::chrono::system_clock::to_time_t(now);// 转换为本地时间结构体std::tm local_tm = *std::localtime(&now_c);// 计算毫秒部分auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;// 格式化为字符串std::stringstream oss;oss << std::put_time(&local_tm, "%Y-%m-%d %H:%M:%S")<< '.' << std::setfill('0') << std::setw(3) << ms.count();return oss.str();
}std::string getCurrentDir()
{static bool b_init = false;if(b_init){return g_root_path;}b_init = true;#ifdef _WIN32char buffer[MAX_PATH];GetModuleFileNameA(NULL, buffer, MAX_PATH);std::string::size_type pos = std::string(buffer).find_last_of("\\/");g_root_path = std::string(buffer).substr(0, pos);std::replace(g_root_path.begin(), g_root_path.end(), '\\',  '\/');
#elsechar buffer[PATH_MAX];if (getcwd(buffer, sizeof(buffer)) != nullptr) {g_root_path = std::string(buffer);}
#endifstd::cout << "g_root_path:"<<g_root_path + LOG_DIR<<std::endl;return g_root_path;
}void initCfg()
{static bool b_init =false;if(b_init){return;}b_init = true;//初始化日志配置std::ifstream file(getCurrentDir() + LOG_CFG);if(!file.is_open()){std::cerr << "open file " <<getCurrentDir() + LOG_CFG << " error"<<std::endl;return;}try {std::string strLine;while (std::getline(file, strLine)) {//去除空格strLine.erase(std::remove(strLine.begin(), strLine.end(), ' '), strLine.end());if(strLine[0] == '#'){continue;}int index = strLine.find('=');if(index == std::string::npos){continue;}std::string key = strLine.substr(0, index);std::string value;int index_end = strLine.find('#');if(index_end == std::string::npos){value = strLine.substr(index + 1, strLine.size() - index);}else{value = strLine.substr(index + 1, index_end - index - 1);}if(key == "LogType"){g_type = std::stoi(value);}else if(key == "LogFileType"){g_log_file_type = std::stoi(value);}else if(key == "LogFileName"){g_log_file = value;}else if(key == "LogOutType"){g_log_out_type = std::stoi(value);}}} catch (std::exception &e) {std::cerr << e.what();}std::cout << "g_type:"<< g_type << std::endl<< "g_log_file_type:"<< g_log_file_type << std::endl<< "g_log_file:"<< g_log_file << std::endl<<"g_log_out_type:" <<g_log_out_type<< std::endl;file.close();
}void getLogFileNameNumberSuffix(const std::string log_file, std::string &name, int &number, std::string &suffix)
{int index  = log_file.find('_');int index_suffix = log_file.find('.');//文件名if(index_suffix == std::string::npos && index == std::string::npos){name = log_file;number = 0;suffix = "";}else if(index == std::string::npos){//没有找到 '_'name = log_file.substr(0, index_suffix);number = 0;suffix = log_file.substr(index_suffix, log_file.size() - index_suffix);}else if(index_suffix == std::string::npos){//没有找到 '.'name = log_file.substr(index, log_file.size() - index);number = std::stoi(log_file.substr(index + 1, log_file.size() - index - 1));suffix = "";}else{name = log_file.substr(0, index);number = std::stoi(log_file.substr(index + 1, index_suffix - index - 1));suffix = log_file.substr(index_suffix,  log_file.size() - index_suffix);}
}void initLogFile()
{static bool b_init = false;if(b_init){return;}b_init = true;if(g_log_file_type == FileNew){while(std::ifstream((getCurrentDir() + LOG_DIR + g_log_file)).good()){std::string name;int number;std::string suffix;getLogFileNameNumberSuffix(g_log_file, name, number, suffix);g_log_file = name + "_" + std::to_string(number + 1) + suffix;}}
}void writeLogFile(const char* filename, const char* log, int type)
{FILE* stream = fopen(filename, "a");if (NULL == stream) {
#ifdef _WIN32bool flag = CreateDirectoryA((g_root_path + LOG_DIR).c_str(), NULL);
#elsemkdir(g_root_path.c_str());
#endif}stream = fopen(filename, "a");if (NULL == stream) {return;}fprintf(stream,"%s\n", log);fclose(stream);
}void writeLog(int type, const char* format, ...)
{std::lock_guard<std::mutex> lock(g_mutex);initCfg();initLogFile();//判断日志类型,是否输出if(type > g_type){return;}va_list ap;va_start(ap, format);int len = vsnprintf(nullptr, 0, format, ap);char *buf = (char*)malloc(len);int rec = vsprintf(buf, format, ap);va_end(ap);switch (g_log_out_type) {case 0:printf("%s\n", buf);break;case 1:writeLogFile((getCurrentDir() + LOG_DIR + g_log_file).c_str(), buf, type);break;default:printf("%s\n", buf);writeLogFile((getCurrentDir() + LOG_DIR + g_log_file).c_str(), buf, type);break;}free(buf);
}

main.cpp

#include <QCoreApplication>
#include "log.h"
#include <iostream>
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);LOG(InfoLog, "LOG:%s %d","LOG", 11);LOG_DEBUG("LOG_DEBUG:%s %d","LOG_DEBUG", 11);LOG_INFO("LOG_INFO:%s %s","LOG_DEBUG","LOG_DEBUG");LOG_WARN("LOG_WARN:%s %d %d %s","LOG_DEBUG", 11, 22, "asda");LOG_ERROR("LOG_ERROR:%s %d %s %d","LOG_DEBUG", 11, "asd", 22);return a.exec();
}

log.cfg

LogType=2 #0:错误 1:告警 2:信息 3:调试
LogFileType = 1  #0:追加 1:重新创建
LogFileName = logg.txt #日志文件名称
LogOutType = 0 #0:输出到终端  1:输出到文件 2:都输出

终端输出
在这里插入图片描述
日志文件
在这里插入图片描述


文章转载自:

http://dxhkcLlX.pLqqp.cn
http://TGGAxgDo.pLqqp.cn
http://jcCT2ZaX.pLqqp.cn
http://Z55euQ86.pLqqp.cn
http://3RTVBuE4.pLqqp.cn
http://rKZ9FrQT.pLqqp.cn
http://kiAj7sKp.pLqqp.cn
http://EHAoWcbL.pLqqp.cn
http://LTL1IOI8.pLqqp.cn
http://i95Es3kH.pLqqp.cn
http://S30pCobz.pLqqp.cn
http://plXLJnNS.pLqqp.cn
http://QWv9YpO4.pLqqp.cn
http://hvRP1Snp.pLqqp.cn
http://44V7lSXA.pLqqp.cn
http://P9w43237.pLqqp.cn
http://6RwTo0JO.pLqqp.cn
http://dMt3VO4B.pLqqp.cn
http://cNGQuuFY.pLqqp.cn
http://9LXgfGEr.pLqqp.cn
http://9u6bd0Ys.pLqqp.cn
http://EEfxJvlV.pLqqp.cn
http://RpnQi1pJ.pLqqp.cn
http://uxMhJcrO.pLqqp.cn
http://j1hDnt7M.pLqqp.cn
http://YzPnmNBy.pLqqp.cn
http://WGlLs5bA.pLqqp.cn
http://SYqGInqV.pLqqp.cn
http://IlIPzGLc.pLqqp.cn
http://hbpL3GQs.pLqqp.cn
http://www.dtcms.com/a/381837.html

相关文章:

  • 学习笔记:Python的起源
  • vcpkg:面向C/C++的跨平台库管理工具软件配置笔记经验教程
  • Claude Code的交互方式
  • 使用atop工具监控Linux系统指标
  • 工具链部署实用技巧 7|模型设计帧率推理时耗时与带宽分析
  • 《SRE 系列(八)| 高效组织协作经验》
  • 数据结构---链式队列
  • 【C++实战⑦】C++函数实战:从基础到项目应用
  • 通过语义AI管道检测文本数据中的潜在异常值
  • 这是第二篇
  • Mamba模型介绍
  • rock linux 9 安装mysql 5.7.44
  • 基于STM32智能农业大棚检测控制系统设计
  • 05 回归问题和分类问题
  • Linux应用(4)——进程通信
  • 用C语言解决喝汽水问题
  • 【开题答辩全过程】以 4S店汽车维修保养管理系统为例,包含答辩的问题和答案
  • 边缘计算技术深入解析
  • 三生原理的“素性塔“结构是否暗含共形场论中的算子乘积展开层级?‌
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘cugraph’问题
  • 评估硬件兼容性时如何快速判断老旧设备是否支持新协议
  • [2025]使用echarts制作一个漂亮的天气预报曲线图
  • 每日算法题推送
  • DataSet-深度学习中的常见类
  • Python编辑器的安装及配置(Pycharm、Jupyter的安装)从0带你配置,小土堆视频
  • SystemVerilog 学习之SystemVerilog简介
  • 中国联通卫星移动通信业务分析
  • 学习游戏制作记录(实现震动效果,文本提示和构建游戏)9.13
  • 【CMake】循环——foreach(),while()
  • 对比Java学习Go——函数、集合和OOP