Logger: simple, convinient and thread safe logger for Qt applications



  • Hello in there.

    I want to proudly present the simple logging component for the Qt applications we're internally using for some of our projects. This component is designed concerning the K.I.S.S. principle and proved itself to be very stable and convinient to use. And yes, it's thread safe and ready for using in multi-threaded applications. I really hope it would be useful for you.

    Here's a simple code example using it:

    #include <QCoreApplication>
    
    #include <Logger.h>
    #include <ConsoleAppender.h>
    
    int main(int argc, char* argv[])
    {
      QCoreApplication app(argc, argv);
      ...
      ConsoleAppender* consoleAppender = new ConsoleAppender();
      consoleAppender->setFormat("[%{type}] <%{function}> %{message}\n");
      logger->registerAppender(consoleAppender);
      ...
      LOG_INFO("Starting the application");
      int result = app.exec();
      ...
      if (result)
        LOG_WARNING() << "Something went wrong." << "Result code is" << result;
    
      return result;
    }
    

    Library is Qt 4 and Qt 5 compatible, tested on Windows, Linux and Android (LogCat support included out-of-the-box). Also you may wish to know, that it's not meant to be a separate component, but it's prepared for including to your application sources, for example, using the git submodule approach. Build scripts to use the Logger in qmake-, CMake- or qbs-based projects are included. Logger also supports using many so-called appenders at once (targeting the log stream to different places), logging categories and many other features: just see the docs :)

    It's distributed free of charge according to the terms of LGPL 2.1 license and can be downloaded on the project GitHub page: https://github.com/dept2/CuteLogger

    Rather full documentation on it is embedded into a header files and may be generated using the doxygen (Doxyfile supplied).

    Waiting for your comments and suggestions :)



  • At first sight (just from your sample above), it looks a little bit like the Qxt logger framework. You have different "appenders", which would in the Qxt lib be QxtLoggerEngines. You have different logging levels, also supported in Qxt. Instead of qxtLog->info, you use LOG_INFO. Looks pretty similar. Yours is LGPL, Qxt is CPL and LGPL and moving to BSD, I believe.

    What is the unique feature, would you say, of your framework above existing ones?



  • I really don't pretend to make an ultimate and unique logging engine for all of the applications you can imagine. There's plenty of libraries for this (QxlLogger you mentioned, log4cxx and much more).

    Just a little list of (IMHO) advantages:

    • Default set of macros (LOG_DEBUG, LOG_INFO etc) collects source file name, source file line and function name (using the FILE, LINE and Q_FUNC_INFO macros accoringly) in addition to the traditional timestamp, log level and message. It gives some more flexibility when debugging a medium sized or large application, without need to seek manually, what part of code sent this message. For example, you can make a little plugin for your favourite IDE (I'll try to publish the plugin for Qt Creator later) and a little appender that sends the log messages over IPC to move to the line of your source that emitted a log message with just a mouse click.
    • It uses the Qt standart QDebug class instead of the custom QxtLogStream class which gives you an opportunity to use the already overloaded operator<<() for your custom types instead of writing the new ones.
    • It haves an AbstractStringAppender class, which gives a flexible way to customize the look of the simple stream log without any modifications to the library code. I've looked through the QxtLogger documentation and haven't found any similiar functionality. For example, you may use "[%l] %m\n" format, which will give you messages like "[Info] Some message text", or something more compicated like "%t{HH:mm:ss.zzz} [%-7l] <%C> %m\n" which will transform to "12:18:11.485 [Debug ] <void Foo::bar(int) const> Some debug message text" :)

    To use it or not is just a matter of taste. Just wanted to publish the little utility which i actively use, hoping that it would be useful for someone else. Also, it will be very interesting for me to add some features to it, according to other developers wishes and comments :)

    If you really think that this library must not be published here, I think this forum thread could be simply removed.

    Upd: just to mention, if the LGPL 2.1 restrictions are unacceptable for someone here, it may be discussed privately (no problems with it).



  • Please don't view my question as an attack. It was mend as an honest question. The features you mention are interesting. It does look like a valuable tool, and some competition to existing solutions can't hurt (though contributing ideas and code to those instead of starting your own also doesn't hurt).

    Thanks for sharing your code, and thanks for clarifying what the strongpoints of your solution are! Note that you can use the standard qDebug() << stuff with QxtLogger too, as you can easily re-route qDebug to QxtLogger either with custom code or simply with QxtLogger::installAsMessageHandler(). Still, you mention some nice features, such as automagically logging the place of the event in the code, and the flexible formatting.



  • Thanks for your question. To be honest, it was my fault: this features (and comparation to QxtLogger) must have been published here at the starting of this topic. But the hard work of documenting the library in english (it was documented poorly and in russian) haven't left place for any good ideas in my mind :)

    The main point of writing this library was to collect the places of code in addition to logging messages. It was quite useful for our small team and rather big codebase.

    I forgot to say, that Logger also installs itself as the Qt message handler, but it cannot be configured in a way that QxtLogger does (haven't any need for this).



  • Can you please let me know where can I download it, it looks good with your texts and I have never used any logger before for Qt



  • [quote author="Immii" date="1292997872"]Can you please let me know where can I download it, it looks good with your texts and I have never used any logger before for Qt[/quote]
    Look at the gitorious link in the original posting. The code is right there!



  • This looks like exactly what my application needs - being still new to Qt, can you provide some instructions for how to build this or where to place the files?



  • The above code explaing how to use ConsoleAppender. I am more interested in learning about how to use FileAppender. If I want use the FileAppender in QPushButton what I need to do.



  • Why do you think there is a difference, other than switching out FileAppender for ConsoleAppender and making sure it has a file name?

    And what do you mean by
    [quote author="01amit" date="1330493543"]If I want use the FileAppender in QPushButton what I need to do.[/quote]
    Using FileAppender in QPushButton? Do you mean you want to trigger logging something if you click on some push button?



  • Yes, whenever i click on push button it should write something to text file. How do I change the following code if I want to use FileAppender. I am very new to this. Where do I specify file name.
    @
    int main(int argc, char* argv[])
    {
    QCoreApplication app(argc, argv);

    ConsoleAppender* consoleAppender = new ConsoleAppender();
    consoleAppender->setFormat("[%-7l] <%C> %m\n");
    Logger::registerAppender(consoleAppender);

    LOG_INFO("Starting the application");
    int result = app.exec();

    if (result)
    LOG_WARNING() << "Something went wrong." << "Result code is" << result;

    return result;
    }
    @

    Edit: please use @ tags around your code sections; Andre



  • Take a look at the header file of FileAppender, especially the constructor. It takes one additional argument...



  • Thanks. now I understood how to use file appender and log data into txt file. I want use SQL database instead of txt file how can i do that.



  • Write a new appender that does just that. You can start by subclassing AbstractStringAppender. Instead of outputting to file, you can use Qt's SQL classes to output to a database.



  • Andre, thanks for your answers in this topic :)

    CuteLogger have been updated about a day ago (thanks goes to Karl-Heinz Reichel). We finally got rid of symlinks in repository, added the Win32 builds support and a qmake file, so currently most of the Qt developers can build it without installing cmake.



  • Hi there,

    I'm starting the logger in main(). When I'm including <Logger.h> in some class of my application the compiler states:

    error: invalid use of incomplete type ‘struct QDebug’
    error: forward declaration of ‘struct QDebug’

    and I still need to incude <QDebug> as well. Is that normal behaviour?

    Thanks!



  • Please update to the current version of Logger. As of commit "c7d9a27":https://gitorious.org/cutelogger/cutelogger/commit/c7d9a27110b110298fdf42b417b6e0e246fa96af QDebug header is included into Logger.h.



  • Nice, works!



  • How to I destroy this logger object and reinstantiate it without existing the application. Say I have three push buttons (1, 2, 3). I want to instantiate when button 1 is pressed. and use LOG_INFO macro when button 2 is pressed. Flush the data to the file when button 3 is pressed and destroy the object. Re-instantiate the class when button 1 is pressed again without closing the application.
    In my application we never exit the application it contoneously runs. I am looking for a way to instantiate the class, use log_info, detroy the object and then reinstantiate.



  • Well, I definitely need to ask a question here: why do you need to manually instantiate and destroy Logger?

    This library is created as singleton without any visible initialization by design. Its main object is automatically created on the first Logger::* static function or macro call. As you can see in "Logger.cpp":https://gitorious.org/cutelogger/cutelogger/blobs/master/src/Logger.cpp the object is automatically destroyed after the application have been closed (using the qAddPostRoutine function).

    So, once again: why do you want to do manually the thing that is done automatically? :)



  • I want to desroy the object when the button is clicked not when the application have been closed.



  • in which version of Qt i can find these files, <Logger.h> and <ConsoleAppender.h> ??? :-?



  • [quote author="aekam" date="1334749555"]in which version of Qt i can find these files, <Logger.h> and <ConsoleAppender.h> ??? :-?[/quote]
    You can't. It's an external project. See the very first post in this topic.



  • How about logging size ? I searched in several Qt based logging libs ( QxtLogger, log4qt ..... ) didn't find any functions in it, related to the size of log functionality. So it will be very usefull to see this functionality !



  • I don't understand the question. What do you mean with 'logging size'? Do you want to set some kind of maximum size for the log file output or something like that?



  • Yes, for example : maximum log messages ( last 100 messages ) , or maximum log file size.



  • I search frew several projects, and no one provide such functionality. Only log4qt, but it hard to understand, and implement.



  • Personally, I think log rotation is a separate task. It seems quite expensive to do something like limiting to the last 100 messages. It means re-writing the entire logfile for each message, as you cannot remove from the start of a file. Adding is trivial though.



  • i already tried my self re-writing file and this real complex task, and heavy in time execution... but log can be very fast happend... but what, if i don't need handle a lot of messages ....



  • I have no idea what you just asked. Sorry.



  • IMO the most correct way to implement a log rotation is to create separate log files for every week/day/hour (choose yours interval) and to automatically remove older logs becoming obsolete. For example, Apache web server logging is organized in such a way. We've implemented that kind of log rotation for one of our projects using Logger some time ago, but I've never published those classes. The problem is I can't share the source because of some licensing restrictions (it was created by another developer working on a commercial project).

    Anyone interested in implementing that kind of functionality (and adding it to logger mainstream code) could easily contact me via email or simply post a merge request on gitorious.



  • Just merged "one important change":https://gitorious.org/cutelogger/cutelogger/merge_requests/2 (thanks goes to Pritam Ghanghas). Now LOG_DEBUG() and other similiar macros supports all the features of qDebug() and could also support the printf-like syntax so we can simply search-and-replace qDebug() with LOG_DEBUG() and QDebug or QtDebug header with Logger.h

    Still waiting for your contributions to make Logger more useful :)



  • Just wanted to notify the project's maintainers that cutelogger doesn't compile using Qt 5 Beta2 with deprecated API turned off by default: qInstallMsgHandler() has become deprecated.



  • Ok, thank you for notification. Currently there is only one project maintainer and I don't have much time for now to implement and support the Qt 5.0.0 compatibility of the project.

    Taking a quick look through the Qt 5 beta2 headers I've noticed there is a lot of work to be done refactoring the Logger to take advantage of the extended Qt 5 logging abilities. If anyone is willing to implement Qt 5 compatibility and post it as a merge request on Gitorious the contribution will be kindly accepted :)



  • Pushed "e3c2745":https://gitorious.org/cutelogger/cutelogger/commit/e3c2745c6c5f38896f87472e01ea2caf2d9e211b. Now Logger successfully builds with Qt 5 and uses some of its advanced logging feature (e.g. file/line/function name gathered in renewed qDebug and the same macros).

    Still some work to be done to support "log categories":https://codereview.qt-project.org/#change,13226 and new Qt log formatting feature in a ConsoleAppender.



  • How do I enable/disable the CuteLogger?



  • @cyberbobs said:

    Hello

    Hello! How do I connect this component to my program, it is necessary to compile? I can not find a solution.
    I copied files but there were errors.
    android/log.h: No such file or directory
    #include <android/log.h>

    windows.h: No such file or directory
    #include <windows.h>

    My system Ubuntu 14.04



  • @Alexorleon Replied to your question on Github. Basically, you don't need to include windows-specific or console appenders to Android project, it is already handled in pro file included in the library sources. Also, it is suggested that you will include CuteLogger sources to your project (if you store project in git repository, you can add it as submodule) and build it alongside your project instead of building it separately and adding the prebuild libraries.



  • Hey, thanks for this library, it's really cool.

    I'd like to know if it was possible and safe to write in several files? I'd like to create several FileAppender's and decide in which of these files I should write.

    Is there any way to indicate to LOG_INFO() the FileAppender I want to write in?



  • Use syslog, it's simple, convenient and thread safe, and has powerful tools to work with (e.g., syslog-ng server). Don't reinvent the wheel!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.