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();
}
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With