Qslog源码下载地址:https://github.com/victronenergy/QsLog
(1)源码集成
在你的工程中,直接包含QsLog.pri文件,进行源码集成。当然你也可以包含QsLog.pri后,编译为xx.dll,在应用工程中去调用xx.dll。
(2)动态库集成
编译QsLogSharedLibrary.pro,生成动态链接库QsLog2.dll,在你的工程中进行调用。
支持六个日志级别,优先级从低到高依次为:Trace、Debug、Info、Warn、Error、Fatal、Off。如下:
enum Level
{
TraceLevel = 0,
DebugLevel,
InfoLevel,
WarnLevel,
ErrorLevel,
FatalLevel,
OffLevel
};
可以通过setLoggingLevel()设置记录日志的级别。
void setLoggingLevel(Level newLevel)
注意:
一般我们可以将日志级别保存到配置文件,以便程序发布后,可通过修改配置来改变记录日志级别。
QsLog的使用很简单,在我们自己的工程中直接include它的QsLog.pri文件,然后源文件中包含QsLog.h就可以使用了。
(1)输出到文件(支持文件分割)
// 测试文件为目的地
void test_output_file()
{
// 初始化日志机制
Logger& logger = Logger::instance();
logger.setLoggingLevel(QsLogging::TraceLevel);
// 添加文件为目的地
const QString sLogPath(QDir(QApplication::applicationDirPath()).filePath("log.txt"));
DestinationPtr fileDestination(DestinationFactory::MakeFileDestination(
sLogPath, EnableLogRotation, MaxSizeBytes(512*1024), MaxOldLogCount(5)));
logger.addDestination(fileDestination);
// 打印日志
QLOG_TRACE() << "1-trace msg";
QLOG_DEBUG() << "2-debug msg";
QLOG_INFO() << "3-info msg";
QLOG_WARN() << "4-warn msg";
QLOG_ERROR() << "5-error msg";
QLOG_FATAL() << "6-fatal msg";
QsLogging::Logger::destroyInstance();
}
目前为TraceLevel,则日志级别比TraceLevel高的都会输出到文件;
若为ErrorLevel,则只有"5-error msg"和"6-fatal msg"这2条会输出。
static DestinationPtr MakeFileDestination(
const QString& filePath,
LogRotationOption rotation = DisableLogRotation,
const MaxSizeBytes &sizeInBytesToRotateAfter = MaxSizeBytes(),
const MaxOldLogCount &oldLogsToKeep = MaxOldLogCount()
);
函数参数含义:
前者表示禁止日志文件分割,即日志始终往一个文件中写入。
后者表示启用日志文件分割,此时sizeInBytesToRotateAfter和oldLogsToKeep参数才有意义。
(2)输出到控制台STDOUT
// 测试stdout为目的地
void test_output_stdout()
{
// 初始化日志机制
Logger& logger = Logger::instance();
logger.setLoggingLevel(QsLogging::TraceLevel);
// 添加stdout为目的地
DestinationPtr debugDestination(DestinationFactory::MakeDebugOutputDestination());
logger.addDestination(debugDestination);
// 打印日志
QLOG_TRACE() << "1-trace msg";
QLOG_DEBUG() << "2-debug msg";
QLOG_INFO() << "3-info msg";
QLOG_WARN() << "4-warn msg";
QLOG_ERROR() << "5-error msg";
QLOG_FATAL() << "6-fatal msg";
QsLogging::Logger::destroyInstance();
}
(3) 输出到处理函数
void logFunction(const QString &message, QsLogging::Level level)
{
qDebug() << "From log function: " << qPrintable(message) << " " << static_cast(level);
}
// 测试函数为目的地
void test_output_function()
{
// 初始化日志机制
Logger& logger = Logger::instance();
logger.setLoggingLevel(QsLogging::TraceLevel);
// 添加函数为目的地
DestinationPtr functorDestination(DestinationFactory::MakeFunctorDestination(&logFunction));
logger.addDestination(functorDestination);
// 打印日志
QLOG_TRACE() << "1-trace msg";
QLOG_DEBUG() << "2-debug msg";
QLOG_INFO() << "3-info msg";
QLOG_WARN() << "4-warn msg";
QLOG_ERROR() << "5-error msg";
QLOG_FATAL() << "6-fatal msg";
QsLogging::Logger::destroyInstance();
}
输出到函数,该函数需要定义为如下类型:
typedef void (*LogFunction)(const QString &message, Level level);
(4)输出到QTEXTEDIT控件
除了上面的输出方式,还可以输出到一个QObject对象上,主要是通过信号槽机制,将打印日志发送到QObject的槽函数进行处理。
void MainWindow::writeLog(const QString &message, int level)
{
ui->textEdit->append(message + " " + QString::number(level));
}
// 测试QObject为目的地
void test_output_qobject(MainWindow* window)
{
// 初始化日志机制
Logger& logger = Logger::instance();
logger.setLoggingLevel(QsLogging::TraceLevel);
// 添加QObject为目的地
DestinationPtr objectDestination(DestinationFactory::MakeFunctorDestination(window, SLOT(writeLog(QString,int))));
logger.addDestination(objectDestination);
// 打印日志
QLOG_TRACE() << "1-trace msg";
QLOG_DEBUG() << "2-debug msg";
QLOG_INFO() << "3-info msg";
QLOG_WARN() << "4-warn msg";
QLOG_ERROR() << "5-error msg";
QLOG_FATAL() << "6-fatal msg";
QsLogging::Logger::destroyInstance();
}
输出到QObject时,需要定义其槽函数,为如下类型:
void xxxx(const QString &message, int level)
写本例子时,发现TRACE信息不能输出到QObject,是因为QsLogDestFunctor.cpp文件中,write函数有个bug,如下:
void QsLogging::FunctorDestination::write(const QString &message, QsLogging::Level level)
{
if (mLogFunction)
mLogFunction(message, level);
if (level > QsLogging::TraceLevel)
emit logMessageReady(message, static_cast(level));
}
应将>改为>=,修改后即可解决,如下:
void QsLogging::FunctorDestination::write(const QString &message, QsLogging::Level level)
{
if (mLogFunction)
mLogFunction(message, level);
if (level >= QsLogging::TraceLevel)
emit logMessageReady(message, static_cast(level));
}
在QsLog.pri文件中
DEFINES += QS_LOG_LINE_NUMBERS
打开此宏定义,重新编译,即可打印带源文件名称和行号的日志。如下:
禁用日志记录,有时候关闭日志记录是有必要的。可以通过3种方式实现:
使用日志宏进行打印日志是线程安全的,日志宏如下:
QLOG_TRACE() << "1-trace msg";
QLOG_DEBUG() << "2-debug msg";
QLOG_INFO() << "3-info msg";
QLOG_WARN() << "4-warn msg";
QLOG_ERROR() << "5-error msg";
QLOG_FATAL() << "6-fatal msg";
这在前面我们已经使用过了。
如setLoggingLevel()、addDestination()函数不是线程安全的。
所谓的异步打印,其实就是单独开一个线程来专门写日志。
在QsLog.pri文件中
DEFINES += QS_LOG_SEPARATE_THREAD
打开此宏定义,重新编译,日志内容就会在单独的线程中排队并写入