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. Basic logging system - problems

Basic logging system - problems

Scheduled Pinned Locked Moved Unsolved General and Desktop
5 Posts 5 Posters 203 Views
  • 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.
  • franco.amatoF Offline
    franco.amatoF Offline
    franco.amato
    wrote on last edited by
    #1

    I wrote a basic thread-safe logging system using a namespace:

    Logger.h

    #ifndef LOGGER_H
    #define LOGGER_H
    
    #include <QMutex>
    #include <QDateTime>
    #include <QFile>
    #include <QString>
    #include <QDir>
    
    namespace Logger {
        enum LogLevel {INFO, WARNING, ERROR, FATAL};
    
        // Function declarations
    
        bool init(const QDir& baseLogDir);
        void log(LogLevel level, const QString& message);
        void info(const QString& message);
        void warning(const QString& message);
        void error(const QString& message);
        void fatal(const QString& message);
        void closeLogFile();
    
        // Helper functions declaration
    
        QString formatLogEntry(LogLevel level, const QString& message);
        QString levelToString(LogLevel level);
    
        // Static members
    
        static QMutex  mutex;
        static QFile logFile;
        static bool logInitialized;
    } // namespace Logger
    
    #endif // LOGGER_H
    

    Logger.cpp

    #include "Logger.h"
    
    #include <QDateTime>
    #include <QFile>
    #include <QTextStream>
    
    namespace Logger {
    QMutex mutex;
    QFile logFile;
    bool logInitialized = false;
    
        QString levelToString(LogLevel level)
        {
            static const QMap<LogLevel, QString> levelMap {
                {INFO, "INFO"},
                {WARNING, "WARNING"},
                {ERROR, "ERROR"},
                {FATAL, "FATAL"}
            };
    
            return levelMap.value(level, "UNKNOW");
        }
    
    QString formatLogEntry(LogLevel level, const QString& message)
    {
        QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        return QString("%1 [%2] %3").arg(timestamp).arg(levelToString(level)).arg(message);
    }
    
    bool init(const QDir& baseLogDir)
    {
        QMutexLocker locker(&mutex);
    
        // Create the daily log directory if it doesn't exist
        if (!baseLogDir.exists())
        {
            if (!baseLogDir.mkpath(baseLogDir.absolutePath()))
            {
                qWarning() << "Failed to create base log directory:" << baseLogDir.path();
                return false;
            }
        }
    
        // Construct the full path to the daily log directory
        QString logFolderPath = baseLogDir.filePath(QDate::currentDate().toString("yyyy-MM-dd"));
        QDir logDirectory(logFolderPath);
    
        // Create the daily log directory if it does't exist
        if (!logDirectory.exists())
        {
            if (!logDirectory.mkdir("."))
            {
                qWarning() << "Failed to create daily log directory:" << logDirectory.path();
            }
        }
    
        // Get the current date and time
    
        // Get the current date and time and format it as "yyyy-MM-dd_hh-mm-ss.log"
        QString logFileName = QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") + ".log";
        QString logFilePath = logDirectory.filePath(logFileName);
    
        if (logFile.isOpen())
        {
            logFile.close();
        }
    
        // Open the new log file
        logFile.setFileName(logFilePath);
        if (!logFile.open(QIODevice::WriteOnly | QIODevice::Append))
        {
            qWarning() << "Failed to open log file: " << logFilePath;
            return false;
        }
    
        logInitialized = true;
        return true;
    }
    
    void log(LogLevel level, const QString& message)
    {
        QMutexLocker locker(&mutex);
        if (logInitialized && logFile.isOpen())
        {
            QTextStream out(&logFile);
            out << formatLogEntry(level, message) << Qt::endl << Qt::flush;
        }
    }
    
    void info(const QString& message)
    {
        log(INFO, message);
    }
    
    void warning(const QString& message)
    {
        log(WARNING, message);
    }
    
    void error(const QString& message)
    {
        log(ERROR, message);
    }
    
    void fatal(const QString& message)
    {
        log(FATAL, message);
    }
    
    void closeLogFile()
    {
        QMutexLocker locker(&mutex);
    
        if (logFile.isOpen())
        {
            logFile.close();
        }
    }
    
    } // namespace Logger
    

    I am having problems in initializing the static variables in the cpp file and also when I include Logger.h in any file, I get linker errors saying that there are linker conflicts even it there is not the same routine.
    What am i doing wrong?

    jsulmJ JonBJ 2 Replies Last reply
    0
    • franco.amatoF franco.amato

      I wrote a basic thread-safe logging system using a namespace:

      Logger.h

      #ifndef LOGGER_H
      #define LOGGER_H
      
      #include <QMutex>
      #include <QDateTime>
      #include <QFile>
      #include <QString>
      #include <QDir>
      
      namespace Logger {
          enum LogLevel {INFO, WARNING, ERROR, FATAL};
      
          // Function declarations
      
          bool init(const QDir& baseLogDir);
          void log(LogLevel level, const QString& message);
          void info(const QString& message);
          void warning(const QString& message);
          void error(const QString& message);
          void fatal(const QString& message);
          void closeLogFile();
      
          // Helper functions declaration
      
          QString formatLogEntry(LogLevel level, const QString& message);
          QString levelToString(LogLevel level);
      
          // Static members
      
          static QMutex  mutex;
          static QFile logFile;
          static bool logInitialized;
      } // namespace Logger
      
      #endif // LOGGER_H
      

      Logger.cpp

      #include "Logger.h"
      
      #include <QDateTime>
      #include <QFile>
      #include <QTextStream>
      
      namespace Logger {
      QMutex mutex;
      QFile logFile;
      bool logInitialized = false;
      
          QString levelToString(LogLevel level)
          {
              static const QMap<LogLevel, QString> levelMap {
                  {INFO, "INFO"},
                  {WARNING, "WARNING"},
                  {ERROR, "ERROR"},
                  {FATAL, "FATAL"}
              };
      
              return levelMap.value(level, "UNKNOW");
          }
      
      QString formatLogEntry(LogLevel level, const QString& message)
      {
          QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
          return QString("%1 [%2] %3").arg(timestamp).arg(levelToString(level)).arg(message);
      }
      
      bool init(const QDir& baseLogDir)
      {
          QMutexLocker locker(&mutex);
      
          // Create the daily log directory if it doesn't exist
          if (!baseLogDir.exists())
          {
              if (!baseLogDir.mkpath(baseLogDir.absolutePath()))
              {
                  qWarning() << "Failed to create base log directory:" << baseLogDir.path();
                  return false;
              }
          }
      
          // Construct the full path to the daily log directory
          QString logFolderPath = baseLogDir.filePath(QDate::currentDate().toString("yyyy-MM-dd"));
          QDir logDirectory(logFolderPath);
      
          // Create the daily log directory if it does't exist
          if (!logDirectory.exists())
          {
              if (!logDirectory.mkdir("."))
              {
                  qWarning() << "Failed to create daily log directory:" << logDirectory.path();
              }
          }
      
          // Get the current date and time
      
          // Get the current date and time and format it as "yyyy-MM-dd_hh-mm-ss.log"
          QString logFileName = QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") + ".log";
          QString logFilePath = logDirectory.filePath(logFileName);
      
          if (logFile.isOpen())
          {
              logFile.close();
          }
      
          // Open the new log file
          logFile.setFileName(logFilePath);
          if (!logFile.open(QIODevice::WriteOnly | QIODevice::Append))
          {
              qWarning() << "Failed to open log file: " << logFilePath;
              return false;
          }
      
          logInitialized = true;
          return true;
      }
      
      void log(LogLevel level, const QString& message)
      {
          QMutexLocker locker(&mutex);
          if (logInitialized && logFile.isOpen())
          {
              QTextStream out(&logFile);
              out << formatLogEntry(level, message) << Qt::endl << Qt::flush;
          }
      }
      
      void info(const QString& message)
      {
          log(INFO, message);
      }
      
      void warning(const QString& message)
      {
          log(WARNING, message);
      }
      
      void error(const QString& message)
      {
          log(ERROR, message);
      }
      
      void fatal(const QString& message)
      {
          log(FATAL, message);
      }
      
      void closeLogFile()
      {
          QMutexLocker locker(&mutex);
      
          if (logFile.isOpen())
          {
              logFile.close();
          }
      }
      
      } // namespace Logger
      

      I am having problems in initializing the static variables in the cpp file and also when I include Logger.h in any file, I get linker errors saying that there are linker conflicts even it there is not the same routine.
      What am i doing wrong?

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @franco-amato said in Basic logging system - problems:

      What am i doing wrong?

      You're not posting the error messages you get.

      You're redefining mutex, LogFile and logInitialized in your cpp file.
      I also do not see a reason to have those variables exposed to the code using logger - they should be moved to cpp file.

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • piervalliP Offline
        piervalliP Offline
        piervalli
        wrote on last edited by
        #3

        I use the class qDebug with qInstallMessageHandler to redirect output on file.

        1 Reply Last reply
        0
        • S Offline
          S Offline
          SimonSchroeder
          wrote on last edited by
          #4

          static in the context of namespaces does not mean the same as static inside classes/structs. Your variables are basically kind of global variables. However, the static in front of it makes them local to the compilation unit (i.e. each .cpp file including Logger.h will have their own set of variables). Because you are including Logger.h in Logger.cpp it will have its own set of these variables and then you redeclare them inside Logger.cpp. If those variables should only be accessed from within Logger.cpp, just throw them out of the header file. Otherwise, extern is most likely the keyword you are looking for instead of static. But, global variables are usually not a good idea. You could also just change the namespace Logger to the class Logger and make all functions static. Then you'd also get what you are actually trying to do (but you loose being able to pull in the namespace to avoid always having to write Logger::info(...) etc.).

          1 Reply Last reply
          3
          • franco.amatoF franco.amato

            I wrote a basic thread-safe logging system using a namespace:

            Logger.h

            #ifndef LOGGER_H
            #define LOGGER_H
            
            #include <QMutex>
            #include <QDateTime>
            #include <QFile>
            #include <QString>
            #include <QDir>
            
            namespace Logger {
                enum LogLevel {INFO, WARNING, ERROR, FATAL};
            
                // Function declarations
            
                bool init(const QDir& baseLogDir);
                void log(LogLevel level, const QString& message);
                void info(const QString& message);
                void warning(const QString& message);
                void error(const QString& message);
                void fatal(const QString& message);
                void closeLogFile();
            
                // Helper functions declaration
            
                QString formatLogEntry(LogLevel level, const QString& message);
                QString levelToString(LogLevel level);
            
                // Static members
            
                static QMutex  mutex;
                static QFile logFile;
                static bool logInitialized;
            } // namespace Logger
            
            #endif // LOGGER_H
            

            Logger.cpp

            #include "Logger.h"
            
            #include <QDateTime>
            #include <QFile>
            #include <QTextStream>
            
            namespace Logger {
            QMutex mutex;
            QFile logFile;
            bool logInitialized = false;
            
                QString levelToString(LogLevel level)
                {
                    static const QMap<LogLevel, QString> levelMap {
                        {INFO, "INFO"},
                        {WARNING, "WARNING"},
                        {ERROR, "ERROR"},
                        {FATAL, "FATAL"}
                    };
            
                    return levelMap.value(level, "UNKNOW");
                }
            
            QString formatLogEntry(LogLevel level, const QString& message)
            {
                QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
                return QString("%1 [%2] %3").arg(timestamp).arg(levelToString(level)).arg(message);
            }
            
            bool init(const QDir& baseLogDir)
            {
                QMutexLocker locker(&mutex);
            
                // Create the daily log directory if it doesn't exist
                if (!baseLogDir.exists())
                {
                    if (!baseLogDir.mkpath(baseLogDir.absolutePath()))
                    {
                        qWarning() << "Failed to create base log directory:" << baseLogDir.path();
                        return false;
                    }
                }
            
                // Construct the full path to the daily log directory
                QString logFolderPath = baseLogDir.filePath(QDate::currentDate().toString("yyyy-MM-dd"));
                QDir logDirectory(logFolderPath);
            
                // Create the daily log directory if it does't exist
                if (!logDirectory.exists())
                {
                    if (!logDirectory.mkdir("."))
                    {
                        qWarning() << "Failed to create daily log directory:" << logDirectory.path();
                    }
                }
            
                // Get the current date and time
            
                // Get the current date and time and format it as "yyyy-MM-dd_hh-mm-ss.log"
                QString logFileName = QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") + ".log";
                QString logFilePath = logDirectory.filePath(logFileName);
            
                if (logFile.isOpen())
                {
                    logFile.close();
                }
            
                // Open the new log file
                logFile.setFileName(logFilePath);
                if (!logFile.open(QIODevice::WriteOnly | QIODevice::Append))
                {
                    qWarning() << "Failed to open log file: " << logFilePath;
                    return false;
                }
            
                logInitialized = true;
                return true;
            }
            
            void log(LogLevel level, const QString& message)
            {
                QMutexLocker locker(&mutex);
                if (logInitialized && logFile.isOpen())
                {
                    QTextStream out(&logFile);
                    out << formatLogEntry(level, message) << Qt::endl << Qt::flush;
                }
            }
            
            void info(const QString& message)
            {
                log(INFO, message);
            }
            
            void warning(const QString& message)
            {
                log(WARNING, message);
            }
            
            void error(const QString& message)
            {
                log(ERROR, message);
            }
            
            void fatal(const QString& message)
            {
                log(FATAL, message);
            }
            
            void closeLogFile()
            {
                QMutexLocker locker(&mutex);
            
                if (logFile.isOpen())
                {
                    logFile.close();
                }
            }
            
            } // namespace Logger
            

            I am having problems in initializing the static variables in the cpp file and also when I include Logger.h in any file, I get linker errors saying that there are linker conflicts even it there is not the same routine.
            What am i doing wrong?

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

            @franco-amato
            Just checking you are aware of existing QMessageLogger Class.

            1 Reply Last reply
            2

            • Login

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