说明:
- 重新整理,增加程序启动和退出时的日志,方便查看
- 修改配置文件,将Warning以上单独再起一份日志记录
- 修改输出日志格式,限定数据长度,对齐格式
代码:
#pragma once
#include "libpublic.h"
#if defined(Q_OS_WIN32)
#include <windows.h>
#include <DbgHelp.h>
//生产DUMP文件
int GenerateMiniDump(HANDLE hFile, PEXCEPTION_POINTERS pExceptionPointers, PWCHAR pwAppName)
{
BOOL bOwnDumpFile = FALSE;
HANDLE hDumpFile = hFile;
MINIDUMP_EXCEPTION_INFORMATION ExpParam;
typedef BOOL(WINAPI * MiniDumpWriteDumpT)(
HANDLE,
DWORD,
HANDLE,
MINIDUMP_TYPE,
PMINIDUMP_EXCEPTION_INFORMATION,
PMINIDUMP_USER_STREAM_INFORMATION,
PMINIDUMP_CALLBACK_INFORMATION
);
MiniDumpWriteDumpT pfnMiniDumpWriteDump = nullptr;
HMODULE hDbgHelp = LoadLibrary(L"DbgHelp.dll");
if (hDbgHelp)
pfnMiniDumpWriteDump = (MiniDumpWriteDumpT)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
if (pfnMiniDumpWriteDump)
{
if (hDumpFile == nullptr || hDumpFile == INVALID_HANDLE_VALUE)
{
//TCHAR szPath[MAX_PATH] = { 0 };
TCHAR szFileName[MAX_PATH] = { 0 };
//TCHAR* szAppName = pwAppName;
TCHAR* szVersion = L"v1.0";
TCHAR dwBufferSize = MAX_PATH;
SYSTEMTIME stLocalTime;
GetLocalTime(&stLocalTime);
//GetTempPath(dwBufferSize, szPath);
//wsprintf(szFileName, L"%s%s", szPath, szAppName);
CreateDirectory(szFileName, nullptr);
wsprintf(szFileName, L"%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
//szPath, szAppName, szVersion,
szVersion,
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
GetCurrentProcessId(), GetCurrentThreadId());
hDumpFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
bOwnDumpFile = TRUE;
OutputDebugString(szFileName);
}
if (hDumpFile != INVALID_HANDLE_VALUE)
{
ExpParam.ThreadId = GetCurrentThreadId();
ExpParam.ExceptionPointers = pExceptionPointers;
ExpParam.ClientPointers = FALSE;
pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
hDumpFile, MiniDumpWithDataSegs, (pExceptionPointers ? &ExpParam : nullptr), nullptr, nullptr);
if (bOwnDumpFile)
CloseHandle(hDumpFile);
}
}
if (hDbgHelp != nullptr)
FreeLibrary(hDbgHelp);
return EXCEPTION_EXECUTE_HANDLER;
}
LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS lpExceptionInfo)
{
if (IsDebuggerPresent())
{
return EXCEPTION_CONTINUE_SEARCH;
}
return GenerateMiniDump(nullptr, lpExceptionInfo, L"test");
}
#endif
#include "log4qt/logger.h"
#include "log4qt/log4qt.h"
#include "log4qt/logmanager.h"
#include "log4qt/propertyconfigurator.h"
class CMyLog4Qt
{
public:
//************************************
// 作者:
// 日期: 2020/08/05
// 函数: initLog
// 参数: const QString & logpath
// 返回: void
// 功能: 初始化日志
//************************************
static void initLog(const QString& logconfig = LibPublic::GetCurrentPath() + "/Config/Log4Qt.conf")
{
#if defined(Q_OS_WIN32)
//生成dump文件
SetUnhandledExceptionFilter(ExceptionFilter);
#endif
Log4Qt::PropertyConfigurator::configure(logconfig);
qDebug() << QString::fromLocal8Bit("=============================================").toUtf8().data();
qDebug() << QString::fromLocal8Bit("程序开始运行!... 程序名称: %1").arg(QApplication::applicationName()).toUtf8().data();
qDebug() << QString::fromLocal8Bit("=============================================").toUtf8().data();
};
static void shutDownLog()
{
qDebug() << QString::fromLocal8Bit("=============================================").toUtf8().data();
qDebug() << QString::fromLocal8Bit("程序结束运行!... 程序名称: %1").arg(QApplication::applicationName()).toUtf8().data();
qDebug() << QString::fromLocal8Bit("=============================================").toUtf8().data();
}
};
配置文件:
#设置储存log文件的根目录
logpath=./Logs
# 配置日志的输出格式: %r耗费毫秒数 %p日志的优先级 %t线程名 %C所属类名通常为全类名 %L代码中的行号 %x线程相关联的NDC %m日志 %n换行
logConversionPattern=[%d{yyyy-MM-dd HH:mm:ss.zzz}][%-5p][%-20t] >> %m %n
log4j.reset=true
#设置是否监听QDebug输出的字符串
log4j.handleQtMessages=true
#在运行中,是否监视此文件配置的变化
log4j.watchThisFile=false
#设置根Logger的输出log等级为All
# log4j.rootLogger日志输出类别和级别:只输出不低于该级别的日志信息 DEBUG < INFO < WARN < ERROR < FATAL
#设置Log输出的几种输出源(appender):console, daily, rolling
log4j.rootLogger=ALL, console, daily, dailyWarn, rolling
#############
# 输出到控制台
#############
###############################################################################################
# 配置INFO CONSOLE输出到控制台
log4j.appender.console=org.apache.log4j.ConsoleAppender
# 输出
log4j.appender.console.Target = System.out
# 配置CONSOLE设置为自定义布局模式
log4j.appender.console.layout=org.apache.log4j.PatternLayout
# 配置logfile为自定义布局模式
log4j.appender.console.layout.ConversionPattern=${logConversionPattern}
###############################################################################################
################
# 输出到日志文件中
################
###############################################################################################
# 配置logfile输出到文件中 每日产生文件
log4j.appender.daily=org.apache.log4j.DailyFileAppender
# 输出文件位置此为项目根目录下的logs文件夹中
log4j.appender.daily.file=${logpath}/Log.log
# 日期格式
log4j.appender.daily.datePattern='.'yyyy-MM-dd
# true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是false
log4j.appender.daily.appendFile=true
# 立即输出
log4j.appender.daily.immediateFlush=false
# 输入日志等级
log4j.appender.daily.Threshold = DEBUG
# 设置保留天数
log4j.appender.daily.keepDays=30
# 配置logfile为自定义布局模式
log4j.appender.daily.layout=org.apache.log4j.PatternLayout
log4j.appender.daily.layout.ConversionPattern=${logConversionPattern}
###############################################################################################
###############################################################################################
# 配置logfile输出到文件中 每日产生文件
log4j.appender.dailyWarn=org.apache.log4j.DailyFileAppender
# 输出文件位置此为项目根目录下的logs文件夹中
log4j.appender.dailyWarn.file=${logpath}/LogWarn.log
# 日期格式
log4j.appender.dailyWarn.datePattern='.'yyyy-MM-dd
# true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是false
log4j.appender.dailyWarn.appendFile=true
# 立即输出
log4j.appender.dailyWarn.immediateFlush=false
# 输入日志等级
log4j.appender.dailyWarn.Threshold = WARN
# 设置保留天数
log4j.appender.dailyWarn.keepDays=30
# 配置logfile为自定义布局模式
log4j.appender.dailyWarn.layout=org.apache.log4j.PatternLayout
log4j.appender.dailyWarn.layout.ConversionPattern=${logConversionPattern}
###############################################################################################
###############################################################################################
# 配置logfile输出到文件中 文件大小到达指定尺寸的时候产生新的日志文件
log4j.appender.rolling=org.apache.log4j.RollingFileAppender
# 输出文件位置此为项目根目录下的logs文件夹中
log4j.appender.rolling.file=${logpath}/LogRolling.log
# true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是false
log4j.appender.rolling.appendFile=false
# 立即输出
log4j.appender.rolling.immediateFlush=true
# 后缀可以是KB,MB,GB达到该大小后创建新的日志文件
log4j.appender.rolling.MaxFileSize=50MB
# 设置滚定文件的最大值5
log4j.appender.rolling.MaxBackupIndex=20
# 配置logfile为自定义布局模式
log4j.appender.rolling.layout=org.apache.log4j.PatternLayout
log4j.appender.rolling.layout.ConversionPattern=${logConversionPattern}
###############################################################################################
另外发现一个问题
如果log4j.appender.daily.immediateFlush=false开启文件缓存,日志输入内容太少,会导致日志文件中无法保存下来,跟了下源码,只能确定调用了QTextStream输出函数,没有调用flush函数,暂时没有时间深入研究,先这样