update logger to show utc

This commit is contained in:
Cyril Anisimov 2025-07-05 12:42:28 +02:00
parent efcc0b7efc
commit 38813d9aa6
2 changed files with 183 additions and 156 deletions

View file

@ -9,8 +9,6 @@
#include <QStandardPaths> #include <QStandardPaths>
#include <QUrl> #include <QUrl>
#include <iostream>
#include "utilities.h" #include "utilities.h"
#include "version.h" #include "version.h"
@ -27,7 +25,7 @@ QTextStream Logger::m_textStream;
QString Logger::m_logFileName = QString("%1.log").arg(APPLICATION_NAME); QString Logger::m_logFileName = QString("%1.log").arg(APPLICATION_NAME);
QString Logger::m_serviceLogFileName = QString("%1.log").arg(SERVICE_NAME); QString Logger::m_serviceLogFileName = QString("%1.log").arg(SERVICE_NAME);
void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{ {
if (msg.simplified().isEmpty()) { if (msg.simplified().isEmpty()) {
return; return;
@ -38,14 +36,21 @@ void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, cons
return; return;
} }
if (msg.startsWith("Unknown property") || msg.startsWith("Could not create pixmap") || msg.startsWith("Populating font") if (msg.startsWith("Unknown property") || msg.startsWith("Could not create pixmap")
|| msg.startsWith("stale focus object")) { || msg.startsWith("Populating font") || msg.startsWith("stale focus object")) {
return; return;
} }
Logger::m_textStream << qFormatLogMessage(type, context, msg) << Qt::endl << Qt::flush; switch (type) {
case QtDebugMsg: Logger::Instance().debug() << msg; break;
std::cout << qFormatLogMessage(type, context, msg).toStdString() << std::endl << std::flush; case QtInfoMsg: Logger::Instance().info() << msg; break;
case QtWarningMsg: Logger::Instance().warning() << msg; break;
case QtCriticalMsg: Logger::Instance().error() << msg; break;
case QtFatalMsg: {
Logger::Instance().error() << msg;
} // Brackets are needed to ensure the destructor of LogStreamer is called before abort()
abort();
}
} }
Logger &Logger::Instance() Logger &Logger::Instance()
@ -57,7 +62,7 @@ Logger &Logger::Instance()
bool Logger::init(bool isServiceLogger) bool Logger::init(bool isServiceLogger)
{ {
QString path = isServiceLogger ? systemLogDir() : userLogsDir(); QString path = isServiceLogger ? systemLogDir() : userLogsDir();
QString logFileName = isServiceLogger ? m_serviceLogFileName : m_logFileName ; QString logFileName = isServiceLogger ? m_serviceLogFileName : m_logFileName;
QDir appDir(path); QDir appDir(path);
if (!appDir.mkpath(path)) { if (!appDir.mkpath(path)) {
return false; return false;
@ -71,19 +76,14 @@ bool Logger::init(bool isServiceLogger)
m_file.setTextModeEnabled(true); m_file.setTextModeEnabled(true);
m_textStream.setDevice(&m_file); m_textStream.setDevice(&m_file);
qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{type} %{message}");
#if !defined(QT_DEBUG) || defined(Q_OS_IOS) qInstallMessageHandler(messageHandler);
qInstallMessageHandler(debugMessageHandler);
#endif
return true; return true;
} }
void Logger::deInit() void Logger::deInit()
{ {
qInstallMessageHandler(nullptr);
qSetMessagePattern("%{message}");
m_textStream.setDevice(nullptr); m_textStream.setDevice(nullptr);
m_file.close(); m_file.close();
} }
@ -234,76 +234,101 @@ void Logger::cleanUp()
clearLogs(true); clearLogs(true);
} }
Logger::Log::Log(Logger *logger, LogLevel logLevel) : m_logger(logger), m_logLevel(logLevel), m_data(new Data()) Logger::LogStreamer::LogStreamer(Logger *logger, LogLevel logLevel)
: m_logger(logger), m_logLevel(logLevel), m_data(new Data())
{ {
} }
Logger::Log::~Log() Logger::LogStreamer::~LogStreamer()
{ {
qDebug() << "Amnezia" << m_logger->className() << m_data->m_buffer.trimmed(); QString logLevelString;
switch (m_logLevel) {
case LogLevel::Trace: logLevelString = "[TRACE]"; break;
case LogLevel::Debug: logLevelString = "[DEBUG]"; break;
case LogLevel::Info: logLevelString = "[INFO]"; break;
case LogLevel::Warning: logLevelString = "[WARNING]"; break;
case LogLevel::Error: logLevelString = "[ERROR]"; break;
}
const QString message = QString("%1 %2 Amnezia %3 : %4")
.arg(QDateTime::currentDateTimeUtc().toString("[yyyy-MM-dd hh:mm:ss.zzzZ]"),
logLevelString, m_logger->className(), m_data->m_buffer.trimmed());
if (m_file.isOpen()) {
QTextStream logToFile(&m_file);
logToFile << message << Qt::endl << Qt::flush;
}
QTextStream logToOutput((m_logLevel == LogLevel::Error) ? stderr : stdout);
logToOutput << message << Qt::endl << Qt::flush;
delete m_data; delete m_data;
} }
Logger::Log Logger::error() Logger::LogStreamer Logger::error()
{ {
return Log(this, LogLevel::Error); return { this, LogLevel::Error };
} }
Logger::Log Logger::warning()
Logger::LogStreamer Logger::warning()
{ {
return Log(this, LogLevel::Warning); return { this, LogLevel::Warning };
} }
Logger::Log Logger::info()
Logger::LogStreamer Logger::info()
{ {
return Log(this, LogLevel::Info); return { this, LogLevel::Info };
} }
Logger::Log Logger::debug()
Logger::LogStreamer Logger::debug()
{ {
return Log(this, LogLevel::Debug); return { this, LogLevel::Debug };
} }
QString Logger::sensitive(const QString &input) QString Logger::sensitive(const QString &input)
{ {
#ifdef Q_DEBUG #ifdef Q_DEBUG
return input; return input;
#else #else
Q_UNUSED(input); Q_UNUSED(input);
return QString(8, 'X'); return { 8, 'X' };
#endif #endif
} }
#define CREATE_LOG_OP_REF(x) \ #define CREATE_LOGSTREAMER_OP_REF(x) \
Logger::Log &Logger::Log::operator<<(x t) \ Logger::LogStreamer &Logger::LogStreamer::operator<<(x t) \
{ \ { \
m_data->m_ts << t << ' '; \ m_data->m_ts << t << ' '; \
return *this; \ return *this; \
} }
CREATE_LOG_OP_REF(uint64_t); CREATE_LOGSTREAMER_OP_REF(uint64_t);
CREATE_LOG_OP_REF(const char *); CREATE_LOGSTREAMER_OP_REF(const char *);
CREATE_LOG_OP_REF(const QString &); CREATE_LOGSTREAMER_OP_REF(const QString &);
CREATE_LOG_OP_REF(const QByteArray &); CREATE_LOGSTREAMER_OP_REF(const QByteArray &);
CREATE_LOG_OP_REF(const void *); CREATE_LOGSTREAMER_OP_REF(const void *);
#undef CREATE_LOG_OP_REF #undef CREATE_LOGSTREAMER_OP_REF
Logger::Log &Logger::Log::operator<<(const QStringList &t) Logger::LogStreamer &Logger::LogStreamer::operator<<(const QStringList &t)
{ {
m_data->m_ts << '[' << t.join(",") << ']' << ' '; m_data->m_ts << '[' << t.join(",") << ']' << ' ';
return *this; return *this;
} }
Logger::Log &Logger::Log::operator<<(const QJsonObject &t) Logger::LogStreamer &Logger::LogStreamer::operator<<(const QJsonObject &t)
{ {
m_data->m_ts << QJsonDocument(t).toJson(QJsonDocument::Indented) << ' '; m_data->m_ts << QJsonDocument(t).toJson(QJsonDocument::Indented) << ' ';
return *this; return *this;
} }
Logger::Log &Logger::Log::operator<<(QTextStreamFunction t) Logger::LogStreamer &Logger::LogStreamer::operator<<(QTextStreamFunction t)
{ {
m_data->m_ts << t; m_data->m_ts << t;
return *this; return *this;
} }
void Logger::Log::addMetaEnum(quint64 value, const QMetaObject *meta, const char *name) void Logger::LogStreamer::addMetaEnum(quint64 value, const QMetaObject *meta, const char *name)
{ {
QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name)); QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));

View file

@ -1,114 +1,116 @@
#ifndef LOGGER_H #ifndef LOGGER_H
#define LOGGER_H #define LOGGER_H
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QString> #include <QString>
#include <QTextStream> #include <QTextStream>
#include "mozilla/shared/loglevel.h" #include "mozilla/shared/loglevel.h"
class Logger : public QObject class Logger : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
static Logger &Instance(); static Logger &Instance();
static bool init(bool isServiceLogger); static bool init(bool isServiceLogger);
static void deInit(); static void deInit();
static bool setServiceLogsEnabled(bool enabled); static bool setServiceLogsEnabled(bool enabled);
static bool openLogsFolder(bool isServiceLogger); static bool openLogsFolder(bool isServiceLogger);
static void clearLogs(bool isServiceLogger); static void clearLogs(bool isServiceLogger);
static void clearServiceLogs(); static void clearServiceLogs();
static void cleanUp(); static void cleanUp();
static QString userLogsFilePath(); static QString userLogsFilePath();
static QString serviceLogsFilePath(); static QString serviceLogsFilePath();
static QString systemLogDir(); static QString systemLogDir();
static QString getLogFile(); static QString getLogFile();
static QString getServiceLogFile(); static QString getServiceLogFile();
// compat with Mozilla logger // compat with Mozilla logger
Logger(const QString &className) Logger(const QString &className)
{ {
m_className = className; m_className = className;
} }
const QString &className() const
{ Logger(Logger const &) = delete;
return m_className; Logger &operator=(Logger const &) = delete;
}
const QString &className() const
class Log {
{ return m_className;
public: }
Log(Logger *logger, LogLevel level);
~Log(); class LogStreamer
{
Log &operator<<(uint64_t t); public:
Log &operator<<(const char *t); LogStreamer(Logger *logger, LogLevel level);
Log &operator<<(const QString &t); ~LogStreamer();
Log &operator<<(const QStringList &t);
Log &operator<<(const QByteArray &t); LogStreamer &operator<<(uint64_t t);
Log &operator<<(const QJsonObject &t); LogStreamer &operator<<(const char *t);
Log &operator<<(QTextStreamFunction t); LogStreamer &operator<<(const QString &t);
Log &operator<<(const void *t); LogStreamer &operator<<(const QStringList &t);
LogStreamer &operator<<(const QByteArray &t);
// Q_ENUM LogStreamer &operator<<(const QJsonObject &t);
template<typename T> typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, Log &>::type operator<<(T t) LogStreamer &operator<<(QTextStreamFunction t);
{ LogStreamer &operator<<(const void *t);
const QMetaObject *meta = qt_getEnumMetaObject(t);
const char *name = qt_getEnumName(t); // Q_ENUM
addMetaEnum(typename QFlags<T>::Int(t), meta, name); template<typename T> typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, LogStreamer &>::type operator<<(T t)
return *this; {
} const QMetaObject *meta = qt_getEnumMetaObject(t);
const char *name = qt_getEnumName(t);
private: addMetaEnum(typename QFlags<T>::Int(t), meta, name);
void addMetaEnum(quint64 value, const QMetaObject *meta, const char *name); return *this;
}
Logger *m_logger;
LogLevel m_logLevel; private:
void addMetaEnum(quint64 value, const QMetaObject *meta, const char *name);
struct Data
{ Logger *m_logger;
Data() : m_ts(&m_buffer, QIODevice::WriteOnly) LogLevel m_logLevel;
{
} struct Data
{
QString m_buffer; Data() : m_ts(&m_buffer, QIODevice::WriteOnly)
QTextStream m_ts; {
}; }
Data *m_data; QString m_buffer;
}; QTextStream m_ts;
};
Log error();
Log warning(); Data *m_data;
Log info(); };
Log debug();
QString sensitive(const QString &input); LogStreamer error();
LogStreamer warning();
private: LogStreamer info();
Logger() {}; LogStreamer debug();
Logger(Logger const &) = delete; QString sensitive(const QString &input);
Logger &operator=(Logger const &) = delete;
private:
static QString userLogsDir(); Logger() = default;
static QFile m_file; static QString userLogsDir();
static QTextStream m_textStream;
static QString m_logFileName; static QFile m_file;
static QString m_serviceLogFileName; static QTextStream m_textStream;
static QString m_logFileName;
friend void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg); static QString m_serviceLogFileName;
// compat with Mozilla logger friend void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
QString m_className;
}; // compat with Mozilla logger
QString m_className;
#endif // LOGGER_H };
#endif // LOGGER_H