Search code examples
linuxqt5boost-logqfilesystemwatcher

QFileSystemWatcher file changed signal emits only ones for few file update


I am using QFileSystemWatcher to control the log file changes. For creating and updating the log file I am using boost library.

When I log few messages in one method file changing signal emits only ones (for last message), but I see that file updating every time after log message added.

So, the code for QFileSystemWatcher is

    std::string fn = "app.log";
    logging::init_log(fn);
    QFileSystemWatcher* watcher = new QFileSystemWatcher();
    auto success = QObject::connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(handleFileChanged(QString)));
    Q_ASSERT(success);
    watcher->addPath(QString::fromStdString(fn));

adding log messages

void a(){
    /* some code */
    logging::write_log("test error", logging::kError);
    logging::write_log("test info", logging::kInfo);
}

QFileSystemWatcher emits signal only ones for Info level message. In file manager I see that file updating after each call (test error, test info). In log file initialization I use

    sink->locked_backend()->auto_flush(true);

so the file updates immediately.

How can I fix this? Or maybe there is another approach how to handle log file updating to show message in GUI.


Solution

  • Similar filesystem event notifications are usually collapsed into one, unless they are consumed by a reader. For example, if the writer writes 10 bytes to a file, the thread that monitors that file for writes will typically see one event instead of 10. This is explicitly outlined in inotify description notes on Linux, which is likely used internally by QFileSystemWatcher.

    This should not matter for any correct implementation of a filesystem monitoring software. The notification only allows the monitor to notice that some event happened (e.g. a write occurred), and it is up to the software to discover further details about the event (e.g. the amount of data that was written, and writing position).

    If you aim to just display the written logs, you should be able to just read the file contents from the current reading position to the end of the file. That read operation may return one log record or more. It can return an incomplete log record, too, if the C++ standard library is implemented in a certain way (e.g. when auto_flush is disabled, and the stream buffer fills the internal buffer with part of the log record content before issuing write). The monitoring software should parse the read content to separate log records and detect incomplete log records (e.g. split data by newline characters).