Qt5: How to use qDebug() to log in a file, multi-thread application

十年热恋 提交于 2019-12-18 13:07:35

问题


I started using Qt5 few days ago. I needed a logger for my app and I decided to use qDebug, but it seems it has to be "redirected" in order to have the logs in a file.

I used qInstallMessageHandler to do that and I wrote my own handler as presented below (inspired from other people here).

It seems it works, but as I am not a guru, I have to ask: Is it ok to use this in a multi-thread application or not?

Also, if it is ok/safe for using in a multi-thread app, can it be improved somehow?

void MessageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg)
{
    mutex.lock();

    QDateTime dateTime(QDateTime::currentDateTime());

    QString timeStr(dateTime.toString("dd-MM-yyyy HH:mm:ss:zzz"));
    QString contextString(QString("(%1, %2)").arg(context.file).arg(context.line));

    QFile outFile("file.log");
    outFile.open(QIODevice::WriteOnly | QIODevice::Append);

    QTextStream stream(&outFile);
    stream << timeStr << " " << contextString << ": " << msg << endl;

    mutex.unlock();
}

回答1:


Your approach looks simple and clean. I'd keep it like that.

There is one thing you can improve: Open the file only once at application start and close it when you close the application. Opening a file is an expensive operation.

You can write into the same open file from multiple threads, since your mutex ensures that only one thread writes at the same time.




回答2:


You can not find anywhere in the Qt documentation that qDebug is thread-safe. So it is not safe to call it simultaneously from multiple threads and indeed you would encounter mixed output if you don't use a locking mechanism.

Your locking approach would be better if you use QMutexLocker as it is strongly recommended by the Qt documentation:

void MessageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg)
{
    QMutexLocker locker(&mutex);
    ...
}

A second approach is to provide a worker class that has slots for writing the log. You can then have an instance of it in a new thread and call it's slots in message handler using QMetaObject::invokeMethod with a Qt::QueuedConnection connection type. This way each call from each thread would be queued and process in the worker thread and it would probably have a better performance since all the job is done in a separate thread.




回答3:


I saw no reply to your concerns about sluggish, I'm sure by this time you figured something out. You could probably improve performance by reducing the amount of code within the critical region. File operations are slow so try to reduce the amount of time spent doing them. This can include keeping the file open, buffering the log and writing periodically, construct the entry out of the locked region and

void MessageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg)
{

    QDateTime dateTime(QDateTime::currentDateTime());

    QString timeStr(dateTime.toString("dd-MM-yyyy HH:mm:ss:zzz"));
    QString contextString(QString("(%1, %2)").arg(context.file).arg(context.line));
    QString entryString("%1 %2: %3");
    entryString = entryString.arg(timeStr).arg(contextString).arg(msg);

    QFile outFile("file.log");

    mutex.lock();
    outFile.open(QIODevice::WriteOnly | QIODevice::Append);  
    QTextStream stream(&outFile);  
    stream << entryString << endl;    
    mutex.unlock();
}


来源:https://stackoverflow.com/questions/29449237/qt5-how-to-use-qdebug-to-log-in-a-file-multi-thread-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!