|
@@ -0,0 +1,174 @@
|
|
|
|
|
+#ifndef TLOGGER_H
|
|
|
|
|
+#define TLOGGER_H
|
|
|
|
|
+
|
|
|
|
|
+#include <fstream>
|
|
|
|
|
+#include <memory>
|
|
|
|
|
+#include <mutex>
|
|
|
|
|
+#include <sstream>
|
|
|
|
|
+#include <string>
|
|
|
|
|
+#include <vector>
|
|
|
|
|
+
|
|
|
|
|
+// 前向声明Qt类型,避免在头文件中包含Qt
|
|
|
|
|
+class QString;
|
|
|
|
|
+
|
|
|
|
|
+namespace TC {
|
|
|
|
|
+// 日志级别枚举
|
|
|
|
|
+enum class LogLevel { DEBUG = 0, INFO = 1, WARNING = 2, ERROR = 3 };
|
|
|
|
|
+
|
|
|
|
|
+// 日志输出接口
|
|
|
|
|
+class LogOutput
|
|
|
|
|
+{
|
|
|
|
|
+public:
|
|
|
|
|
+ virtual ~LogOutput() = default;
|
|
|
|
|
+ virtual void write(LogLevel level, const std::string& message) = 0;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 控制台输出
|
|
|
|
|
+class ConsoleOutput : public LogOutput
|
|
|
|
|
+{
|
|
|
|
|
+public:
|
|
|
|
|
+ void write(LogLevel level, const std::string& message) override;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 文件输出
|
|
|
|
|
+class FileOutput : public LogOutput
|
|
|
|
|
+{
|
|
|
|
|
+public:
|
|
|
|
|
+ explicit FileOutput(const std::string& filename);
|
|
|
|
|
+ ~FileOutput();
|
|
|
|
|
+ void write(LogLevel level, const std::string& message) override;
|
|
|
|
|
+
|
|
|
|
|
+private:
|
|
|
|
|
+ std::ofstream m_file;
|
|
|
|
|
+ std::mutex m_mutex;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 主日志类
|
|
|
|
|
+class Logger
|
|
|
|
|
+{
|
|
|
|
|
+public:
|
|
|
|
|
+ static Logger& instance();
|
|
|
|
|
+
|
|
|
|
|
+ // 设置日志级别
|
|
|
|
|
+ void setLevel(LogLevel level);
|
|
|
|
|
+ LogLevel getLevel() const;
|
|
|
|
|
+
|
|
|
|
|
+ // 添加输出目标
|
|
|
|
|
+ void addOutput(std::unique_ptr<LogOutput> output);
|
|
|
|
|
+ void clearOutputs();
|
|
|
|
|
+
|
|
|
|
|
+ // 日志记录方法
|
|
|
|
|
+ void debug(const std::string& message);
|
|
|
|
|
+ void info(const std::string& message);
|
|
|
|
|
+ void warning(const std::string& message);
|
|
|
|
|
+ void error(const std::string& message);
|
|
|
|
|
+
|
|
|
|
|
+ // 格式化日志记录
|
|
|
|
|
+ template<typename... Args>
|
|
|
|
|
+ void debugf(const std::string& format, Args&&... args)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (shouldLog(LogLevel::DEBUG)) {
|
|
|
|
|
+ log(LogLevel::DEBUG, formatString(format, std::forward<Args>(args)...));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ template<typename... Args>
|
|
|
|
|
+ void infof(const std::string& format, Args&&... args)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (shouldLog(LogLevel::INFO)) {
|
|
|
|
|
+ log(LogLevel::INFO, formatString(format, std::forward<Args>(args)...));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ template<typename... Args>
|
|
|
|
|
+ void warningf(const std::string& format, Args&&... args)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (shouldLog(LogLevel::WARNING)) {
|
|
|
|
|
+ log(LogLevel::WARNING, formatString(format, std::forward<Args>(args)...));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ template<typename... Args>
|
|
|
|
|
+ void errorf(const std::string& format, Args&&... args)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (shouldLog(LogLevel::ERROR)) {
|
|
|
|
|
+ log(LogLevel::ERROR, formatString(format, std::forward<Args>(args)...));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+#ifdef QT_CORE_LIB
|
|
|
|
|
+ // Qt兼容接口
|
|
|
|
|
+ void qtDebug(const QString& message);
|
|
|
|
|
+ void qtInfo(const QString& message);
|
|
|
|
|
+ void qtWarning(const QString& message);
|
|
|
|
|
+ void qtError(const QString& message);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化方法(全局初始化时调用)
|
|
|
|
|
+ static void initialize(const std::string& logFile = "av_log.txt",
|
|
|
|
|
+ LogLevel level = LogLevel::INFO,
|
|
|
|
|
+ bool enableConsole = true,
|
|
|
|
|
+ bool enableQt = true);
|
|
|
|
|
+
|
|
|
|
|
+private:
|
|
|
|
|
+ Logger() = default;
|
|
|
|
|
+ ~Logger() = default;
|
|
|
|
|
+ Logger(const Logger&) = delete;
|
|
|
|
|
+ Logger& operator=(const Logger&) = delete;
|
|
|
|
|
+
|
|
|
|
|
+ void log(LogLevel level, const std::string& message);
|
|
|
|
|
+ bool shouldLog(LogLevel level) const;
|
|
|
|
|
+ std::string getCurrentTime() const;
|
|
|
|
|
+ std::string levelToString(LogLevel level) const;
|
|
|
|
|
+
|
|
|
|
|
+ template<typename... Args>
|
|
|
|
|
+ std::string formatString(const std::string& format, Args&&... args)
|
|
|
|
|
+ {
|
|
|
|
|
+ std::ostringstream oss;
|
|
|
|
|
+ formatImpl(oss, format, std::forward<Args>(args)...);
|
|
|
|
|
+ return oss.str();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理无参数情况的formatImpl重载
|
|
|
|
|
+ void formatImpl(std::ostringstream& oss, const std::string& format) { oss << format; }
|
|
|
|
|
+
|
|
|
|
|
+ template<typename T>
|
|
|
|
|
+ void formatImpl(std::ostringstream& oss, const std::string& format, T&& value)
|
|
|
|
|
+ {
|
|
|
|
|
+ size_t pos = format.find("{}");
|
|
|
|
|
+ if (pos != std::string::npos) {
|
|
|
|
|
+ oss << format.substr(0, pos) << std::forward<T>(value) << format.substr(pos + 2);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ oss << format;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ template<typename T, typename... Args>
|
|
|
|
|
+ void formatImpl(std::ostringstream& oss, const std::string& format, T&& value, Args&&... args)
|
|
|
|
|
+ {
|
|
|
|
|
+ size_t pos = format.find("{}");
|
|
|
|
|
+ if (pos != std::string::npos) {
|
|
|
|
|
+ oss << format.substr(0, pos) << std::forward<T>(value);
|
|
|
|
|
+ formatImpl(oss, format.substr(pos + 2), std::forward<Args>(args)...);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ oss << format;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ LogLevel m_level = LogLevel::INFO;
|
|
|
|
|
+ std::vector<std::unique_ptr<LogOutput>> m_outputs;
|
|
|
|
|
+ mutable std::mutex m_mutex;
|
|
|
|
|
+};
|
|
|
|
|
+} // namespace TC
|
|
|
|
|
+
|
|
|
|
|
+#define T_LOGGER_DEBUG(msg) TC::Logger::instance().debug(msg)
|
|
|
|
|
+#define T_LOGGER_INFO(msg) TC::Logger::instance().info(msg)
|
|
|
|
|
+#define T_LOGGER_WARNING(msg) TC::Logger::instance().warning(msg)
|
|
|
|
|
+#define T_LOGGER_ERROR(msg) TC::Logger::instance().error(msg)
|
|
|
|
|
+
|
|
|
|
|
+#define T_LOGGER_DEBUGF(fmt, ...) TC::Logger::instance().debugf(fmt, __VA_ARGS__)
|
|
|
|
|
+#define T_LOGGER_INFOF(fmt, ...) TC::Logger::instance().infof(fmt, __VA_ARGS__)
|
|
|
|
|
+#define T_LOGGER_WARNINGF(fmt, ...) TC::Logger::instance().warningf(fmt, __VA_ARGS__)
|
|
|
|
|
+#define T_LOGGER_ERRORF(fmt, ...) TC::Logger::instance().errorf(fmt, __VA_ARGS__)
|
|
|
|
|
+
|
|
|
|
|
+#endif // TLOGGER_H
|