Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to fetch the current file name and line number to be written into a file for logging purpose
Qt 6.12 LTS is out! See what's new in the release blog

How to fetch the current file name and line number to be written into a file for logging purpose

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
11 Posts 4 Posters 10.3k Views 2 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.
  • GrecKoG Offline
    GrecKoG Offline
    GrecKo
    Qt Champions 2018
    wrote on last edited by
    #2

    You can do it with qInstallMessageHandler
    This will intercepts call to console.log , console.debug ...
    The example in the documentation outputs the line number like you want.

    1 Reply Last reply
    1
    • C Offline
      C Offline
      chandan94
      wrote on last edited by
      #3

      @GrecKo said in How to fetch the current file name and line number to be written into a file for logging purpose:

      documentation

      Thanks @GrecKo , But I dont want to print the line number on the console. I want to pass the line number that is fetched dynamically which is to be printed in a file. Also, any suggestions for fetching the file name dynamically which also needs to e printed into a file.
      TIA.

      GrecKoG 1 Reply Last reply
      0
      • hskoglundH Offline
        hskoglundH Offline
        hskoglund
        wrote on last edited by
        #4

        Hi, I had a similar problem, where I wanted to log filename+linenumer with a message as well. I came up with this (note: this was for widget-based .cpp code, no qml):

        // define a class for logging
        class LoggingObject
        {
            QString sFilename = "unknown";
            int     nLineNo   = 0;
        
            public:
            LoggingObject(QString sFilename,int nLineNo)
            {
                this->sFilename = sFilename;
                this->nLineNo   = nLineNo;
            }
        
            void logInvoker(const char *msg,...)
            {
           // build the log message using vasprintf
               va_list ap;
               va_start(ap, msg);
               QString sMsg = QString::vasprintf(msg, ap);
        
           // prefix with filename and lineno. and write to our file
              fileio.write(QString("File %1 lineno. %2 msg: '%3'").arg(sFilename).arg(nLineNo).arg(sMsg));
            }
        };
        

        then #define a macro to call it

        #define log LoggingObject(__FILE__,__LINE__).logInvoker
        

        then in your code you can write something like:

        ...
        log("Back button clicked");
        ...
        
        C 1 Reply Last reply
        3
        • C chandan94

          @GrecKo said in How to fetch the current file name and line number to be written into a file for logging purpose:

          documentation

          Thanks @GrecKo , But I dont want to print the line number on the console. I want to pass the line number that is fetched dynamically which is to be printed in a file. Also, any suggestions for fetching the file name dynamically which also needs to e printed into a file.
          TIA.

          GrecKoG Offline
          GrecKoG Offline
          GrecKo
          Qt Champions 2018
          wrote on last edited by
          #5

          @chandan94 with qInstallMessageHandler you do what you want with the message. You can output it to the console, write it to a file or both.

          hskoglundH 1 Reply Last reply
          0
          • GrecKoG GrecKo

            @chandan94 with qInstallMessageHandler you do what you want with the message. You can output it to the console, write it to a file or both.

            hskoglundH Offline
            hskoglundH Offline
            hskoglund
            wrote on last edited by
            #6

            @GrecKo Yes I use qInstallMessageHandler in all my programs, it's a handy function, but it can not help me with displaying the filename and linenumber from where I called the log macro to log something. For example:

            ...
            log("First message");
            ...
            log("Second message);
            ...
            

            (Those 2 calls should show the same filename like 'mainWindow.cpp' but different linenumbers).

            GrecKoG 1 Reply Last reply
            0
            • hskoglundH hskoglund

              Hi, I had a similar problem, where I wanted to log filename+linenumer with a message as well. I came up with this (note: this was for widget-based .cpp code, no qml):

              // define a class for logging
              class LoggingObject
              {
                  QString sFilename = "unknown";
                  int     nLineNo   = 0;
              
                  public:
                  LoggingObject(QString sFilename,int nLineNo)
                  {
                      this->sFilename = sFilename;
                      this->nLineNo   = nLineNo;
                  }
              
                  void logInvoker(const char *msg,...)
                  {
                 // build the log message using vasprintf
                     va_list ap;
                     va_start(ap, msg);
                     QString sMsg = QString::vasprintf(msg, ap);
              
                 // prefix with filename and lineno. and write to our file
                    fileio.write(QString("File %1 lineno. %2 msg: '%3'").arg(sFilename).arg(nLineNo).arg(sMsg));
                  }
              };
              

              then #define a macro to call it

              #define log LoggingObject(__FILE__,__LINE__).logInvoker
              

              then in your code you can write something like:

              ...
              log("Back button clicked");
              ...
              
              C Offline
              C Offline
              chandan94
              wrote on last edited by
              #7

              @hskoglund
              Hi, I am making a Qt quick application. Can you suggest something for this? Also, I am confused how to use qInstallMessageHandler.

              1 Reply Last reply
              0
              • hskoglundH hskoglund

                @GrecKo Yes I use qInstallMessageHandler in all my programs, it's a handy function, but it can not help me with displaying the filename and linenumber from where I called the log macro to log something. For example:

                ...
                log("First message");
                ...
                log("Second message);
                ...
                

                (Those 2 calls should show the same filename like 'mainWindow.cpp' but different linenumbers).

                GrecKoG Offline
                GrecKoG Offline
                GrecKo
                Qt Champions 2018
                wrote on last edited by
                #8

                @hskoglund Indeed, you have to use qDebug and friends for that.

                1 Reply Last reply
                0
                • hskoglundH Offline
                  hskoglundH Offline
                  hskoglund
                  wrote on last edited by
                  #9

                  I'm no expert on Qt quick apps, but qInstallMessageHandler works the same, and instead of qDebug(), in a .qml file you can use console.log. So lets try:

                  First declare your messagehandler, easiest is to include it in your main.cpp, something like this:

                  void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
                  {
                  // construct a msg
                      QString sFilename = context.category;
                      QString sFunction = context.function;
                      int nLineNo       = context.line;
                  
                      QString s = QString("File '%1' function '%2' at line no %3: '%4'\n").arg(sFilename).arg(sFunction).arg(nLineNo).arg(msg);
                  
                  // write to file
                     FILE* f;
                  #ifdef _MSC_BUILD
                      if (0 != fopen_s(&f,"myfile.log","a+"))   // MSVC compiler: fopen() is frowned upon, use fopen_s()
                          f = NULL;
                  #else
                      f = fopen("myfile.log","a+");          // all other compilers: use standard fopen() call
                  #endif
                      if (f)
                      {
                          fprintf(f,"%s",qUtf8Printable(s));
                          fclose(f);
                      }
                  
                  // also show if we're running inside Qt Creator (delayed)
                      fprintf(stderr,"%s",qUtf8Printable(s));
                  }
                  

                  and then inside your main() install the handler, easiest is at the beginning:

                  
                  int main(int argc, char *argv[])
                  {
                      qInstallMessageHandler(myMessageHandler);
                  
                      QGuiApplication app(argc, argv);
                  ...
                  

                  Now try using a console.log('Hello from qml') in a qml file. Good luck!

                  1 Reply Last reply
                  3
                  • Pradeep KumarP Offline
                    Pradeep KumarP Offline
                    Pradeep Kumar
                    wrote on last edited by
                    #10

                    Hi @chandan94

                    u can use the below mentioned way for all the debug, based on critical , fatal also.

                    int main(int argc, char *argv[])
                    {
                        QApplication a(argc, argv);
                    
                        qDebug() << Q_FUNC_INFO << "In Main " << endl;
                    #ifdef DEBUG
                        FILE * fp;
                        fp = fopen (LOG_FILE_PATH, "a+");
                        if(fp==NULL)
                            fp = fopen (LOG_FILE_PATH, "w");
                        if(fp==NULL){
                            return 0;
                        }
                        fclose(fp);
                        qInstallMessageHandler(myAppLogsToFile);
                    #endif
                        FirstClass firstClassObjecct;
                        firstClassObjecct.show();
                    
                        return a.exec();
                    }
                    
                    void myAppLogsToFile(QtMsgType type, const QMessageLogContext &context, const QString &msg)
                    {
                        QString timeFormat = "dd-MMM-yyyy hh:mm:ss:zzz"; // u can change the format  of datetime
                    
                        QByteArray localMsg = msg.toLocal8Bit();
                        QByteArray tim = QDateTime::currentDateTime().toString(timeFormat).toLocal8Bit();
                        FILE * fp;
                        fp = fopen (LOG_FILE_PATH, "a");
                    
                        if(fp==NULL){
                            return;
                        }
                        switch (type) {
                        case QtDebugMsg:
                            fprintf(fp, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
                            break;
                        case QtWarningMsg:
                            fprintf(fp, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
                            break;
                        case QtCriticalMsg:
                            fprintf(fp, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
                            break;
                        case QtFatalMsg:
                            fprintf(fp, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
                            abort();
                        default :
                            break;
                        }
                        fclose(fp);
                    }
                    

                    Thanks,

                    Pradeep Kumar
                    Qt,QML Developer

                    C 1 Reply Last reply
                    4
                    • Pradeep KumarP Pradeep Kumar

                      Hi @chandan94

                      u can use the below mentioned way for all the debug, based on critical , fatal also.

                      int main(int argc, char *argv[])
                      {
                          QApplication a(argc, argv);
                      
                          qDebug() << Q_FUNC_INFO << "In Main " << endl;
                      #ifdef DEBUG
                          FILE * fp;
                          fp = fopen (LOG_FILE_PATH, "a+");
                          if(fp==NULL)
                              fp = fopen (LOG_FILE_PATH, "w");
                          if(fp==NULL){
                              return 0;
                          }
                          fclose(fp);
                          qInstallMessageHandler(myAppLogsToFile);
                      #endif
                          FirstClass firstClassObjecct;
                          firstClassObjecct.show();
                      
                          return a.exec();
                      }
                      
                      void myAppLogsToFile(QtMsgType type, const QMessageLogContext &context, const QString &msg)
                      {
                          QString timeFormat = "dd-MMM-yyyy hh:mm:ss:zzz"; // u can change the format  of datetime
                      
                          QByteArray localMsg = msg.toLocal8Bit();
                          QByteArray tim = QDateTime::currentDateTime().toString(timeFormat).toLocal8Bit();
                          FILE * fp;
                          fp = fopen (LOG_FILE_PATH, "a");
                      
                          if(fp==NULL){
                              return;
                          }
                          switch (type) {
                          case QtDebugMsg:
                              fprintf(fp, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
                              break;
                          case QtWarningMsg:
                              fprintf(fp, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
                              break;
                          case QtCriticalMsg:
                              fprintf(fp, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
                              break;
                          case QtFatalMsg:
                              fprintf(fp, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
                              abort();
                          default :
                              break;
                          }
                          fclose(fp);
                      }
                      

                      Thanks,

                      C Offline
                      C Offline
                      chandan94
                      wrote on last edited by
                      #11

                      @Pradeep-Kumar said in How to fetch the current file name and line number to be written into a file for logging purpose:

                      u can use the below mentioned way for all the debug, based on critical , fatal also.

                      Hi @Pradeep-Kumar ,

                      I am using :

                      class FileIO : public QObject
                      {
                      Q_OBJECT
                      public slots:
                      bool write(const QString& source, const QString& data)
                      {
                      if (source.isEmpty())
                      return false;

                          QFile file(source);
                          if (!file.open(QFile::Append | QFile::Truncate))
                              return false;
                      
                          QTextStream out(&file);
                          out << data;
                          file.close();
                          return true;
                      }
                      

                      for write function.
                      And in qml:
                      fileio.write("/tmp/test.log", Qt.formatDateTime(new Date(), "MMM dd hh:mm:ss.zzzzzz") + "|" + "|" + "|" + "Back button clicked" + "|" + "fileName:Menu.qml" + "|" + "lineNumber:30" + "\n");
                      So is there some property like QT.formatDateTime property, which I can use directly to get the line number and filename?

                      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
                      • Unsolved