mirror of https://github.com/linuxdeepin/dtkcore
refactor: log files move to dtklog
Issue: linuxdeepin/dtk#182 dtklog: https://github.com/linuxdeepin/dtklog
This commit is contained in:
parent
51feaf445c
commit
1a6e919cc5
|
@ -5,7 +5,7 @@ Maintainer: Deepin Packages Builder <packages@deepin.com>
|
|||
Build-Depends: debhelper-compat ( =12), pkg-config,
|
||||
qttools5-dev-tools, qttools5-dev, qtbase5-private-dev, doxygen,
|
||||
libgsettings-qt-dev, libgtest-dev, libdtkcommon-dev, cmake,
|
||||
libuchardet-dev, libicu-dev, libsystemd-dev, libspdlog-dev
|
||||
libuchardet-dev, libicu-dev, libdtklog-dev
|
||||
Standards-Version: 3.9.8
|
||||
|
||||
Package: libdtkcore5
|
||||
|
@ -28,7 +28,8 @@ Description: Deepin Tool Kit Core Utilities
|
|||
|
||||
Package: libdtkcore-dev
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libdtkcore5( =${binary:Version}), libdtkcommon-dev(>=5.6.16)
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libdtkcore5( =${binary:Version}),
|
||||
libdtkcommon-dev(>=5.6.16), libdtklog-dev
|
||||
Description: Deepin Tool Kit Core Devel library
|
||||
DtkCore is base devel library of Deepin Qt/C++ applications.
|
||||
.
|
||||
|
|
|
@ -22,7 +22,7 @@ endif
|
|||
dh $@
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=ON -DBUILD_VERSION=$(BUILD_VER) -DDTK_VERSION=$(PACK_VER) -DD_DSG_APP_DATA_FALLBACK=/var/dsg/appdata -DBUILD_WITH_SYSTEMD=ON
|
||||
dh_auto_configure -- -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=ON -DBUILD_VERSION=$(BUILD_VER) -DDTK_VERSION=$(PACK_VER) -DD_DSG_APP_DATA_FALLBACK=/var/dsg/appdata
|
||||
|
||||
#override_dh_auto_test:
|
||||
# echo "skip auto test"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "RollingFileAppender.h"
|
||||
#include "Logger.h"
|
||||
#include "LogManager.h"
|
||||
#include "FileAppender.h"
|
||||
#include "ConsoleAppender.h"
|
||||
#include "AbstractStringAppender.h"
|
||||
#include "AbstractAppender.h"
|
||||
#include "JournalAppender.h"
|
||||
#include "dloghelper.h"
|
||||
#include <RollingFileAppender.h>
|
||||
#include <Logger.h>
|
||||
#include <LogManager.h>
|
||||
#include <FileAppender.h>
|
||||
#include <ConsoleAppender.h>
|
||||
#include <AbstractStringAppender.h>
|
||||
#include <AbstractAppender.h>
|
||||
#include <JournalAppender.h>
|
||||
#include <dloghelper.h>
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#ifndef ABSTRACTAPPENDER_H
|
||||
#define ABSTRACTAPPENDER_H
|
||||
|
||||
#include "dtkcore_global.h"
|
||||
#include <Logger.h>
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
class LIBDTKCORESHARED_EXPORT AbstractAppender
|
||||
{
|
||||
public:
|
||||
AbstractAppender();
|
||||
virtual ~AbstractAppender();
|
||||
|
||||
Logger::LogLevel detailsLevel() const;
|
||||
void setDetailsLevel(Logger::LogLevel level);
|
||||
void setDetailsLevel(const QString &level);
|
||||
|
||||
void write(const QDateTime &time, Logger::LogLevel level, const char *file, int line,
|
||||
const char *func, const QString &category, const QString &msg);
|
||||
|
||||
protected:
|
||||
virtual void append(const QDateTime &time, Logger::LogLevel level, const char *file, int line,
|
||||
const char *func, const QString &category, const QString &msg) = 0;
|
||||
|
||||
private:
|
||||
QMutex m_writeMutex;
|
||||
|
||||
Logger::LogLevel m_detailsLevel;
|
||||
mutable QMutex m_detailsLevelMutex;
|
||||
};
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
#endif // ABSTRACTAPPENDER_H
|
|
@ -1,37 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#ifndef ABSTRACTSTRINGAPPENDER_H
|
||||
#define ABSTRACTSTRINGAPPENDER_H
|
||||
|
||||
#include "AbstractAppender.h"
|
||||
|
||||
#include <QReadWriteLock>
|
||||
#include <QDateTime>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
class LIBDTKCORESHARED_EXPORT AbstractStringAppender : public AbstractAppender
|
||||
{
|
||||
public:
|
||||
AbstractStringAppender();
|
||||
virtual QString format() const;
|
||||
void setFormat(const QString &format);
|
||||
|
||||
static QString stripFunctionName(const char *name);
|
||||
protected:
|
||||
QString formattedString(const QDateTime &time, Logger::LogLevel level, const char *file, int line,
|
||||
const char *func, const QString &category, const QString &msg) const;
|
||||
QString formattedString(const QDateTime &time, Logger::LogLevel level, const char *file, int line,
|
||||
const char *func, const QString &category, const QString &msg, bool withcolor) const;
|
||||
|
||||
private:
|
||||
static QByteArray qCleanupFuncinfo(const char*);
|
||||
|
||||
QString m_format;
|
||||
mutable QReadWriteLock m_formatLock;
|
||||
};
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
#endif // ABSTRACTSTRINGAPPENDER_H
|
|
@ -1,30 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#ifndef CONSOLEAPPENDER_H
|
||||
#define CONSOLEAPPENDER_H
|
||||
|
||||
#include "dtkcore_global.h"
|
||||
#include <AbstractStringAppender.h>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
class LIBDTKCORESHARED_EXPORT ConsoleAppender : public AbstractStringAppender
|
||||
{
|
||||
public:
|
||||
ConsoleAppender();
|
||||
virtual QString format() const;
|
||||
void ignoreEnvironmentPattern(bool ignore);
|
||||
|
||||
protected:
|
||||
virtual void append(const QDateTime &time, Logger::LogLevel level, const char *file, int line,
|
||||
const char *func, const QString &category, const QString &msg);
|
||||
|
||||
private:
|
||||
bool m_ignoreEnvPattern;
|
||||
};
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
|
||||
#endif // CONSOLEAPPENDER_H
|
|
@ -1,43 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#ifndef FILEAPPENDER_H
|
||||
#define FILEAPPENDER_H
|
||||
|
||||
// Logger
|
||||
#include "dtkcore_global.h"
|
||||
#include <AbstractStringAppender.h>
|
||||
|
||||
// Qt
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
class LIBDTKCORESHARED_EXPORT FileAppender : public AbstractStringAppender
|
||||
{
|
||||
public:
|
||||
FileAppender(const QString &fileName = QString());
|
||||
~FileAppender();
|
||||
|
||||
QString fileName() const;
|
||||
void setFileName(const QString &s);
|
||||
|
||||
qint64 size() const;
|
||||
|
||||
protected:
|
||||
virtual void append(const QDateTime &time, Logger::LogLevel level, const char *file, int line,
|
||||
const char *func, const QString &category, const QString &msg);
|
||||
bool openFile();
|
||||
void closeFile();
|
||||
|
||||
private:
|
||||
QFile m_logFile;
|
||||
QTextStream m_logStream;
|
||||
mutable QMutex m_logFileMutex;
|
||||
};
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
|
||||
#endif // FILEAPPENDER_H
|
|
@ -1,38 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#ifndef JOURNALAPPENDER_H
|
||||
#define JOURNALAPPENDER_H
|
||||
|
||||
#include "dtkcore_global.h"
|
||||
#include <AbstractAppender.h>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
class LIBDTKCORESHARED_EXPORT JournalAppender : public AbstractAppender
|
||||
{
|
||||
public:
|
||||
JournalAppender()
|
||||
: AbstractAppender()
|
||||
{
|
||||
}
|
||||
~JournalAppender() override = default;
|
||||
using JournalPriority = int;
|
||||
|
||||
protected:
|
||||
virtual void append(const QDateTime &time,
|
||||
Logger::LogLevel level,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const QString &category,
|
||||
const QString &msg) override;
|
||||
|
||||
private:
|
||||
bool m_ignoreEnvPattern;
|
||||
};
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
|
||||
#endif // JOURNALAPPENDER_H
|
|
@ -1,66 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
#ifndef LOGGER_H
|
||||
#define LOGGER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "dloggerdefs.h"
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
class AbstractAppender;
|
||||
class LoggerPrivate;
|
||||
class LIBDTKCORESHARED_EXPORT Logger
|
||||
{
|
||||
Q_DISABLE_COPY(Logger)
|
||||
public:
|
||||
//!@~english the log levels
|
||||
enum LogLevel {
|
||||
Trace, //!<@~english Trace level. Can be used for mostly unneeded records used for internal code tracing.
|
||||
Debug, //!<@~english Debug level.for the debugging of the software.
|
||||
Info, //!<@~english Info level. Can be used for informational records, which may be interesting for not only developers.
|
||||
Warning, //!<@~english Warning. May be used to log some non-fatal warnings detected by your application.
|
||||
Error, //!<@~english May be used for a big problems making your application work wrong but not crashing.
|
||||
Fatal //!<@~english Fatal. Used for unrecoverable errors, crashes the application (abort) right after the log record is written.
|
||||
};
|
||||
|
||||
Logger();
|
||||
Logger(const QString &defaultCategory);
|
||||
~Logger();
|
||||
|
||||
static Logger *globalInstance();
|
||||
|
||||
static QString levelToString(LogLevel level);
|
||||
static LogLevel levelFromString(const QString &str);
|
||||
|
||||
void registerAppender(AbstractAppender *appender);
|
||||
void registerCategoryAppender(const QString &category, AbstractAppender *appender);
|
||||
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
|
||||
QT_DEPRECATED_X("no longer take effect") void logToGlobalInstance(const QString &category, bool logToGlobal = false);
|
||||
#endif
|
||||
void setDefaultCategory(const QString &category);
|
||||
QString defaultCategory() const;
|
||||
|
||||
void write(const QDateTime &time, LogLevel level, const char *file, int line,
|
||||
const char *func, const char *category, const QString &msg);
|
||||
void write(LogLevel level, const char *file, int line,
|
||||
const char *func, const char *category, const QString &msg);
|
||||
QDebug write(LogLevel level, const char *file, int line,
|
||||
const char *func, const char *category);
|
||||
void writeAssert(const char *file, int line,
|
||||
const char *func, const char *condition);
|
||||
|
||||
private:
|
||||
void write(const QDateTime &time, LogLevel level, const char *file, int line,
|
||||
const char *func, const char *category,
|
||||
const QString &msg, bool fromLocalInstance);
|
||||
Q_DECLARE_PRIVATE(Logger)
|
||||
LoggerPrivate *d_ptr;
|
||||
};
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
#endif // LOGGER_H
|
|
@ -1,71 +0,0 @@
|
|||
// Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd.
|
||||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#ifndef ROLLINGFILEAPPENDER_H
|
||||
#define ROLLINGFILEAPPENDER_H
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
#include <FileAppender.h>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
class LIBDTKCORESHARED_EXPORT RollingFileAppender : public FileAppender
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
@~english
|
||||
The enum DatePattern defines constants for date patterns.
|
||||
\sa setDatePattern(DatePattern)
|
||||
*/
|
||||
enum DatePattern
|
||||
{
|
||||
|
||||
MinutelyRollover = 0,/*!<@~english The minutely date pattern string is "'.'yyyy-MM-dd-hh-mm". */
|
||||
HourlyRollover,/*!<@~english The hourly date pattern string is "yyyy-MM-dd-hh". */
|
||||
HalfDailyRollover,/*!<@~english The half-daily date pattern string is "'.'yyyy-MM-dd-a". */
|
||||
DailyRollover,/*!<@~english The daily date pattern string is "'.'yyyy-MM-dd". */
|
||||
WeeklyRollover,/*!<@~english The weekly date pattern string is "'.'yyyy-ww". */
|
||||
MonthlyRollover/*!<@~english The monthly date pattern string is "'.'yyyy-MM". */
|
||||
};
|
||||
|
||||
RollingFileAppender(const QString &fileName = QString());
|
||||
|
||||
DatePattern datePattern() const;
|
||||
void setDatePattern(DatePattern datePattern);
|
||||
QT_DEPRECATED_X("use setDatePattern(DatePattern)") void setDatePattern(const QString &datePattern);
|
||||
|
||||
QT_DEPRECATED_X("use datePattern(DatePattern)") QString datePatternString() const;
|
||||
|
||||
void setLogFilesLimit(int limit);
|
||||
int logFilesLimit() const;
|
||||
|
||||
void setLogSizeLimit(int limit);
|
||||
qint64 logSizeLimit() const;
|
||||
|
||||
protected:
|
||||
virtual void append(const QDateTime &time, Logger::LogLevel level, const char *file, int line,
|
||||
const char *func, const QString &category, const QString &msg);
|
||||
|
||||
private:
|
||||
void rollOver();
|
||||
void computeRollOverTime();
|
||||
void computeFrequency();
|
||||
void removeOldFiles();
|
||||
void setDatePatternString(const QString &datePatternString);
|
||||
|
||||
QString m_datePatternString;
|
||||
DatePattern m_frequency;
|
||||
|
||||
QDateTime m_rollOverTime;
|
||||
QString m_rollOverSuffix;
|
||||
int m_logFilesLimit;
|
||||
qint64 m_logSizeLimit;
|
||||
mutable QMutex m_rollingMutex;
|
||||
};
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
|
||||
#endif // ROLLINGFILEAPPENDER_H
|
|
@ -1,42 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
#ifndef DLOGGER_DEFINE_H
|
||||
#define DLOGGER_DEFINE_H
|
||||
|
||||
#include "dtkcore_global.h"
|
||||
#include <QLoggingCategory>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
class Logger;
|
||||
class DLogHelper;
|
||||
LIBDTKCORESHARED_EXPORT Logger *loggerInstance();
|
||||
#define dlogger loggerInstance()
|
||||
|
||||
#define DLOG_CTX(category) QMessageLogContext(__FILE__, __LINE__, Q_FUNC_INFO, category)
|
||||
|
||||
// include DLog or dloghelper.h
|
||||
#define dTrace DLogHelper(Logger::Trace, DLOG_CTX("default")).write
|
||||
#define dDebug DLogHelper(Logger::Debug, DLOG_CTX("default")).write
|
||||
#define dInfo DLogHelper(Logger::Info, DLOG_CTX("default")).write
|
||||
#define dWarning DLogHelper(Logger::Warning, DLOG_CTX("default")).write
|
||||
#define dError DLogHelper(Logger::Error, DLOG_CTX("default")).write
|
||||
#define dFatal DLogHelper(Logger::Fatal, DLOG_CTX("default")).write
|
||||
|
||||
#define dCDebug(category) DLogHelper(Logger::Debug, DLOG_CTX(category)).write()
|
||||
#define dCInfo(category) DLogHelper(Logger::Info, DLOG_CTX(category)).write()
|
||||
#define dCWarning(category) DLogHelper(Logger::Warning, DLOG_CTX(category)).write()
|
||||
#define dCError(category) DLogHelper(Logger::Error, DLOG_CTX(category)).write()
|
||||
#define dCFatal(category) DLogHelper(Logger::Fatal, DLOG_CTX(category)).write()
|
||||
|
||||
#define dTraceTime DLogHelper helper(Logger::Trace, DLOG_CTX("default")); helper.timing
|
||||
#define dDebugTime DLogHelper helper(Logger::Debug, DLOG_CTX("default")); helper.timing
|
||||
#define dInfoTime DLogHelper helper(Logger::Info, DLOG_CTX("default")); helper.timing
|
||||
|
||||
#define dAssert(cond) ((!(cond)) ? loggerInstance()->writeAssert(__FILE__, __LINE__, Q_FUNC_INFO, #cond) : qt_noop())
|
||||
#define dAssertX(cond, msg) ((!(cond)) ? loggerInstance()->writeAssert(__FILE__, __LINE__, Q_FUNC_INFO, msg) : qt_noop())
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
|
||||
#endif // DLOGGER_DEFINE_H
|
|
@ -1,37 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#ifndef DLOGHELPER_H
|
||||
#define DLOGHELPER_H
|
||||
|
||||
#include <dtkcore_global.h>
|
||||
#include "Logger.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
class DLogHelperPrivate;
|
||||
class LIBDTKCORESHARED_EXPORT DLogHelper : public QObject
|
||||
{
|
||||
Q_DISABLE_COPY(DLogHelper)
|
||||
public:
|
||||
DLogHelper(Logger::LogLevel level, const QMessageLogContext &context, QObject *parent = nullptr);
|
||||
~DLogHelper();
|
||||
|
||||
void write(const char* msg, ...) Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
|
||||
void write(const QString& msg);
|
||||
QDebug write();
|
||||
|
||||
void timing(const QString& msg, QObject *context = nullptr);
|
||||
|
||||
static Logger::LogLevel levelFromQtMsgType(QtMsgType mt);
|
||||
static QtMsgType qtMsgTypeFromLogLevel(Logger::LogLevel lvl);
|
||||
|
||||
Q_DECLARE_PRIVATE(DLogHelper)
|
||||
};
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
|
||||
#endif // DLOGHELPER_H
|
|
@ -1,22 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#ifndef OUTPUTDEBUGAPPENDER_H
|
||||
#define OUTPUTDEBUGAPPENDER_H
|
||||
|
||||
#include "dtkcore_global.h"
|
||||
#include <AbstractStringAppender.h>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
class LIBDTKCORESHARED_EXPORT OutputDebugAppender : public AbstractStringAppender
|
||||
{
|
||||
protected:
|
||||
virtual void append(const QDateTime &time, Logger::LogLevel level, const char *file, int line,
|
||||
const char *func, const QString &category, const QString &msg);
|
||||
};
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
|
||||
#endif // OUTPUTDEBUGAPPENDER_H
|
|
@ -6,6 +6,7 @@ endif()
|
|||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(Qt@QT_VERSION_MAJOR@Core)
|
||||
find_dependency(Qt@QT_VERSION_MAJOR@Xml)
|
||||
find_dependency(Dtk@DTK_VERSION_MAJOR@Log)
|
||||
|
||||
if (LINUX)
|
||||
find_dependency(Qt@QT_VERSION_MAJOR@DBus)
|
||||
|
|
|
@ -8,3 +8,4 @@ Description: Deepin Tool Kit dtkcore header files
|
|||
Version: @CMAKE_PROJECT_VERSION@
|
||||
Libs: -L${libdir} -ldtk@DTK_VERSION_MAJOR@core
|
||||
Cflags: -I${includedir} -DQT_MESSAGELOGCONTEXT
|
||||
Requires: dtk@DTK_VERSION_MAJOR@log
|
||||
|
|
|
@ -8,7 +8,7 @@ QT.dtkcore.tools = @CMAKE_INSTALL_PREFIX@/@TOOL_INSTALL_DIR@
|
|||
QT.dtkcore.libs = @CMAKE_INSTALL_PREFIX@/@LIBRARY_INSTALL_DIR@
|
||||
QT.dtkcore.includes = @CMAKE_INSTALL_PREFIX@/@INCLUDE_INSTALL_DIR@
|
||||
QT.dtkcore.frameworks =
|
||||
QT.dtkcore.depends = core dbus xml
|
||||
QT.dtkcore.depends = core dbus xml dtklog
|
||||
QT.dtkcore.module_config = v2 ltcg
|
||||
QT.dtkcore.DEFINES += QT_MESSAGELOGCONTEXT
|
||||
QT_MODULES +=
|
||||
|
|
|
@ -7,6 +7,7 @@ set(CMAKE_AUTOUIC ON)
|
|||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
|
||||
find_package(Dtk${DTK_VERSION_MAJOR}Log REQUIRED)
|
||||
if(LINUX)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus)
|
||||
|
@ -14,9 +15,6 @@ if(LINUX)
|
|||
pkg_check_modules(QGSettings REQUIRED IMPORTED_TARGET gsettings-qt) #Dtk6 removed.
|
||||
endif()
|
||||
|
||||
if(BUILD_WITH_SYSTEMD)
|
||||
pkg_check_modules(Systemd REQUIRED IMPORTED_TARGET libsystemd)
|
||||
endif()
|
||||
endif()
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Xml)
|
||||
find_package(DtkBuildHelper REQUIRED)
|
||||
|
@ -39,7 +37,6 @@ include(filesystem/filesystem.cmake)
|
|||
#end filesystem
|
||||
# start log
|
||||
include(log/log.cmake)
|
||||
find_package(spdlog REQUIRED)
|
||||
#end log
|
||||
# start settings
|
||||
include(settings/settings.cmake)
|
||||
|
@ -67,24 +64,18 @@ if(LINUX)
|
|||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::DBus
|
||||
Qt${QT_VERSION_MAJOR}::Xml
|
||||
Dtk${DTK_VERSION_MAJOR}::Log
|
||||
)
|
||||
target_link_libraries(${LIB_NAME} PRIVATE
|
||||
ICU::uc
|
||||
Qt${QT_VERSION_MAJOR}::CorePrivate
|
||||
uchardet
|
||||
spdlog::spdlog
|
||||
)
|
||||
if("${QT_VERSION_MAJOR}" STREQUAL "5")
|
||||
target_link_libraries(${LIB_NAME} PRIVATE
|
||||
PkgConfig::QGSettings
|
||||
)
|
||||
endif()
|
||||
if(BUILD_WITH_SYSTEMD)
|
||||
target_link_libraries(${LIB_NAME} PRIVATE
|
||||
PkgConfig::Systemd
|
||||
)
|
||||
add_definitions(-DBUILD_WITH_SYSTEMD)
|
||||
endif()
|
||||
|
||||
else()
|
||||
add_library(${LIB_NAME} SHARED
|
||||
|
@ -105,7 +96,6 @@ else()
|
|||
ICU::uc
|
||||
Qt${QT_VERSION_MAJOR}::CorePrivate
|
||||
uchardet
|
||||
spdlog::spdlog
|
||||
)
|
||||
if("${QT_VERSION_MAJOR}" STREQUAL "5")
|
||||
target_link_libraries(${LIB_NAME} PRIVATE
|
||||
|
|
|
@ -1,167 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include "AbstractAppender.h"
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\class Dtk::Core::AbstractAppender
|
||||
\inmodule dtkcore
|
||||
|
||||
\brief The AbstractAppender class provides an abstract base class for writing a log entries.
|
||||
|
||||
The AbstractAppender class is the base interface class for all log appenders that could be used with Logger.
|
||||
|
||||
AbstractAppender provides a common implementation for the thread safe, mutex-protected logging of application
|
||||
messages, such as ConsoleAppender, FileAppender or something else. AbstractAppender is abstract and can not be
|
||||
instantiated, but you can use any of its subclasses or create a custom log appender at your choice.
|
||||
|
||||
Appenders are the logical devices that is aimed to be attached to Logger object by calling
|
||||
Logger::registerAppender(). On each log record call from the application Logger object sequentially calls write()
|
||||
function on all the appenders registered in it.
|
||||
|
||||
You can subclass AbstractAppender to implement a logging target of any kind you like. It may be the external logging
|
||||
subsystem (for example, syslog in *nix), XML file, SQL database entries, D-Bus messages or anything else you can
|
||||
imagine.
|
||||
|
||||
For the simple non-structured plain text logging (for example, to a plain text file or to the console output) you may
|
||||
like to subclass the AbstractStringAppender instead of AbstractAppender, which will give you a more convenient way to
|
||||
control the format of the log output.
|
||||
|
||||
\sa AbstractStringAppender
|
||||
\sa Logger::registerAppender()
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Constructs a AbstractAppender object.
|
||||
*/
|
||||
AbstractAppender::AbstractAppender()
|
||||
:m_detailsLevel(Logger::Debug)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Destructs the AbstractAppender object.
|
||||
*/
|
||||
AbstractAppender::~AbstractAppender()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Returns the current details level of appender.
|
||||
|
||||
Log records with a log level lower than a current detailsLevel() will be silently ignored by appender and would not
|
||||
be sent to its append() function.
|
||||
|
||||
It provides additional logging flexibility, allowing you to set the different severity levels for different types
|
||||
of logs.
|
||||
|
||||
\note This function is thread safe.
|
||||
|
||||
\return The log level.
|
||||
|
||||
\sa setDetailsLevel()
|
||||
\sa Logger::LogLevel
|
||||
*/
|
||||
Logger::LogLevel AbstractAppender::detailsLevel() const
|
||||
{
|
||||
QMutexLocker locker(&m_detailsLevelMutex);
|
||||
return m_detailsLevel;
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Sets the current details level of appender.
|
||||
|
||||
Default details \a level is Logger::Debug
|
||||
|
||||
\note This function is thread safe.
|
||||
|
||||
\sa detailsLevel()
|
||||
\sa Logger::LogLevel
|
||||
*/
|
||||
void Dtk::Core::AbstractAppender::setDetailsLevel(Logger::LogLevel level)
|
||||
{
|
||||
QMutexLocker locker(&m_detailsLevelMutex);
|
||||
m_detailsLevel = level;
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Sets the current details \a level of appender.
|
||||
|
||||
This function is provided for convenience, it behaves like an above function.
|
||||
|
||||
\sa detailsLevel()
|
||||
\sa Logger::LogLevel
|
||||
*/
|
||||
void AbstractAppender::setDetailsLevel(const QString &level)
|
||||
{
|
||||
setDetailsLevel(Logger::levelFromString(level));
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Tries to write the log record to this logger.
|
||||
|
||||
This is the function called by Logger object to write a log \a message to the appender.
|
||||
|
||||
The \a time parameter indicates the time stamp.
|
||||
The \a level parameter describes the LogLevel.
|
||||
The \a file parameter is the current file name.
|
||||
The \a line parameter indicates the number of lines to output.
|
||||
The \a func parameter indicates the function name to output.
|
||||
The \a category parameter indicates the log category.
|
||||
The \a msg parameter indicates the output message.
|
||||
|
||||
\note This function is thread safe.
|
||||
|
||||
\sa Logger::write()
|
||||
\sa detailsLevel()
|
||||
*/
|
||||
void AbstractAppender::write(const QDateTime &time, Logger::LogLevel level, const char *file, int line, const char *func, const QString &category, const QString &msg)
|
||||
{
|
||||
if (level < detailsLevel())
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&m_writeMutex);
|
||||
append(time, level, file, line, func, category, msg);
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\fn virtual void AbstractAppender::append(const QDateTime &timeStamp, Logger::LogLevel level, const char *file, int line,
|
||||
const char *function, const QString &category, const QString &message) = 0
|
||||
|
||||
\brief Writes the log record to the logger instance
|
||||
|
||||
This function is called every time when user tries to write a message to this AbstractAppender instance using
|
||||
the write() function. Write function works as proxy and transfers only the messages with log level more or equal
|
||||
to the current logLevel().
|
||||
|
||||
Overload this function when you are implementing a custom appender.
|
||||
|
||||
The \a time parameter indicates the time stamp.
|
||||
The \a level parameter describes the LogLevel.
|
||||
The \a file parameter is the current file name.
|
||||
The \a line parameter indicates the number of lines to output.
|
||||
The \a func parameter indicates the function name to output.
|
||||
The \a category parameter indicates the log category.
|
||||
The \a msg parameter indicates the output message.
|
||||
|
||||
\note This function is not needed to be thread safe because it is never called directly by Logger object. The
|
||||
write() function works as a proxy and protects this function from concurrent access.
|
||||
|
||||
\sa Logger::write()
|
||||
*/
|
||||
|
||||
DCORE_END_NAMESPACE
|
|
@ -1,481 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include "AbstractStringAppender.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QCoreApplication>
|
||||
#include <QThread>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
inline static QString formattedLevelWithColor(Logger::LogLevel level, QString &msg) {
|
||||
switch (level) {
|
||||
case Logger::Trace:
|
||||
return QString("\x1b[94m%1\x1b[0m").arg(msg);
|
||||
case Logger::Debug:
|
||||
return QString("\x1b[36m%1\x1b[0m").arg(msg);
|
||||
case Logger::Info:
|
||||
return QString("\x1b[32m%1\x1b[0m").arg(msg);
|
||||
case Logger::Warning:
|
||||
return QString("\x1b[33m%1\x1b[0m").arg(msg);
|
||||
case Logger::Error:
|
||||
return QString("\x1b[31m%1\x1b[0m").arg(msg);
|
||||
case Logger::Fatal:
|
||||
return QString("\x1b[35m%1\x1b[0m").arg(msg);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\class Dtk::Core::AbstractStringAppender
|
||||
\inmodule dtkcore
|
||||
|
||||
\brief The AbstractStringAppender class provides a convenient base for appenders working with plain text formatted
|
||||
logs.
|
||||
|
||||
AbstractSringAppender is the simple extension of the AbstractAppender class providing the convenient way to create
|
||||
custom log appenders working with a plain text formatted log targets.
|
||||
|
||||
It have the formattedString() protected function that formats the logging arguments according to a format set with
|
||||
setFormat().
|
||||
|
||||
This class can not be directly instantiated because it contains pure virtual function inherited from AbstractAppender
|
||||
class.
|
||||
|
||||
For more detailed description of customizing the log output format see the documentation on the setFormat() function.
|
||||
*/
|
||||
|
||||
const char formattingMarker = '%';
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Constructs a new string appender object.
|
||||
*/
|
||||
AbstractStringAppender::AbstractStringAppender()
|
||||
: m_format(QLatin1String("%{time}{yyyy-MM-ddTHH:mm:ss.zzz} [%{type:-7}] <%{function}> %{message}\n"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Returns the current log format string.
|
||||
|
||||
The default format is set to "%{time}{yyyy-MM-ddTHH:mm:ss.zzz} [%{type:-7}] <%{function}> %{message}\n". You can set a different log record
|
||||
format using the setFormat() function.
|
||||
|
||||
\sa setFormat(const QString&)
|
||||
*/
|
||||
QString AbstractStringAppender::format() const
|
||||
{
|
||||
QReadLocker locker(&m_formatLock);
|
||||
return m_format;
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Sets the logging format for writing strings to the log target with this appender.
|
||||
|
||||
The string format seems to be very common to those developers who have used a standard sprintf function.
|
||||
|
||||
Log output format is a simple QString with the special markers (starting with % sign) which will be replaced with
|
||||
it's internal meaning when writing a log record.
|
||||
|
||||
Controlling marker begins with the percent sign (%) which is followed by the command inside {} brackets
|
||||
(the command describes, what will be put to log record instead of marker).
|
||||
Optional field width argument may be specified right after the command (through the colon symbol before the closing bracket)
|
||||
Some commands requires an additional formatting argument (in the second {} brackets).
|
||||
|
||||
Field width argument works almost identically to the QString::arg() fieldWidth argument (and uses it
|
||||
internally). For example, "%{type:-7}" will be replaced with the left padded debug level of the message
|
||||
("Debug ") or something. For the more detailed description of it you may consider to look to the Qt
|
||||
Reference Documentation.
|
||||
|
||||
Supported marker commands are:
|
||||
\list
|
||||
\li %{time} - timestamp. You may specify your custom timestamp \a format using the second {} brackets after the marker,
|
||||
\li timestamp \a format here will be similar to those used in QDateTime::toString() function. For example,
|
||||
\li "%{time}{dd-MM-yyyy, HH:mm}" may be replaced with "17-12-2010, 20:17" depending on current date and time.
|
||||
\li The default \a format used here is "HH:mm:ss.zzz".
|
||||
\li %{type} - Log level. Possible log levels are shown in the Logger::LogLevel enumerator.
|
||||
\li %{Type} - Uppercased log level.
|
||||
\li %{typeOne} - One letter log level.
|
||||
\li %{TypeOne} - One uppercase letter log level.
|
||||
\li %{File} - Full source file name (with path) of the file that requested log recording. Uses the __FILE__ preprocessor macro.
|
||||
\li %{file} - Short file name (with stripped path).
|
||||
\li %{line} - Line number in the source file. Uses the __LINE__ preprocessor macro.
|
||||
\li %{Function} - Name of function that called on of the LOG_* macros. Uses the Q_FUNC_INFO macro provided with Qt.
|
||||
\li %{function} - Similar to the %{Function}, but the function name is stripped using stripFunctionName
|
||||
\li %{message} - The log message sent by the caller.
|
||||
\li %{category} - The log category.
|
||||
\li %{appname} - Application name (returned by QCoreApplication::applicationName() function).
|
||||
\li %{pid} - Application pid (returned by QCoreApplication::applicationPid() function).
|
||||
\li %{threadid} - ID of current thread.
|
||||
\li %% - Convinient marker that is replaced with the single % mark.
|
||||
\endlist
|
||||
|
||||
\note Format doesn't add '\\n' to the end of the \a format line. Please consider adding it manually.
|
||||
|
||||
\sa format()
|
||||
\sa stripFunctionName()
|
||||
\sa Logger::LogLevel
|
||||
*/
|
||||
void AbstractStringAppender::setFormat(const QString &format)
|
||||
{
|
||||
QWriteLocker locker(&m_formatLock);
|
||||
m_format = format;
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Strips the long function signature (as added by Q_FUNC_INFO macro).
|
||||
|
||||
The string processing drops the returning type, arguments and template parameters of function. It is definitely
|
||||
useful for enchancing the log output readability.
|
||||
|
||||
The \a name parameter is the function name.
|
||||
|
||||
\return stripped function name
|
||||
*/
|
||||
QString AbstractStringAppender::stripFunctionName(const char *name)
|
||||
{
|
||||
return QString::fromLatin1(qCleanupFuncinfo(name));
|
||||
}
|
||||
|
||||
// The function was backported from Qt5 sources (qlogging.h)
|
||||
QByteArray AbstractStringAppender::qCleanupFuncinfo(const char *name)
|
||||
{
|
||||
QByteArray info(name);
|
||||
|
||||
// Strip the function info down to the base function name
|
||||
// note that this throws away the template definitions,
|
||||
// the parameter types (overloads) and any const/volatile qualifiers.
|
||||
if (info.isEmpty())
|
||||
return info;
|
||||
|
||||
int pos;
|
||||
|
||||
// skip trailing [with XXX] for templates (gcc)
|
||||
pos = info.size() - 1;
|
||||
if (info.endsWith(']')) {
|
||||
while (--pos) {
|
||||
if (info.at(pos) == '[')
|
||||
info.truncate(pos);
|
||||
}
|
||||
}
|
||||
|
||||
bool hasLambda = false;
|
||||
QRegularExpression lambdaRegex("::<lambda\\(.*\\)>");
|
||||
QRegularExpressionMatch match = lambdaRegex.match(QString::fromLatin1(info));
|
||||
if (match.hasMatch()) {
|
||||
hasLambda = true;
|
||||
info.remove(match.capturedStart(), match.capturedLength());
|
||||
}
|
||||
|
||||
// operator names with '(', ')', '<', '>' in it
|
||||
static const char operator_call[] = "operator()";
|
||||
static const char operator_lessThan[] = "operator<";
|
||||
static const char operator_greaterThan[] = "operator>";
|
||||
static const char operator_lessThanEqual[] = "operator<=";
|
||||
static const char operator_greaterThanEqual[] = "operator>=";
|
||||
|
||||
// canonize operator names
|
||||
info.replace("operator ", "operator");
|
||||
|
||||
// remove argument list
|
||||
Q_FOREVER {
|
||||
int parencount = 0;
|
||||
pos = info.lastIndexOf(')');
|
||||
if (pos == -1) {
|
||||
// Don't know how to parse this function name
|
||||
return info;
|
||||
}
|
||||
|
||||
// find the beginning of the argument list
|
||||
--pos;
|
||||
++parencount;
|
||||
while (pos && parencount) {
|
||||
if (info.at(pos) == ')')
|
||||
++parencount;
|
||||
else if (info.at(pos) == '(')
|
||||
--parencount;
|
||||
--pos;
|
||||
}
|
||||
if (parencount != 0)
|
||||
return info;
|
||||
|
||||
info.truncate(++pos);
|
||||
|
||||
if (info.at(pos - 1) == ')') {
|
||||
if (info.indexOf(operator_call) == pos - (int)strlen(operator_call))
|
||||
break;
|
||||
|
||||
// this function returns a pointer to a function
|
||||
// and we matched the arguments of the return type's parameter list
|
||||
// try again
|
||||
info.remove(0, info.indexOf('('));
|
||||
info.chop(1);
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasLambda)
|
||||
info.append("::lambda");
|
||||
|
||||
// find the beginning of the function name
|
||||
int parencount = 0;
|
||||
int templatecount = 0;
|
||||
--pos;
|
||||
|
||||
// make sure special characters in operator names are kept
|
||||
if (pos > -1) {
|
||||
switch (info.at(pos)) {
|
||||
case ')':
|
||||
if (info.indexOf(operator_call) == pos - (int)strlen(operator_call) + 1)
|
||||
pos -= 2;
|
||||
break;
|
||||
case '<':
|
||||
if (info.indexOf(operator_lessThan) == pos - (int)strlen(operator_lessThan) + 1)
|
||||
--pos;
|
||||
break;
|
||||
case '>':
|
||||
if (info.indexOf(operator_greaterThan) == pos - (int)strlen(operator_greaterThan) + 1)
|
||||
--pos;
|
||||
break;
|
||||
case '=': {
|
||||
int operatorLength = (int)strlen(operator_lessThanEqual);
|
||||
if (info.indexOf(operator_lessThanEqual) == pos - operatorLength + 1)
|
||||
pos -= 2;
|
||||
else if (info.indexOf(operator_greaterThanEqual) == pos - operatorLength + 1)
|
||||
pos -= 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (pos > -1) {
|
||||
if (parencount < 0 || templatecount < 0)
|
||||
return info;
|
||||
|
||||
char c = info.at(pos);
|
||||
if (c == ')')
|
||||
++parencount;
|
||||
else if (c == '(')
|
||||
--parencount;
|
||||
else if (c == '>')
|
||||
++templatecount;
|
||||
else if (c == '<')
|
||||
--templatecount;
|
||||
else if (c == ' ' && templatecount == 0 && parencount == 0)
|
||||
break;
|
||||
|
||||
--pos;
|
||||
}
|
||||
info = info.mid(pos + 1);
|
||||
|
||||
// remove trailing '*', '&' that are part of the return argument
|
||||
while ((info.at(0) == '*')
|
||||
|| (info.at(0) == '&'))
|
||||
info = info.mid(1);
|
||||
|
||||
// we have the full function name now.
|
||||
// clean up the templates
|
||||
while ((pos = info.lastIndexOf('>')) != -1) {
|
||||
if (!info.contains('<'))
|
||||
break;
|
||||
|
||||
// find the matching close
|
||||
int end = pos;
|
||||
templatecount = 1;
|
||||
--pos;
|
||||
while (pos && templatecount) {
|
||||
const char c = info.at(pos);
|
||||
if (c == '>')
|
||||
++templatecount;
|
||||
else if (c == '<')
|
||||
--templatecount;
|
||||
--pos;
|
||||
}
|
||||
++pos;
|
||||
info.remove(pos, end - pos + 1);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
QString AbstractStringAppender::formattedString(const QDateTime &time, Logger::LogLevel level,
|
||||
const char *file, int line, const char *func,
|
||||
const QString &category, const QString &msg ) const {
|
||||
return formattedString(time, level, file, line, func, category, msg, false);
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Returns the string to record to the logging target, formatted according to the format().
|
||||
|
||||
\a time The time stamp.
|
||||
The \a level parameter describes the LogLevel, and the \a file parameter is the current file name,
|
||||
and the \a line parameter indicates the number of lines to output.
|
||||
The \a func parameter indicates the function name to output.
|
||||
The \a category parameter indicates the log category.
|
||||
The \a msg parameter indicates the output message.
|
||||
The \a withcolor parameter indicates wether to add color to output
|
||||
|
||||
\sa format()
|
||||
\sa setFormat(const QString&)
|
||||
*/
|
||||
QString AbstractStringAppender::formattedString(const QDateTime &time, Logger::LogLevel level,
|
||||
const char *file, int line, const char *func,
|
||||
const QString &category, const QString &msg,
|
||||
bool withcolor) const
|
||||
{
|
||||
QString f = format();
|
||||
|
||||
// dtkcore无法正确解析Qt的日志格式,dtk默认的日志格式并未和Qt统一,解析方式需要兼容两种不同的格式。
|
||||
if (f.contains(QLatin1String("time ")))
|
||||
f.replace(f.indexOf(' ', f.indexOf(QLatin1String("time")) + QLatin1String("time").size()), 1, QLatin1String("}{"));
|
||||
|
||||
const int size = f.size();
|
||||
|
||||
QString result;
|
||||
|
||||
int i = 0;
|
||||
while (i < f.size()) {
|
||||
QChar c = f.at(i);
|
||||
|
||||
// We will silently ignore the broken % marker at the end of string
|
||||
if (c != QLatin1Char(formattingMarker) || (i + 2) >= size) {
|
||||
result.append(c);
|
||||
} else {
|
||||
i += 2;
|
||||
QChar currentChar = f.at(i);
|
||||
QString command;
|
||||
int fieldWidth = 0;
|
||||
|
||||
if (currentChar.isLetter()) {
|
||||
command.append(currentChar);
|
||||
int j = 1;
|
||||
while ((i + j) < size && f.at(i + j).isLetter()) {
|
||||
command.append(f.at(i+j));
|
||||
j++;
|
||||
}
|
||||
|
||||
i+=j;
|
||||
currentChar = f.at(i);
|
||||
|
||||
// Check for the padding instruction
|
||||
if (currentChar == QLatin1Char(':')) {
|
||||
currentChar = f.at(++i);
|
||||
if (currentChar.isDigit() || currentChar.category() == QChar::Punctuation_Dash) {
|
||||
int j = 1;
|
||||
while ((i + j) < size && f.at(i + j).isDigit()) j++;
|
||||
|
||||
fieldWidth = f.mid(i, j).toInt();
|
||||
i += j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log record chunk to insert instead of formatting instruction
|
||||
QString chunk;
|
||||
|
||||
// Time stamp
|
||||
if (command == QLatin1String("time")) {
|
||||
if (f.at(i + 1) == QLatin1Char('{')) {
|
||||
int j = 1;
|
||||
while ((i + 2 + j) < size && f.at(i + 2 + j) != QLatin1Char('}')) j++;
|
||||
|
||||
if ((i + 2 + j) < size) {
|
||||
chunk = time.toString(f.mid(i + 2, j));
|
||||
|
||||
i += j;
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (chunk.isNull())
|
||||
chunk = time.toString(QLatin1String("HH:mm:ss.zzz"));
|
||||
|
||||
} else if (command == QLatin1String("type")) {
|
||||
// Log level
|
||||
chunk = Logger::levelToString(level);
|
||||
if (withcolor) {
|
||||
chunk = formattedLevelWithColor(level, chunk);
|
||||
}
|
||||
} else if (command == QLatin1String("Type")) {
|
||||
// Uppercased log level
|
||||
chunk = Logger::levelToString(level).toUpper();
|
||||
if (withcolor) {
|
||||
chunk = formattedLevelWithColor(level, chunk);
|
||||
}
|
||||
} else if (command == QLatin1String("typeOne")) {
|
||||
// One letter log level
|
||||
chunk = Logger::levelToString(level).left(1).toLower();
|
||||
if (withcolor) {
|
||||
chunk = formattedLevelWithColor(level, chunk);
|
||||
}
|
||||
} else if (command == QLatin1String("TypeOne")) {
|
||||
// One uppercase letter log level
|
||||
chunk = Logger::levelToString(level).left(1).toUpper();
|
||||
if (withcolor) {
|
||||
chunk = formattedLevelWithColor(level, chunk);
|
||||
}
|
||||
} else if (command == QLatin1String("File")) {
|
||||
// Filename
|
||||
chunk = QLatin1String(file);
|
||||
} else if (command == QLatin1String("file")) {
|
||||
// Filename without a path
|
||||
chunk = QString(QLatin1String(file)).section('/', -1);
|
||||
} else if (command == QLatin1String("line")) {
|
||||
// Source line number
|
||||
chunk = QString::number(line);
|
||||
} else if (command == QLatin1String("Function")) {
|
||||
// Function name, as returned by Q_FUNC_INFO
|
||||
chunk = QString::fromLatin1(func);
|
||||
} else if (command == QLatin1String("function")) {
|
||||
// Stripped function name
|
||||
chunk = stripFunctionName(func);
|
||||
} else if (command == QLatin1String("message")) {
|
||||
// Log message
|
||||
chunk = msg;
|
||||
} else if (command == QLatin1String("category")) {
|
||||
// Log message
|
||||
chunk = category;
|
||||
} else if (command == QLatin1String("pid")) {
|
||||
// Application pid
|
||||
chunk = QString::number(QCoreApplication::applicationPid());
|
||||
} else if (command == QLatin1String("appname")) {
|
||||
// Application name
|
||||
chunk = QCoreApplication::applicationName();
|
||||
} else if (command == QLatin1String("threadid")) {
|
||||
// Thread ID (duplicates Qt5 threadid debbuging way)
|
||||
chunk = QLatin1String("0x") + QString::number(qlonglong(QThread::currentThread()->currentThread()), 16);
|
||||
} else if (command == QString(formattingMarker)) {
|
||||
// We simply replace the double formatting marker (%) with one
|
||||
chunk = QLatin1Char(formattingMarker);
|
||||
} else {
|
||||
// Do not process any unknown commands
|
||||
chunk = QString(formattingMarker);
|
||||
chunk.append(command);
|
||||
}
|
||||
|
||||
if (!chunk.isEmpty() && chunk != "0") {
|
||||
result.append(QString(QLatin1String("%1")).arg(chunk, fieldWidth));
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DCORE_END_NAMESPACE
|
|
@ -1,88 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
// Local
|
||||
|
||||
#include "ConsoleAppender.h"
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/spdlog-inl.h>
|
||||
#include <spdlog/details/registry.h>
|
||||
#include <spdlog/details/registry-inl.h>
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
|
||||
// STL
|
||||
#include <iostream>
|
||||
extern "C" {
|
||||
#include <unistd.h>
|
||||
}
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
@~english
|
||||
@class Dtk::Core::ConsoleAppender
|
||||
@ingroup dlog
|
||||
|
||||
@brief ConsoleAppender is the simple appender that writes the log records to the std::cerr output stream.
|
||||
|
||||
ConsoleAppender uses "[%{type:-7}] <%{function}> %{message}\n" as a default output format. It is similar to the
|
||||
AbstractStringAppender but doesn't show a time.
|
||||
|
||||
You can modify ConsoleAppender output format without modifying your code by using \c QT_MESSAGE_PATTERN environment
|
||||
variable. If you need your application to ignore this environment variable you can call
|
||||
ConsoleAppender::ignoreEnvironmentPattern(true)
|
||||
*/
|
||||
|
||||
|
||||
ConsoleAppender::ConsoleAppender()
|
||||
: AbstractStringAppender()
|
||||
, m_ignoreEnvPattern(false)
|
||||
{
|
||||
if (!spdlog::get("console")) {
|
||||
auto clogger = spdlog::stdout_color_mt("console");
|
||||
clogger->set_level(spdlog::level::level_enum(detailsLevel()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString ConsoleAppender::format() const
|
||||
{
|
||||
const QString envPattern = QString::fromLocal8Bit(qgetenv("QT_MESSAGE_PATTERN"));
|
||||
return (m_ignoreEnvPattern || envPattern.isEmpty()) ? AbstractStringAppender::format() : (envPattern + "\n");
|
||||
}
|
||||
|
||||
|
||||
void ConsoleAppender::ignoreEnvironmentPattern(bool ignore)
|
||||
{
|
||||
m_ignoreEnvPattern = ignore;
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Writes the log record to the std::cerr stream.
|
||||
\reimp
|
||||
|
||||
The \a time parameter indicates the time stamp.
|
||||
The \a level parameter describes the LogLevel.
|
||||
The \a file parameter is the current file name.
|
||||
The \a line parameter indicates the number of lines to output.
|
||||
The \a func parameter indicates the function name to output.
|
||||
The \a category parameter indicates the log category.
|
||||
The \a msg parameter indicates the output message.
|
||||
|
||||
\sa AbstractStringAppender::format()
|
||||
*/
|
||||
void ConsoleAppender::append(const QDateTime &time, Logger::LogLevel level, const char *file, int line,
|
||||
const char *func, const QString &category, const QString &msg)
|
||||
{
|
||||
auto clogger = spdlog::get("console");
|
||||
Q_ASSERT(clogger);
|
||||
clogger->set_level(spdlog::level::level_enum(detailsLevel()));
|
||||
|
||||
const auto &formatted = formattedString(time, level, file, line, func, category, msg, isatty(STDOUT_FILENO));
|
||||
clogger->log(spdlog::level::level_enum(level), formatted.toStdString());
|
||||
}
|
||||
|
||||
DCORE_END_NAMESPACE
|
|
@ -1,131 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include "FileAppender.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "rollingfilesink_p.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
std::string loggerName(const QFile &logFile)
|
||||
{
|
||||
return QFileInfo(logFile).fileName().toStdString();
|
||||
}
|
||||
/*!
|
||||
@~english
|
||||
@class Dtk::Core::FileAppender
|
||||
@ingroup dtkcore
|
||||
|
||||
@brief Simple appender that writes the log records to the plain text file.
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
@~english
|
||||
@brief Constructs the new file appender assigned to file with the given \a fileName.
|
||||
*/
|
||||
FileAppender::FileAppender(const QString &fileName)
|
||||
{
|
||||
setFileName(fileName);
|
||||
}
|
||||
|
||||
|
||||
FileAppender::~FileAppender()
|
||||
{
|
||||
closeFile();
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Returns the name set by setFileName() or to the FileAppender constructor.
|
||||
|
||||
\sa setFileName()
|
||||
*/
|
||||
QString FileAppender::fileName() const
|
||||
{
|
||||
QMutexLocker locker(&m_logFileMutex);
|
||||
return m_logFile.fileName();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Sets the \a s name of the file. The name can have no path, a relative path, or an absolute path.
|
||||
|
||||
\sa fileName()
|
||||
*/
|
||||
void FileAppender::setFileName(const QString &s)
|
||||
{
|
||||
QMutexLocker locker(&m_logFileMutex);
|
||||
|
||||
if (s == m_logFile.fileName())
|
||||
return;
|
||||
|
||||
closeFile();
|
||||
|
||||
m_logFile.setFileName(s);
|
||||
|
||||
if (!spdlog::get(loggerName(s)))
|
||||
rolling_logger_mt(loggerName(s),
|
||||
m_logFile.fileName().toStdString(),
|
||||
1024 * 1024 * 20, 0);
|
||||
}
|
||||
|
||||
qint64 FileAppender::size() const
|
||||
{
|
||||
QMutexLocker locker(&m_logFileMutex);
|
||||
|
||||
if (auto *bs = get_sink<rolling_file_sink_mt>(loggerName(m_logFile))){
|
||||
return qint64(bs->filesize());
|
||||
}
|
||||
|
||||
return m_logFile.size();
|
||||
}
|
||||
|
||||
bool FileAppender::openFile()
|
||||
{
|
||||
auto fl = spdlog::get(loggerName(m_logFile));
|
||||
|
||||
return fl.get();
|
||||
}
|
||||
|
||||
/*!
|
||||
@~english
|
||||
\brief Write the log record to the file.
|
||||
\reimp
|
||||
|
||||
The \a time parameter indicates the time stamp.
|
||||
The \a level parameter describes the LogLevel.
|
||||
The \a file parameter is the current file name.
|
||||
The \a line parameter indicates the number of lines to output.
|
||||
The \a func parameter indicates the func name to output.
|
||||
The \a category parameter indicates the log category.
|
||||
The \a msg parameter indicates the output message.
|
||||
|
||||
\sa fileName()
|
||||
\sa AbstractStringAppender::format()
|
||||
*/
|
||||
void FileAppender::append(const QDateTime &time, Logger::LogLevel level, const char *file, int line,
|
||||
const char *func, const QString &category, const QString &msg)
|
||||
{
|
||||
|
||||
if (!openFile())
|
||||
return;
|
||||
|
||||
auto fl = spdlog::get(loggerName(m_logFile));
|
||||
fl->set_level(spdlog::level::level_enum(detailsLevel()));
|
||||
|
||||
const auto &formatted = formattedString(time, level, file, line, func, category, msg);
|
||||
fl->log(spdlog::level::level_enum(level), formatted.toStdString());
|
||||
fl->flush();
|
||||
}
|
||||
|
||||
void FileAppender::closeFile()
|
||||
{
|
||||
spdlog::drop(loggerName(m_logFile));
|
||||
}
|
||||
|
||||
DCORE_END_NAMESPACE
|
|
@ -1,67 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
#include "JournalAppender.h"
|
||||
|
||||
#define SD_JOURNAL_SUPPRESS_LOCATION
|
||||
#include <systemd/sd-journal.h>
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
/**
|
||||
* @~english
|
||||
* @brief it can be used to send log to journal
|
||||
* @param time journal time
|
||||
* @param level log level
|
||||
* @param file
|
||||
* @param line Number of lines of code when writing to the log
|
||||
* @param func function name
|
||||
* @param category log category
|
||||
* @param msg log message
|
||||
*/
|
||||
void JournalAppender::append(const QDateTime &time,
|
||||
Logger::LogLevel level,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const QString &category,
|
||||
const QString &msg)
|
||||
{
|
||||
JournalPriority logLevel = LOG_INFO;
|
||||
switch (level) {
|
||||
case Logger::Debug:
|
||||
logLevel = LOG_DEBUG;
|
||||
break;
|
||||
case Logger::Info:
|
||||
logLevel = LOG_INFO;
|
||||
break;
|
||||
case Logger::Warning:
|
||||
logLevel = LOG_WARNING;
|
||||
break;
|
||||
case Logger::Error:
|
||||
logLevel = LOG_ERR;
|
||||
break;
|
||||
case Logger::Fatal:
|
||||
logLevel = LOG_CRIT;
|
||||
break;
|
||||
default:
|
||||
logLevel = LOG_INFO;
|
||||
break;
|
||||
}
|
||||
sd_journal_send("MESSAGE=%s",
|
||||
msg.toStdString().c_str(),
|
||||
"PRIORITY=%d",
|
||||
logLevel,
|
||||
"DTKPRIORITTY=%d",
|
||||
level,
|
||||
"CODE_FILE=%s",
|
||||
file,
|
||||
"CODE_LINE=%d",
|
||||
line,
|
||||
"CODE_FUNC=%s",
|
||||
func,
|
||||
"CODE_CATEGORY=%s",
|
||||
category.toStdString().c_str(),
|
||||
NULL);
|
||||
}
|
||||
|
||||
DCORE_END_NAMESPACE
|
|
@ -12,8 +12,6 @@
|
|||
#include <JournalAppender.h>
|
||||
#include "dstandardpaths.h"
|
||||
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
#define RULES_KEY ("rules")
|
||||
|
@ -126,9 +124,6 @@ void DLogManagerPrivate::updateLoggingRules()
|
|||
DLogManager::DLogManager()
|
||||
:d_ptr(new DLogManagerPrivate(this))
|
||||
{
|
||||
spdlog::set_automatic_registration(true);
|
||||
spdlog::set_pattern("%v");
|
||||
|
||||
d_ptr->initLoggingRules();
|
||||
}
|
||||
|
||||
|
@ -242,7 +237,6 @@ QString DLogManager::joinPath(const QString &path, const QString &fileName){
|
|||
|
||||
DLogManager::~DLogManager()
|
||||
{
|
||||
spdlog::shutdown();
|
||||
}
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
|
|
1058
src/log/Logger.cpp
1058
src/log/Logger.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1,59 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
// Local
|
||||
#include "win32/OutputDebugAppender.h"
|
||||
|
||||
#include <spdlog/sinks/msvc_sink.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
// STL
|
||||
#include <windows.h>
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class Dtk::Core::OutputDebugAppender
|
||||
\inmodule dtkcore
|
||||
|
||||
\brief Appender that writes the log records to the Microsoft Debug Log.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief Writes the log record to the windows debug log.
|
||||
\reimp
|
||||
|
||||
\brief Writes the log record to the windows debug log.
|
||||
|
||||
The \a time parameter indicates the time stamp.
|
||||
The \a level parameter describes the LogLevel.
|
||||
The \a file parameter is the current file name.
|
||||
The \a line parameter indicates the number of lines to output.
|
||||
The \a func parameter indicates the function name to output.
|
||||
The \a category parameter indicates the log category.
|
||||
The \a msg parameter indicates the output message.
|
||||
|
||||
\sa AbstractStringAppender::format()
|
||||
*/
|
||||
void OutputDebugAppender::append(const QDateTime &time,
|
||||
Logger::LogLevel level,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const QString &category,
|
||||
const QString &msg)
|
||||
{
|
||||
auto msvclogger = spdlog::get("msvc");
|
||||
if (!msvclogger)
|
||||
msvclogger = spdlog::create<spdlog::sinks::msvc_sink_mt>("msvc", true);
|
||||
|
||||
Q_ASSERT(msvclogger);
|
||||
|
||||
msvclogger->set_level(spdlog::level::level_enum(detailsLevel()));
|
||||
const auto &formatted = formattedString(time, level, file, line, func, category, msg);
|
||||
msvclogger->log(spdlog::level::level_enum(level), formatted.toStdString());
|
||||
msvclogger->flush();
|
||||
}
|
||||
|
||||
DCORE_END_NAMESPACE
|
|
@ -1,63 +0,0 @@
|
|||
# Dtk/Core/DLog
|
||||
|
||||
DLog is the log module of deepin tool kit for Qt/C++
|
||||
|
||||
Logger is a simple way to write the history of your application lifecycle to any target logging device (which is called Appender and may write to any target you will implement with it: console, text file, XML or something - you choose) and to map logging message to a class, function, source file and line of code which it is called from.
|
||||
|
||||
Some simple appenders (which may be considered an examples) are provided with the Logger itself: see ConsoleAppender and FileAppender documentation.
|
||||
|
||||
It supports using it in a multithreaded applications, so all of its functions are thread safe.
|
||||
|
||||
Logger internally uses the lazy-initialized singleton object and needs no definite initialization, but you may consider registering a log appender before calling any log recording functions or macros.
|
||||
|
||||
The library design of Logger allows you to simply mass-replace all occurrences of qDebug and similar calls with similar Logger macros (e.g. dDebug())
|
||||
|
||||
Note
|
||||
Logger uses a singleton global instance which lives through all the application life cycle and self-destroys destruction of the QCoreApplication (or QApplication) instance. It needs a QCoreApplication instance to be created before any of the Logger's functions are called.
|
||||
|
||||
## Usage
|
||||
|
||||
Just add pkgconfig in .pro file
|
||||
|
||||
```
|
||||
unix {
|
||||
CONFIG+=link_pkgconfig
|
||||
PKGCONFIG+=dtkcore
|
||||
}
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```cpp
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <DLog>
|
||||
using namespace Dtk::Log;
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
// 1 you can use standrd deepin application log format
|
||||
// 1.1 log to console
|
||||
DLogManager::registerConsoleAppender();
|
||||
// 1.2 log to standrd deepin user cache path: ~/.cache/{organ}/{appname}/
|
||||
// app.setOrganizationName("dtk-test"); // must set
|
||||
// app.setApplicationName("dlog-example"); // must set
|
||||
// dInfo()<< "LogFile:" << DLogManager::getlogFilePath();
|
||||
// DLogManager::registerFileAppender();
|
||||
// 1.3 log to stdout and file
|
||||
// DLogManager::registerFileAppender();
|
||||
// DLogManager::registerConsoleAppender();
|
||||
// 2 Register your own dlogger format;
|
||||
// ConsoleAppender* consoleAppender = new ConsoleAppender;
|
||||
// consoleAppender->setFormat("[%{type:-7}] <%{Function}> %{message}\n");
|
||||
// dlogger->registerAppender(consoleAppender);
|
||||
dInfo("Starting the application");
|
||||
int result = 1;
|
||||
dWarning() << "Something went wrong." << "Result code is" << result;
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
\sa Dtk::Core::DLogManager
|
||||
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "RollingFileAppender.h"
|
||||
|
||||
#include "rollingfilesink_p.h"
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
extern std::string loggerName(const QFile &logFile);
|
||||
/*!
|
||||
@~english
|
||||
@class Dtk::Core::RollingFileAppender
|
||||
@ingroup dlog
|
||||
@brief The RollingFileAppender class extends FileAppender so that the underlying file is rolled over at a user chosen frequency.
|
||||
|
||||
The class is based on Log4Qt.DailyRollingFileAppender class (http://log4qt.sourceforge.net/)
|
||||
and has the same date pattern format.
|
||||
|
||||
For example, if the fileName is set to /foo/bar and the DatePattern set to the daily rollover ('.'yyyy-MM-dd'.log'), on 2014-02-16 at midnight,
|
||||
the logging file /foo/bar.log will be copied to /foo/bar.2014-02-16.log and logging for 2014-02-17 will continue in /foo/bar
|
||||
until it rolls over the next day.
|
||||
|
||||
The logFilesLimit parameter is used to automatically delete the oldest log files in the directory during rollover
|
||||
(so no more than logFilesLimit recent log files exist in the directory at any moment).
|
||||
*/
|
||||
|
||||
RollingFileAppender::RollingFileAppender(const QString &fileName)
|
||||
: FileAppender(fileName)
|
||||
{
|
||||
setLogFilesLimit(1);
|
||||
setLogSizeLimit(1024 * 1024 * 20);
|
||||
}
|
||||
|
||||
void RollingFileAppender::append(const QDateTime &time, Logger::LogLevel level, const char *file, int line,
|
||||
const char *func, const QString &category, const QString &msg)
|
||||
{
|
||||
FileAppender::append(time, level, file, line , func, category, msg);
|
||||
}
|
||||
|
||||
RollingFileAppender::DatePattern RollingFileAppender::datePattern() const
|
||||
{
|
||||
QMutexLocker locker(&m_rollingMutex);
|
||||
return m_frequency;
|
||||
}
|
||||
|
||||
QString RollingFileAppender::datePatternString() const
|
||||
{
|
||||
QMutexLocker locker(&m_rollingMutex);
|
||||
return m_datePatternString;
|
||||
}
|
||||
|
||||
void RollingFileAppender::setDatePattern(DatePattern datePattern)
|
||||
{
|
||||
QMutexLocker locker(&m_rollingMutex);
|
||||
m_frequency = datePattern;
|
||||
|
||||
computeRollOverTime();
|
||||
}
|
||||
|
||||
void RollingFileAppender::setDatePattern(const QString &/*datePattern*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RollingFileAppender::setDatePatternString(const QString &/*datePatternString*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RollingFileAppender::computeFrequency()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RollingFileAppender::removeOldFiles()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RollingFileAppender::computeRollOverTime()
|
||||
{
|
||||
if (auto *fs = get_sink<rolling_file_sink_mt>(loggerName(fileName()))){
|
||||
return fs->set_interval(RollingInterval(m_frequency));
|
||||
}
|
||||
}
|
||||
|
||||
void RollingFileAppender::rollOver()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RollingFileAppender::setLogFilesLimit(int limit)
|
||||
{
|
||||
QMutexLocker locker(&m_rollingMutex);
|
||||
m_logFilesLimit = limit;
|
||||
|
||||
if (auto *fs = get_sink<rolling_file_sink_mt>(loggerName(fileName()))){
|
||||
return fs->set_max_files(std::size_t(limit));
|
||||
}
|
||||
}
|
||||
|
||||
int RollingFileAppender::logFilesLimit() const
|
||||
{
|
||||
QMutexLocker locker(&m_rollingMutex);
|
||||
return m_logFilesLimit;
|
||||
}
|
||||
|
||||
void RollingFileAppender::setLogSizeLimit(int limit)
|
||||
{
|
||||
QMutexLocker locker(&m_rollingMutex);
|
||||
m_logSizeLimit = limit;
|
||||
|
||||
if (auto *fs = get_sink<rolling_file_sink_mt>(loggerName(fileName()))){
|
||||
return fs->set_max_size(std::size_t(limit));
|
||||
}
|
||||
}
|
||||
|
||||
qint64 RollingFileAppender::logSizeLimit() const
|
||||
{
|
||||
QMutexLocker locker(&m_rollingMutex);
|
||||
return m_logSizeLimit;
|
||||
}
|
||||
|
||||
DCORE_END_NAMESPACE
|
|
@ -1,158 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include "dloghelper.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QElapsedTimer>
|
||||
#include <private/qobject_p.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
class DLogHelperPrivate : public QObjectPrivate {
|
||||
public:
|
||||
// Functions.
|
||||
explicit DLogHelperPrivate(int version = QObjectPrivateVersion)
|
||||
: QObjectPrivate(version) {
|
||||
|
||||
}
|
||||
~DLogHelperPrivate() {
|
||||
|
||||
}
|
||||
|
||||
void setContext(const QMessageLogContext &ctx) {
|
||||
file = ctx.file;
|
||||
line = ctx.line;
|
||||
function = ctx.function;
|
||||
category = ctx.category;
|
||||
}
|
||||
void setLevel(Logger::LogLevel lvl) {
|
||||
level = lvl;
|
||||
}
|
||||
|
||||
const char *file = nullptr;
|
||||
const char *function = nullptr;
|
||||
const char *category = nullptr;
|
||||
int line = 0;
|
||||
Logger::LogLevel level = Logger::LogLevel::Debug;
|
||||
};
|
||||
|
||||
DLogHelper::DLogHelper(Logger::LogLevel level, const QMessageLogContext &context, QObject *parent)
|
||||
: QObject(*new DLogHelperPrivate, parent)
|
||||
{
|
||||
d_func()->setContext(context);
|
||||
d_func()->setLevel(level);
|
||||
}
|
||||
|
||||
DLogHelper::~DLogHelper()
|
||||
{
|
||||
}
|
||||
|
||||
void DLogHelper::write(const char* msg, ...)
|
||||
{
|
||||
QString message;
|
||||
va_list va;
|
||||
va_start(va, msg);
|
||||
message = QString::vasprintf(msg, va);
|
||||
va_end(va);
|
||||
|
||||
write(message);
|
||||
}
|
||||
|
||||
void DLogHelper::write(const QString &msg)
|
||||
{
|
||||
Q_D(DLogHelper);
|
||||
Logger::globalInstance()->write(d->level, d->file, d->line,
|
||||
d->function, d->category, msg);
|
||||
}
|
||||
|
||||
QDebug DLogHelper::write()
|
||||
{
|
||||
Q_D(DLogHelper);
|
||||
return Logger::globalInstance()->write(d->level, d->file, d->line,
|
||||
d->function, d->category);
|
||||
}
|
||||
|
||||
void DLogHelper::timing(const QString &msg, QObject *context/* = nullptr*/)
|
||||
{
|
||||
if (!context)
|
||||
context = this;
|
||||
|
||||
QElapsedTimer *elapsedTimer = new QElapsedTimer;
|
||||
elapsedTimer->start();
|
||||
QObject::connect(context, &QObject::destroyed, [elapsedTimer, msg, this](){
|
||||
QString message;
|
||||
message = msg + (QLatin1String(" finished in "));
|
||||
|
||||
qint64 elapsed = elapsedTimer->elapsed();
|
||||
delete elapsedTimer;
|
||||
|
||||
if (elapsed >= 10000)
|
||||
message += QString::number(elapsed / 1000) + QLatin1String("s.");
|
||||
else
|
||||
message += QString::number(elapsed) + QLatin1String("ms.");
|
||||
|
||||
write(message);
|
||||
});
|
||||
}
|
||||
|
||||
Logger::LogLevel DLogHelper::levelFromQtMsgType(QtMsgType mt)
|
||||
{
|
||||
Logger::LogLevel level;
|
||||
switch (mt)
|
||||
{
|
||||
case QtDebugMsg:
|
||||
level = Logger::Debug;
|
||||
break;
|
||||
#if QT_VERSION >= 0x050500
|
||||
case QtInfoMsg:
|
||||
level = Logger::Info;
|
||||
break;
|
||||
#endif
|
||||
case QtWarningMsg:
|
||||
level = Logger::Warning;
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
level = Logger::Error;
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
level = Logger::Fatal;
|
||||
break;
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
QtMsgType DLogHelper::qtMsgTypeFromLogLevel(Logger::LogLevel lvl)
|
||||
{
|
||||
QtMsgType mt;
|
||||
switch (lvl)
|
||||
{
|
||||
case Logger::Debug:
|
||||
mt = QtDebugMsg;
|
||||
break;
|
||||
#if QT_VERSION >= 0x050500
|
||||
case Logger::Info:
|
||||
mt = QtInfoMsg;
|
||||
break;
|
||||
#endif
|
||||
case Logger::Warning:
|
||||
mt = QtWarningMsg;
|
||||
break;
|
||||
case Logger::Error:
|
||||
mt = QtCriticalMsg;
|
||||
break;
|
||||
case Logger::Fatal:
|
||||
mt = QtFatalMsg;
|
||||
break;
|
||||
default:
|
||||
mt = QtWarningMsg;
|
||||
}
|
||||
return mt;
|
||||
}
|
||||
|
||||
DCORE_END_NAMESPACE
|
|
@ -1,34 +1,12 @@
|
|||
file(GLOB LOG_HEADER
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../include/log/*.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../include/log/LogManager.h
|
||||
)
|
||||
set(LOG_SOURCE
|
||||
${CMAKE_CURRENT_LIST_DIR}/RollingFileAppender.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/Logger.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/FileAppender.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/ConsoleAppender.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/AbstractStringAppender.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/AbstractAppender.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/LogManager.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/dloghelper.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/rollingfilesink_p.h
|
||||
)
|
||||
|
||||
if(BUILD_WITH_SYSTEMD AND UNIX AND NOT APPLE)
|
||||
list(APPEND LOG_SOURCE
|
||||
${CMAKE_CURRENT_LIST_DIR}/JournalAppender.cpp
|
||||
)
|
||||
endif()
|
||||
set(log_SRCS
|
||||
${LOG_HEADER}
|
||||
${LOG_SOURCE}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(log_SRCS
|
||||
${LOG_HEADER}
|
||||
${LOG_SOURCE}
|
||||
${CMAKE_CURRENT_LIST_DIR}/OutputDebugAppender.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../include/log/win32/OutputDebugAppender.h
|
||||
)
|
||||
else()
|
||||
set(log_SRCS
|
||||
${LOG_HEADER}
|
||||
${LOG_SOURCE}
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -1,311 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/details/file_helper.h>
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
#include <spdlog/fmt/fmt.h>
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
#include <spdlog/details/os.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#include <dtkcore_global.h>
|
||||
|
||||
#ifndef SPDLOG_VERSION_CHECK
|
||||
#define SPDLOG_VERSION_CHECK(major, minor, patch) (major * 10000 + minor * 100 + patch)
|
||||
#endif
|
||||
DCORE_BEGIN_NAMESPACE
|
||||
|
||||
using namespace spdlog;
|
||||
|
||||
/*
|
||||
* Generator of Hourly log file names in format basename.ext.YYYY-MM-DD-HH-MM-SS
|
||||
*/
|
||||
struct rolling_filename_calculator
|
||||
{
|
||||
// Create filename for the form basename.ext.YYYY-MM-DD-HH-MM-SS
|
||||
static filename_t calc_filename(const filename_t &filename, const tm &now_tm)
|
||||
{
|
||||
#if SPDLOG_VERSION < SPDLOG_VERSION_CHECK(1,10,0)
|
||||
#if SPDLOG_VERSION < SPDLOG_VERSION_CHECK(1,4,0)
|
||||
std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::basic_memory_buffer<char, 250>, fmt::basic_string_view<wchar_t>>::type w;
|
||||
#else
|
||||
std::conditional<std::is_same<filename_t::value_type, char>::value, spdlog::memory_buf_t, spdlog::wmemory_buf_t>::type w;
|
||||
#endif
|
||||
fmt::format_to(w, SPDLOG_FILENAME_T("{}.{:04d}-{:02d}-{:02d}-{:02d}-{:02d}-{:02d}"), filename,
|
||||
now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday,
|
||||
now_tm.tm_hour, now_tm.tm_min, now_tm.tm_sec);
|
||||
return fmt::to_string(w);
|
||||
#else
|
||||
return fmt_lib::format(SPDLOG_FILENAME_T("{}.{:04d}-{:02d}-{:02d}-{:02d}-{:02d}-{:02d}"), filename,
|
||||
now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday,
|
||||
now_tm.tm_hour, now_tm.tm_min, now_tm.tm_sec);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
enum RollingInterval
|
||||
{
|
||||
RI_Minutely = 0,
|
||||
RI_Hourly,
|
||||
RI_HalfDaily,
|
||||
RI_Daily,
|
||||
RI_Weekly,
|
||||
RI_Monthly
|
||||
};
|
||||
|
||||
/*
|
||||
* Rolling file sink based on time and file size.
|
||||
* If max_files > 0, retain only the last max_files and delete previous.
|
||||
*/
|
||||
template<typename Mutex, typename FileNameCalc = rolling_filename_calculator>
|
||||
class rolling_file_sink final : public sinks::base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
// create rolling file sink which rollings on given interval
|
||||
rolling_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files,
|
||||
bool rolling_on_open = false, RollingInterval interval = RI_Daily)
|
||||
: base_filename_(std::move(base_filename))
|
||||
, rolling_on_open_(rolling_on_open)
|
||||
, interval_(interval)
|
||||
, filenames_q_()
|
||||
{
|
||||
set_max_size(max_size);
|
||||
set_max_files(max_files);
|
||||
|
||||
auto filename = base_filename_;
|
||||
file_helper_.open(filename, false);
|
||||
current_size_ = file_helper_.size(); // expensive. called only once
|
||||
rotation_tp_ = next_rotation_tp_();
|
||||
if (rolling_on_open && current_size_ > 0)
|
||||
{
|
||||
rolling_();
|
||||
current_size_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
filename_t filename()
|
||||
{
|
||||
std::lock_guard<Mutex> lock(sinks::base_sink<Mutex>::mutex_);
|
||||
return file_helper_.filename();
|
||||
}
|
||||
size_t filesize()
|
||||
{
|
||||
std::lock_guard<Mutex> lock(sinks::base_sink<Mutex>::mutex_);
|
||||
return file_helper_.size();
|
||||
}
|
||||
void set_max_files(std::size_t max_files)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(sinks::base_sink<Mutex>::mutex_);
|
||||
if (max_files > 200000)
|
||||
{
|
||||
throw spdlog_ex("rolling sink constructor: max_files arg cannot exceed 200000");
|
||||
}
|
||||
max_files_ = max_files;
|
||||
if (max_files > 0)
|
||||
init_filenames_q_();
|
||||
}
|
||||
void set_max_size(std::size_t max_size)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(sinks::base_sink<Mutex>::mutex_);
|
||||
if (max_size == 0)
|
||||
{
|
||||
throw spdlog_ex("rolling sink constructor: max_size arg cannot be zero");
|
||||
}
|
||||
max_size_ = max_size;
|
||||
}
|
||||
void set_interval(RollingInterval interval)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(sinks::base_sink<Mutex>::mutex_);
|
||||
interval_ = interval;
|
||||
rotation_tp_ = next_rotation_tp_();
|
||||
}
|
||||
|
||||
protected:
|
||||
void sink_it_(const details::log_msg &msg) override
|
||||
{
|
||||
#if SPDLOG_VERSION < SPDLOG_VERSION_CHECK(1,4,0)
|
||||
fmt::memory_buffer formatted;
|
||||
#else
|
||||
memory_buf_t formatted;
|
||||
#endif
|
||||
sinks::base_sink<Mutex>::formatter_->format(msg, formatted);
|
||||
auto new_size = current_size_ + formatted.size();
|
||||
|
||||
auto time = msg.time;
|
||||
bool should_rolling = time >= rotation_tp_ || new_size > max_size_;
|
||||
if (should_rolling)
|
||||
{
|
||||
file_helper_.flush();
|
||||
if (file_helper_.size() > 0)
|
||||
{
|
||||
rolling_();
|
||||
new_size = formatted.size();
|
||||
}
|
||||
}
|
||||
|
||||
file_helper_.write(formatted);
|
||||
current_size_ = new_size;
|
||||
|
||||
// Do the cleaning only at the end because it might throw on failure.
|
||||
if (should_rolling && max_files_ > 0)
|
||||
{
|
||||
delete_old_();
|
||||
}
|
||||
}
|
||||
|
||||
void flush_() override
|
||||
{
|
||||
file_helper_.flush();
|
||||
}
|
||||
|
||||
private:
|
||||
void init_filenames_q_()
|
||||
{
|
||||
filenames_q_.clear();
|
||||
QDir dir(QString::fromStdString(base_filename_));
|
||||
dir.cdUp();
|
||||
|
||||
auto namefilter = QFileInfo(base_filename_.c_str()).fileName().append("*");
|
||||
|
||||
auto fileInfos = dir.entryInfoList({ namefilter }, QDir::NoDotAndDotDot | QDir::Files, QDir::Name);
|
||||
for (const auto &fi : fileInfos) {
|
||||
if (fi.filePath().compare(base_filename_.c_str()))
|
||||
filenames_q_.push_back(std::move(fi.filePath().toStdString()));
|
||||
}
|
||||
}
|
||||
|
||||
tm now_tm(log_clock::time_point tp)
|
||||
{
|
||||
time_t tnow = log_clock::to_time_t(tp);
|
||||
return spdlog::details::os::localtime(tnow);
|
||||
}
|
||||
|
||||
log_clock::time_point next_rotation_tp_()
|
||||
{
|
||||
auto now = log_clock::now();
|
||||
tm date = now_tm(now);
|
||||
auto rotation_time = log_clock::from_time_t(std::mktime(&date));
|
||||
|
||||
switch (interval_) {
|
||||
case RI_Minutely:
|
||||
date.tm_min += 1;
|
||||
break;
|
||||
case RI_Hourly:
|
||||
date.tm_hour += 1;
|
||||
break;
|
||||
case RI_HalfDaily:
|
||||
date.tm_hour += 12;
|
||||
break;
|
||||
case RI_Daily:
|
||||
date.tm_mday += 1;
|
||||
break;
|
||||
case RI_Weekly:
|
||||
date.tm_mday += 7;
|
||||
break;
|
||||
case RI_Monthly:
|
||||
date.tm_mon += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
rotation_time = log_clock::from_time_t(std::mktime(&date));
|
||||
return rotation_time;
|
||||
}
|
||||
|
||||
// Delete the file N rotations ago.
|
||||
// Throw spdlog_ex on failure to delete the old file.
|
||||
void delete_old_()
|
||||
{
|
||||
using details::os::filename_to_str;
|
||||
using details::os::remove;
|
||||
|
||||
// base_filename_ not in filenames_q_
|
||||
while (filenames_q_.size() > max_files_ - 1)
|
||||
{
|
||||
auto old_filename = std::move(filenames_q_.front());
|
||||
filenames_q_.pop_front();
|
||||
bool ok = remove(old_filename) == 0;
|
||||
if (!ok)
|
||||
{
|
||||
filenames_q_.push_back(std::move(old_filename));
|
||||
throw(spdlog_ex("Failed removing file " + filename_to_str(old_filename), errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rolling_()
|
||||
{
|
||||
using details::os::filename_to_str;
|
||||
|
||||
file_helper_.close();
|
||||
// xxx.log == > xxx.log.YYYY-MM-DD-HH-MM-SS
|
||||
auto backupName = FileNameCalc::calc_filename(base_filename_, now_tm(log_clock::now()));
|
||||
if (details::os::rename(base_filename_, backupName))
|
||||
{
|
||||
file_helper_.reopen(true); // truncate the log file anyway to prevent it to grow beyond its limit!
|
||||
current_size_ = 0;
|
||||
throw spdlog_ex("rolling_file_sink: failed renaming " + filename_to_str(base_filename_) + " to " + filename_to_str(backupName), errno);
|
||||
}
|
||||
|
||||
filenames_q_.push_back(std::move(backupName));
|
||||
rotation_tp_ = next_rotation_tp_();
|
||||
|
||||
file_helper_.reopen(true);
|
||||
}
|
||||
|
||||
filename_t base_filename_;
|
||||
log_clock::time_point rotation_tp_;
|
||||
details::file_helper file_helper_;
|
||||
bool rolling_on_open_;
|
||||
std::size_t max_size_;
|
||||
std::size_t max_files_;
|
||||
std::size_t current_size_;
|
||||
RollingInterval interval_;
|
||||
std::list<filename_t> filenames_q_;
|
||||
};
|
||||
|
||||
using rolling_file_sink_mt = rolling_file_sink<std::mutex>;
|
||||
using rolling_file_sink_st = rolling_file_sink<details::null_mutex>;
|
||||
|
||||
|
||||
//
|
||||
// factory functions
|
||||
//
|
||||
template<typename Factory = spdlog::synchronous_factory>
|
||||
inline std::shared_ptr<logger> rolling_logger_mt(const std::string &logger_name, const filename_t &filename, std::size_t max_file_size,
|
||||
std::size_t max_files, bool rolling_on_open = false, RollingInterval interval = RI_Daily)
|
||||
{
|
||||
return Factory::template create<rolling_file_sink_mt>(logger_name, filename, max_file_size, max_files, rolling_on_open, interval);
|
||||
}
|
||||
|
||||
template<typename Factory = spdlog::synchronous_factory>
|
||||
inline std::shared_ptr<logger> rolling_logger_st(const std::string &logger_name, const filename_t &filename, std::size_t max_file_size,
|
||||
std::size_t max_files, bool rolling_on_open = false, RollingInterval interval = RI_Daily)
|
||||
{
|
||||
return Factory::template create<rolling_file_sink_st>(logger_name, filename, max_file_size, max_files, rolling_on_open, interval);
|
||||
}
|
||||
|
||||
template<typename Sink>
|
||||
Sink *get_sink(const std::string &logger_name)
|
||||
{
|
||||
Sink *sink = nullptr;
|
||||
|
||||
auto fl = spdlog::get(logger_name);
|
||||
if (!fl)
|
||||
return sink;
|
||||
spdlog::sink_ptr s_ptr = fl->sinks()[0];
|
||||
sink = dynamic_cast<Sink *>(s_ptr.get());
|
||||
|
||||
return sink;
|
||||
}
|
||||
|
||||
DCORE_END_NAMESPACE
|
|
@ -1,157 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <QFile>
|
||||
#include <QLocale>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include "log/Logger.h"
|
||||
#include "log/dloghelper.h"
|
||||
#include "log/FileAppender.h"
|
||||
#include "log/ConsoleAppender.h"
|
||||
#include "log/RollingFileAppender.h"
|
||||
|
||||
DCORE_USE_NAMESPACE
|
||||
|
||||
class ut_Logger: public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
QString tmpFileName() {
|
||||
Q_ASSERT(m_tmpFile);
|
||||
return m_tmpFile->fileName();
|
||||
}
|
||||
Logger *m_logger = nullptr;
|
||||
QTemporaryFile *m_tmpFile = nullptr;
|
||||
};
|
||||
|
||||
void ut_Logger::SetUp()
|
||||
{
|
||||
m_logger = new Logger;
|
||||
m_tmpFile = new QTemporaryFile;
|
||||
m_tmpFile->open();
|
||||
}
|
||||
|
||||
void ut_Logger::TearDown()
|
||||
{
|
||||
if (m_logger) {
|
||||
delete m_logger;
|
||||
m_logger = nullptr;
|
||||
}
|
||||
m_tmpFile->close();
|
||||
delete m_tmpFile;
|
||||
}
|
||||
|
||||
TEST_F(ut_Logger, testLevelToString)
|
||||
{
|
||||
QString trace = Logger::levelToString(Logger::Trace);
|
||||
ASSERT_EQ(trace, "Trace");
|
||||
QString debug = Logger::levelToString(Logger::Debug);
|
||||
ASSERT_EQ(debug, "Debug");
|
||||
QString info = Logger::levelToString(Logger::Info);
|
||||
ASSERT_EQ(info, "Info");
|
||||
QString warning = Logger::levelToString(Logger::Warning);
|
||||
ASSERT_EQ(warning, "Warning");
|
||||
QString error = Logger::levelToString(Logger::Error);
|
||||
ASSERT_EQ(error, "Error");
|
||||
QString fatal = Logger::levelToString(Logger::Fatal);
|
||||
ASSERT_EQ(fatal, "Fatal");
|
||||
}
|
||||
|
||||
TEST_F(ut_Logger, testLevelFromString)
|
||||
{
|
||||
Logger::LogLevel trace = Logger::levelFromString("Trace");
|
||||
ASSERT_EQ(trace, Logger::Trace);
|
||||
Logger::LogLevel debug = Logger::levelFromString("Debug");
|
||||
ASSERT_EQ(debug, Logger::Debug);
|
||||
Logger::LogLevel info = Logger::levelFromString("Info");
|
||||
ASSERT_EQ(info, Logger::Info);
|
||||
Logger::LogLevel warning = Logger::levelFromString("Warning");
|
||||
ASSERT_EQ(warning, Logger::Warning);
|
||||
Logger::LogLevel error = Logger::levelFromString("Error");
|
||||
ASSERT_EQ(error, Logger::Error);
|
||||
Logger::LogLevel fatal = Logger::levelFromString("Fatal");
|
||||
ASSERT_EQ(fatal, Logger::Fatal);
|
||||
}
|
||||
|
||||
TEST_F(ut_Logger, testGlobalInstance)
|
||||
{
|
||||
ASSERT_TRUE(Logger::globalInstance());
|
||||
}
|
||||
|
||||
TEST_F(ut_Logger, testRegisterAppender)
|
||||
{
|
||||
Logger* gLogger = Logger::globalInstance();
|
||||
FileAppender *fileAppener = new FileAppender(tmpFileName());
|
||||
if (fileAppener->detailsLevel() > Logger::Trace)
|
||||
fileAppener->setDetailsLevel(Logger::Trace);
|
||||
gLogger->registerAppender(fileAppener);
|
||||
ASSERT_TRUE(fileAppener->size() == 0);
|
||||
dInfo("testRegisterAppender");
|
||||
ASSERT_TRUE(fileAppener->size() != 0);
|
||||
|
||||
ConsoleAppender *consoleAppener = new ConsoleAppender();
|
||||
if (consoleAppener->detailsLevel() > Logger::Trace)
|
||||
consoleAppener->setDetailsLevel(Logger::Trace);
|
||||
gLogger->registerAppender(consoleAppener);
|
||||
consoleAppener->ignoreEnvironmentPattern(false);
|
||||
QString format = consoleAppener->format();
|
||||
consoleAppener->setFormat("[%{file}: %{line} %{type:-7}] <%{function}> %{message}\n");
|
||||
dTrace("testRegisterAppender");
|
||||
|
||||
RollingFileAppender *rollingFileAppender = new RollingFileAppender("/tmp/rollLog");
|
||||
if (rollingFileAppender->detailsLevel() > Logger::Trace)
|
||||
rollingFileAppender->setDetailsLevel(Logger::Trace);
|
||||
gLogger->registerAppender(rollingFileAppender);
|
||||
rollingFileAppender->setLogFilesLimit(2);
|
||||
ASSERT_TRUE(rollingFileAppender->logFilesLimit() == 2);
|
||||
rollingFileAppender->setDatePattern(RollingFileAppender::MinutelyRollover);
|
||||
ASSERT_TRUE(rollingFileAppender->datePattern() == RollingFileAppender::MinutelyRollover);
|
||||
dTrace("testRegisterAppender");
|
||||
rollingFileAppender->setDatePattern(RollingFileAppender::HourlyRollover);
|
||||
ASSERT_TRUE(rollingFileAppender->datePattern() == RollingFileAppender::HourlyRollover);
|
||||
dTrace("testRegisterAppender");
|
||||
rollingFileAppender->setDatePattern(RollingFileAppender::HalfDailyRollover);
|
||||
ASSERT_TRUE(rollingFileAppender->datePattern() == RollingFileAppender::HalfDailyRollover);
|
||||
dTrace("testRegisterAppender");
|
||||
}
|
||||
|
||||
TEST_F(ut_Logger, testRegisterCategoryAppender)
|
||||
{
|
||||
qInfo() << "tmpFileName()" << tmpFileName();
|
||||
Logger* gLogger = Logger::globalInstance();
|
||||
FileAppender *fileAppener = new FileAppender(tmpFileName());
|
||||
gLogger->registerCategoryAppender("testRegisterCategoryAppender", fileAppener);
|
||||
if (fileAppener->detailsLevel() > Logger::Trace)
|
||||
fileAppener->setDetailsLevel(Logger::Trace);
|
||||
ASSERT_TRUE(fileAppener->size() == 0);
|
||||
dCDebug("testRegisterCategoryAppender") << "testRegisterCategoryAppender";
|
||||
ASSERT_TRUE(fileAppener->size() != 0);
|
||||
}
|
||||
|
||||
TEST_F(ut_Logger, testLogToGlobalInstance)
|
||||
{
|
||||
Logger* gLogger = Logger::globalInstance();
|
||||
FileAppender *fileAppener = new FileAppender(tmpFileName());
|
||||
if (fileAppener->detailsLevel() > Logger::Trace)
|
||||
fileAppener->setDetailsLevel(Logger::Trace);
|
||||
gLogger->registerAppender(fileAppener);
|
||||
|
||||
ASSERT_TRUE(fileAppener->size() == 0);
|
||||
dTrace("testRegisterAppender");
|
||||
ASSERT_TRUE(fileAppener->size() != 0);
|
||||
}
|
||||
|
||||
TEST_F(ut_Logger, testSetDefaultCategory)
|
||||
{
|
||||
m_logger->setDefaultCategory("testSetDefaultCategory");
|
||||
ASSERT_EQ(m_logger->defaultCategory(), "testSetDefaultCategory");
|
||||
}
|
||||
|
||||
TEST_F(ut_Logger, testDefaultCategory)
|
||||
{
|
||||
ASSERT_EQ(m_logger->defaultCategory(), "");
|
||||
}
|
Loading…
Reference in New Issue