Skip to content
This repository was archived by the owner on Jan 28, 2022. It is now read-only.

Logging

Christian Riedl edited this page Dec 5, 2019 · 8 revisions

Logging

The Logger class is intende for use in QML and C++ code inside the remote itself and also in the integration DLL's. Qt logging system use a QtMsgType as "severity". Unfortunately it is not sorted as usually. The highest value has QtInfoMsg. So I had to introduce some workarround to define a logging level to filter the loggings in this sequence :

{ QtDebugMsg, QtInfoMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg };

Features

  • Log categories based on QLoggingCategory. For every category
    • Log message counter per severity (QtMsgType).
    • Log level
  • Write functions for use from QML
  • Log messages can optionally show the source file and the line number (qDebug feature).
  • Function to set the log level per category (setCategoryLogLevel)
  • Function to register a log category and its QLoggingCategory instance (defineLogCategory). When log level of a category is changed the QLoggingCategory instance is updated accordingly.
  • I assume that an integration plugin has its own logging category. Integrations load function registers the plugins. So Logger class can contol also the integrations log. Integrations must implement the new setLogEnabled function.
  • Log targets can be individually enabled, disabled
    • debug : The Qt Creators console
    • file : A log file (created every new hour), with purge function
    • queue : A queue with defineable maximum size. It is used to send messages to the web_configurator. It is better not to send every message individually. The web configurator has to request a package of messages (cyclically) with a specified maximum number of messages, a log level and a list of categories as filter.

Logger class

Q_PROPERTY  (int        logLevel            READ logLevel       WRITE setLogLevel)      // default log level
Q_PROPERTY  (bool       fileEnabled         READ fileEnabled    WRITE setFileEnabled)
Q_PROPERTY  (bool       queueEnabled        READ queueEnabled   WRITE setQueueEnabled)
Q_PROPERTY  (bool       debugEnabled        READ debugEnabled   WRITE setDebugEnabled)
Q_PROPERTY  (bool       showSourcePos       READ showSourcePos  WRITE setShowSourcePos)

// write log functions intended for QML
Q_INVOKABLE void        write               (const QString& msg);
Q_INVOKABLE void        writeDebug          (const QString& msg);
Q_INVOKABLE void        writeInfo           (const QString& msg);
Q_INVOKABLE void        writeWarning        (const QString& msg);

Q_INVOKABLE int         toMsgType           (const QString& msgType);

// set category log level, if category is not existing it is created
Q_INVOKABLE void        setCategoryLogLevel (const QString& category, int level);
Q_INVOKABLE int         getCategoryLogLevel (const QString& category);

// important when a plugin is unloaded
Q_INVOKABLE void        removeCategory      (const QString& category);

// for use in QML or from YIO API
Q_INVOKABLE QJsonArray  getQueuedMessages   (int maxCount, int logLevel, const QStringList& categories);
Q_INVOKABLE QJsonObject getInformation      ();

Q_INVOKABLE int         getFileCount        ();
Q_INVOKABLE void        purgeFiles          (int purgeHours);

// path :       directory for log file, if empty no log file
// logLevel :   default log level, will be overwritten by config setting.log
// debug :      output to QtCreator DEBUG
// showSource : show qDebug ... source and line
// queueSize :  maximum Queue size
// purgeHours : purge at start
explicit Logger (const QString& path, QtMsgType logLevel = QtDebugMsg, bool debug = true, bool showSource = false, int queueSize = 100, int purgeHours = 12, QObject *parent = nullptr);

// for use from C++ to register a Logging category
// used by integrations to register plugin logging
void   defineLogCategory   (const QString& category, int level, QLoggingCategory* loggingCategory = nullptr, IntegrationInterface* plugin = nullptr);

Remote-software sample

YioAPI::YioAPI(QQmlApplicationEngine *engine) :
    m_log("yioapi"),
    m_engine(engine)
{
    s_instance = this;
    Logger::getInstance()->defineLogCategory(m_log.categoryName(), QtMsgType::QtDebugMsg, &m_log);
}

Integration sample

class OpenWeatherFactory : public IntegrationInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "YIO.IntegrationInterface" FILE "openweather.json")
Q_INTERFACES(IntegrationInterface)
public:
    explicit OpenWeatherFactory(QObject* parent = nullptr);
    virtual ~OpenWeatherFactory() override {
    }
    void        create         (const QVariantMap& config, QObject *entities, QObject *notifications, QObject* api, QObject *configObj) override;
    void        setLogEnabled  (QtMsgType msgType, bool enable) override
    {   _log.setEnabled(msgType, enable);   }
private:
    QLoggingCategory    _log;
};

The QLoggingCategory _log must be passed on to the integration instances and threads (I propose in the constructor, as reference).

Important : the log category must be the same as the plugin name !!!

Initial loglevel of an integration can be configured in config.json :

"integrations": 
{
    "smarthomemqtt":
    {
        "log": "debug",
        "data":

YIOAPI integration

All logger functions can be controlled by the YIO API (type is log).

Actions :

  • start, target : (file|debug|queue)
  • stop, target : (file|debug|queue)
  • showsource
  • hidesource
  • setloglevel category, level : (debug, info, warning, ctritoical, fatal)
  • getmessages count, level, categorylist (all when missing)

sample result (time is unix time, type is severity) :

{  "type":"log",
   "messages":
   [
      {"cat":"openweather",
       "msg":"setup",
       "src":"..\\integration.openweather\\OpenWeather.cpp:206",
       "time":"1575551902",
       "type":0
      },
      {"cat":"openweather",
       "msg":"connect",
       "src":"..\\integration.openweather\\OpenWeather.cpp:226",
       "time":"1575551905",
      "type":0
      }
   ]
}
  • getinfo

sample result :

{
  "type":"log",
  "info":
  {
    "categories": 
   [
     {   
            "category":"qt.network.ssl",
            "countCritical":0,"countDebug":0,"countFatal":0,"countInfo":0,"countWarning":3,
            "level":4
    },
    {
            "category":"openweather",
            "countCritical":0,"countDebug":3,"countFatal":0,"countInfo":0,"countWarning":0,
            "level":0
    }
  ],
  "debugEnabled":true,"fileEnabled":true,"fileCount":3, "queueEnabled":true,"showSourcePos":true
  },
}
Clone this wiki locally