Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to log to file AND debugger at once?
Forum Updated to NodeBB v4.3 + New Features

How to log to file AND debugger at once?

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 4 Posters 1.8k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    Tobias Fensch
    wrote on last edited by
    #1

    Hi there,

    I know that I can install mal own message handler to write debug output in a file. But that disables the debug output in QtCreator completely.

    How can I write my debug messages to the debugger again?
    fprintf(stderr, ...) doesnt work.

    regards,
    Tobias

    D JonBJ 3 Replies Last reply
    0
    • T Tobias Fensch

      Hi there,

      I know that I can install mal own message handler to write debug output in a file. But that disables the debug output in QtCreator completely.

      How can I write my debug messages to the debugger again?
      fprintf(stderr, ...) doesnt work.

      regards,
      Tobias

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #3

      @Tobias-Fensch
      My recollection: QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)

      Installs a Qt message handler which has been defined previously. Returns a pointer to the previous message handler.

      I think you need to remember that previous message handler returned when you install and call that explicitly at the beginning or end of your own added code, to get the original behaviour too. Try it out.

      T 1 Reply Last reply
      3
      • T Tobias Fensch

        Hi there,

        I know that I can install mal own message handler to write debug output in a file. But that disables the debug output in QtCreator completely.

        How can I write my debug messages to the debugger again?
        fprintf(stderr, ...) doesnt work.

        regards,
        Tobias

        D Offline
        D Offline
        DerReisende
        wrote on last edited by
        #2

        @Tobias-Fensch If you write your custom handler in a way that it logs both to file and console you get the desired output. I for example use a custom qt message handler to redirect logging to spdlog library which displays both on console and writes asynchronously to file

        1 Reply Last reply
        0
        • T Tobias Fensch

          Hi there,

          I know that I can install mal own message handler to write debug output in a file. But that disables the debug output in QtCreator completely.

          How can I write my debug messages to the debugger again?
          fprintf(stderr, ...) doesnt work.

          regards,
          Tobias

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #3

          @Tobias-Fensch
          My recollection: QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)

          Installs a Qt message handler which has been defined previously. Returns a pointer to the previous message handler.

          I think you need to remember that previous message handler returned when you install and call that explicitly at the beginning or end of your own added code, to get the original behaviour too. Try it out.

          T 1 Reply Last reply
          3
          • T Tobias Fensch

            Hi there,

            I know that I can install mal own message handler to write debug output in a file. But that disables the debug output in QtCreator completely.

            How can I write my debug messages to the debugger again?
            fprintf(stderr, ...) doesnt work.

            regards,
            Tobias

            D Offline
            D Offline
            DerReisende
            wrote on last edited by DerReisende
            #4

            @Tobias-Fensch
            I use the following code for logging to console and file:

            #include <fmt/format.h>
            #include <qlogging.h>
            #include <QDebug>
            
            #include <spdlog/spdlog.h>
            #include "spdlog/async.h"
            #include <spdlog/sinks/stdout_color_sinks.h>
            #include <spdlog/sinks/rotating_file_sink.h>
            #include <QStandardPaths>
            #include <QFile>
            
            #include "logging.h"
            
            static void init_spdlog() {
                constexpr int FILE_SIZE = 1 * 1024 * 1024; // 1 Megabyte
                constexpr int NUM_KEPT_LOGS = 2;
                spdlog::init_thread_pool(8192, 1);
                auto stdout_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
            
                const QString fileName{"app.log"};
                auto logFileLocation = QStandardPaths::locate(QStandardPaths::StandardLocation::DocumentsLocation,
                                                         "", QStandardPaths::LocateDirectory);
                if (logFileLocation.isEmpty()) {
                    qFatal("Unable to find standard directory");
                }
                logFileLocation += fileName;
                auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logFileLocation.toStdString(),
                                                                                            FILE_SIZE, NUM_KEPT_LOGS);
                std::vector<spdlog::sink_ptr> sinks{stdout_sink, rotating_sink};
                auto logger = std::make_shared<spdlog::async_logger>("loggername", sinks.begin(), sinks.end(),
                                                                     spdlog::thread_pool(), spdlog::async_overflow_policy::block);
            
                spdlog::set_default_logger(logger);
                spdlog::set_pattern("[%H:%M:%S.%f] [%^%=10l%$] [thread %t] %v");
                spdlog::flush_every(std::chrono::seconds(3));
                spdlog::set_level(spdlog::level::debug); // Set global log level to debug
            }
            
            static void qt_message_handler(QtMsgType type, [[maybe_unused]] const QMessageLogContext &context, const QString &msg) {
                const QByteArray localMsg = msg.toLocal8Bit();
            #ifdef NDEBUG
                const auto out_msg = fmt::format("\t{}", localMsg.constData());
            #else
                const char *function = context.function ? context.function : "";
                const auto out_msg = fmt::format("\t{} [LINE:{}, {}]",
                                                  localMsg.constData(),
                                                  context.line,
                                                  function);
            #endif
                switch (type) {
                    case QtDebugMsg:
                        spdlog::debug(out_msg);
                        break;
                    case QtInfoMsg:
                        spdlog::info(out_msg);
                        break;
                    case QtWarningMsg:
                        spdlog::warn(out_msg);
                        break;
                    case QtCriticalMsg:
                        spdlog::error(out_msg);
                        break;
                    case QtFatalMsg:
                        spdlog::critical(out_msg);
                        spdlog::shutdown();
                        break;
                }
            }
            
            void init_logging() {
                init_spdlog();
            
                qInstallMessageHandler(qt_message_handler);
            }
            

            Uses fmt and spdlog libraries.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #5

              Hi,

              Your issue is in fact simple: your handler only writes to your logger hence no message seen anymore on the standard output/error channels.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • JonBJ JonB

                @Tobias-Fensch
                My recollection: QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)

                Installs a Qt message handler which has been defined previously. Returns a pointer to the previous message handler.

                I think you need to remember that previous message handler returned when you install and call that explicitly at the beginning or end of your own added code, to get the original behaviour too. Try it out.

                T Offline
                T Offline
                Tobias Fensch
                wrote on last edited by
                #6

                @JonB that does the trick! thanks.

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved