Unsolved How to fetch the current file name and line number to be written into a file for logging purpose
-
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. -
You can do it with
qInstallMessageHandler
This will intercepts call toconsole.log
,console.debug
...
The example in the documentation outputs the line number like you want. -
@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. -
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"); ...
-
@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. -
@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).
-
@hskoglund
Hi, I am making a Qt quick application. Can you suggest something for this? Also, I am confused how to use qInstallMessageHandler. -
@hskoglund Indeed, you have to use
qDebug
and friends for that. -
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!
-
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 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?