需求
- GUI log分登记
- GUI log记入文件
- GUI log每个文件大小限制在1M
- GUI log共10个文件,回滚覆盖写入
- GUI log最新的日志总是计入xxx.0.log, 依次xxx.1.log, xxx.2.log, 依次类推
Qt 调试信息
qDebug() //调试消息
qInfo() //信息消息
qWarning() //警告消息
qCritical() //错误消息
qFatal() //致命错误消息
默认环境下输出的调试信息
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 打印信息
qDebug() << "This is a debug message";
qDebug("This is a debug message");
qInfo("This is a info message");
qWarning("This is a warning message");
qCritical("This is a critical message");
qFatal("This is a fatal message");
return a.exec();
}
输出结果如下所示:
This is a debug message
This is a debug message
This is a info message
This is a warning message
This is a critical message
This is a fatal message
安装自定义的消息处理程序
先看下官方给的例子
#include <qapplication.h>
#include <stdio.h>
#include <stdlib.h>
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
const char *file = context.file ? context.file : "";
const char *function = context.function ? context.function : "";
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
break;
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 安装消息处理程序
auto front = qInstallMessageHandler(myMessageOutput);
// 打印信息
qDebug() << "This is a debug message";
qDebug("This is a debug message");
qInfo("This is a info message");
qWarning("This is a warning message");
qCritical("This is a critical message");
qFatal("This is a fatal message");
return a.exec();
}
- 输出结果
Debug: This is a debug message (…\main.cpp:89, int __cdecl main(int,char *[]))
Info: This is a info message (…\main.cpp:90, int __cdecl main(int,char *[]))
Warning: This is a warning message (…\main.cpp:91, int __cdecl main(int,char *[]))
Critical: This is a critical message (…\main.cpp:92, int __cdecl main(int,char *[]))
Fatal: This is a fatal message (…\main.cpp:93, int __cdecl main(int,char *[]))
自定义输出格式
通过上述输出结果,可以发现,通过自定义格式,可以让log按找自己想要的结果来记录,比如time, pid, tid, fun, line等信息
enum class LogType {
Reset = 0,
Bold,
Unbold,
FrontBlack,
FrontRed,
FrontGreen,
FrontYellow,
FrontBlue,
FrontPurple,
FrontCyan,
FrontWhite,
BackBlack,
BackRed,
BackGreen,
BackYellow,
BackBlue,
BackPurple,
BackCyan,
BackWhite,
TypeCount
};
static const char *logCommands[] = {
"\033[0m", "\033[1m", "\033[2m", "\033[30m", "\033[31m",
"\033[32m", "\033[33m", "\033[34m", "\033[35m", "\033[36m",
"\033[37m", "\033[40m", "\033[41m", "\033[42m", "\033[43m",
"\033[44m", "\033[45m", "\033[46m", "\033[47m",
};
//自定义消息类型字符串
static const char *msgType[] = {"Debug", "Warning", "Critical", "Fatal",
"Info"};
//自定义消息处理函数
void customMessageHandler(QtMsgType type, const QMessageLogContext &context,const QString &msg) {
const char *file = context.file ? context.file : "default";
const char *function = context.function ? context.function : "default";
if (msg.isNull() || msg.isEmpty()) {
return;
}
//获取进程码
static auto pid = getpid();
//获取线程PID
static thread_local auto tid = syscall(__NR_gettid);
QString logInfo =
QString::fromLocal8Bit("[%1] %2 %3 [%4] [%5] [%6] [%7] %8")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz"))
.arg(pid)
.arg(tid)
.arg(msgType[type])
.arg(function)
.arg(context.line)
.arg(msg.toUtf8().data());
switch (type) {
case QtDebugMsg:
qInfo().noquote() << logCommands[enumToInt(LogType::FrontPurple)]
<< logInfo << logCommands[0];
htQLog::debug(logInfo); //自定义的处理函数
break;
case QtInfoMsg:
qInfo().noquote() << logCommands[enumToInt(LogType::FrontGreen)]
<< logInfo << logCommands[0];
htQLog::info(logInfo);
break;
case QtWarningMsg:
qInfo().noquote() << logCommands[enumToInt(LogType::FrontYellow)]
<< logInfo << logCommands[0];
htQLog::warning(logInfo);
break;
case QtCriticalMsg:
qInfo().noquote() << logCommands[enumToInt(LogType::FrontRed)]
<< logCommands[enumToInt(LogType::Bold)] << logInfo
<< logCommands[0];
htQLog::critical(logInfo);
break;
case QtFatalMsg:
qInfo().noquote() << logCommands[enumToInt(LogType::FrontRed)]
<< logCommands[enumToInt(LogType::Bold)] << logInfo
<< logCommands[0];
htQLog::fatal(logInfo);
break;
default:
break;
}
}
超级终端的字体背景和颜色显示
# man console_codes //查看支持哪些颜色
printf(“\033[0;30;41m color!!! \033[0m Hello \n”);
其中41的位置代表字的背景色, 30的位置是代表字的颜色,0 是字的一些特殊属性,0代表默认关闭,一些其他属性如闪烁、下划线等。ascii code 是对颜色进行调用的。
\033[ ; m …… \033[0m
颜色的控制通过ESC字符(\033)加”[“加颜色代码加”m”实现。ESC的ASCII码是十进制的27,八进制的033(\033)
在 ANSI 兼容终端里,可以用彩色显示文本而不仅仅是黑白。但是我们自己编写的程序能否输出彩色的字符呢?当然答案是肯定的。下面的语句就输出高亮的黑色背景的绿色字。
\033 声明了转义序列的开始,然后是 [ 开始定义颜色。后面的 1 定义了高亮显示字符。然后是背景颜色,这里面是40,表示黑色背景。接着是前景颜色,这里面是32,表示绿色。我们用 \033[0m 关闭转义序列, \033[0m 是终端默认颜色。通过上面的介绍,就知道了如何输出彩色字符了。
printf(“\033[1;40;32m color!!! \033[0m hello\n”);
————————————————
原文链接:https://blog.csdn.net/u014470361/article/details/81512330
写入文件
自定义写入文件接口,将log保存至文件。
htQLog::debug(logInfo);
htQLog::info(logInfo);
htQLog::warning(logInfo);
htQLog::critical(logInfo);
htQLog::fatal(logInfo);
QFile file("log.txt");
file.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream text_stream(&file);
text_stream << message << "\r\n";
file.flush();
file.close();
多线程log日志
- 多线程下I/O操作枷锁
void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
// 加锁
static QMutex mutex;
mutex.lock();
/*
* log 组包
*/
...
// 解锁
mutex.unlock();
}
开源log库
-
上述写法适用与小型项目,对实时性要求不高。 但是读写文件和获取时间其实是耗时的,再加上锁后,可能会都系统性能要求高的项目有影响。
-
log4qt、spdlog、log4cpp