Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • 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
Forum Updated to NodeBB v4.3 + New Features

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 7.6k 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.
  • C Offline
    C Offline
    chandan94
    wrote on last edited by chandan94
    #1

    I am creating a log for my application, printing the current date, time and other stuff. But I am struck at writing the filename and line number(the line from where I am calling my write function) into a file. Basically, I am using

    fileio.write("/tmp/test.log", Qt.formatDateTime(new Date(), "MMM dd hh:mm:ss.zzzzzz") + "|" + "|" + "|" + "Back button clicked" + "|" + "fileName:Menu.qml" + "|" + "lineNumber:30" + "\n");

    in my qml to call a fileio function which does the write operation. As you can see I am printing the line number and filename manually. Is there a way to print it dynamically?
    Can somebody help out?
    TIA.

    1 Reply Last reply
    0
    • 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 Online
          hskoglundH Online
          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 Online
              hskoglundH Online
              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 Online
                    hskoglundH Online
                    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 Extensions
                        • Unsolved