#pragma once #pragma warning(disable : 4996) #include #include #include #include #include #include #include #include "LogArg.h" #include "Export.h" #include namespace uns { enum ServerLogLevel { llAll = 0x000000, llTrace = 0x000001, llDebug = 0x000010, llInfo = 0x000020, llWarning = 0x000030, llError = 0x000040, llFatal = 0x000050, llOff = 0xFFFFFF }; enum LogRotationPeriod { RP_None = 0, RP_Hourly = 1, RP_Daily = 2 }; std::string UNSWSC_DLL_EXPORT toBinary(long number, int bits); std::string UNSWSC_DLL_EXPORT toBinary(std::uint32_t number, int bits); std::string UNSWSC_DLL_EXPORT toBinary(unsigned long number, int bits); }; class UNSWSC_DLL_EXPORT ServerLogger { private: std::fstream LogStream; std::string LogFileName; std::atomic CurrentLevel; //避免数据竟态UB // 异步队列与线程控制 std::deque LogQueue; std::mutex QueueMutex; std::condition_variable QueueCV; std::thread WorkerThread; std::atomic_bool WorkerRunning; std::atomic_bool ThreadRunningFlag; // 日志分时段(轮转)支持 uns::LogRotationPeriod RotatePeriod; std::time_t CurrentFilePeriodStart; // 新增:大小轮转支持 std::size_t MaxFileSizeBytes; // 最大文件大小(字节) int CurrentOSLIndex; // 当前 period 下的 OSL 索引(从 0 开始) private: std::string GenerateLogHeader(uns::ServerLogLevel LogLevel); std::string GenerateFileInfo(std::string filename, int line_num); void WriteBatchToOutputs(const std::deque& batch) ; void WorkerLoop(); std::string MakeRotatedFileName(const std::string& base, std::time_t t, int osl_index = 0); void RotateIfNeeded(std::time_t now, bool check_size_after_write = false); void LogImpl(uns::ServerLogLevel level, const std::string& format, const uns::LogArg* args, size_t count); void LogFImpl(uns::ServerLogLevel level, const std::string& filename, int line_num, const std::string& format, const uns::LogArg* args, size_t count); void LogFMTImpl(uns::ServerLogLevel level, const std::string& format, const uns::LogArg* args, size_t count); void LogFMT_FImpl(uns::ServerLogLevel level, const std::string& filename, int line_num, const std::string& format, const uns::LogArg* args, size_t count); public: ServerLogger(); ServerLogger(uns::ServerLogLevel log_level, std::string file = "", uns::LogRotationPeriod rotation = uns::RP_None, std::size_t max_bytes = 50 * 1024 * 1024); ServerLogger(const ServerLogger& obj) = delete; ~ServerLogger(); public: bool InitLogger(uns::ServerLogLevel log_level, const std::string& file = "", uns::LogRotationPeriod rotation = uns::RP_None, std::size_t max_bytes = 50 * 1024 * 1024); void CloseLog(); void DisableLog(); void FlushLogBuffer(); void EnableLog(uns::ServerLogLevel level); template void Log(uns::ServerLogLevel level, const std::string& format, Args&&... args); template void LogF(uns::ServerLogLevel level, const std::string& filename, int line_num, const std::string format, Args&&... args); template void LogFMT(uns::ServerLogLevel level, const std::string& format, Args&&... args); template void LogFMT_F(uns::ServerLogLevel level, const std::string& filename, int line_num, const std::string format, Args&&... args); }; template inline void ServerLogger::Log(uns::ServerLogLevel level, const std::string& format, Args&&... args) { uns::ServerLogLevel curr_level = CurrentLevel.load(std::memory_order_relaxed); if ((curr_level == uns::llOff) || (level < curr_level)) return; if constexpr (sizeof...(Args) == 0) LogImpl(level, format, nullptr, 0); else { // 在客户端的栈上瞬间分配数组并完成类型擦除 uns::LogArg packed_args[] = { uns::LogArg(std::forward(args))... }; LogImpl(level, format, packed_args, sizeof...(Args)); } } template inline void ServerLogger::LogF(uns::ServerLogLevel level, const std::string& filename, int line_num, std::string format, Args&&... args) { uns::ServerLogLevel curr_level = CurrentLevel.load(std::memory_order_relaxed); if ((curr_level == uns::llOff) || (level < curr_level)) return; if constexpr (sizeof...(Args) == 0) LogFImpl(level, filename, line_num, format, nullptr, 0); else { uns::LogArg packed_args[] = { uns::LogArg(std::forward(args))... }; LogFImpl(level, filename, line_num, format, packed_args, sizeof...(Args)); } } template inline void ServerLogger::LogFMT(uns::ServerLogLevel level, const std::string& format, Args && ...args) { uns::ServerLogLevel curr_level = CurrentLevel.load(std::memory_order_relaxed); if ((curr_level == uns::llOff) || (level < curr_level)) return; if constexpr (sizeof...(Args) == 0) LogFMTImpl(level, format, nullptr, 0); else { uns::LogArg packed_args[] = { uns::LogArg(std::forward(args))... }; LogFMTImpl(level, format, packed_args, sizeof...(Args)); } } template inline void ServerLogger::LogFMT_F(uns::ServerLogLevel level, const std::string& filename, int line_num, const std::string format, Args && ...args) { uns::ServerLogLevel curr_level = CurrentLevel.load(std::memory_order_relaxed); if ((curr_level == uns::llOff) || (level < curr_level)) return; if constexpr (sizeof...(Args) == 0) LogFMT_FImpl(level, filename, line_num, format, nullptr, 0); else { uns::LogArg packed_args[] = { uns::LogArg(std::forward(args))... }; LogFMT_FImpl(level, filename, line_num, format, packed_args, sizeof...(Args)); } } extern UNSWSC_DLL_EXPORT ServerLogger GlobalServerLogger; #if (defined(_WIN32) || defined(_WIN64)) #define __FILENAME__ std::strrchr("\\" __FILE__, '\\') + 1 #else #define __FILENAME__ std::strrchr("/" __FILE__, '/') + 1 #endif #define SCLOG_CONSOLE_INIT(__log_level__) GlobalServerLogger.InitLogger(__log_level__) #define SCLOG_FILE_INIT(__file_name__, __log_level__, ...) GlobalServerLogger.InitLogger(__log_level__, __file_name__, ##__VA_ARGS__) #define SCLOG_WRITE(__level__, __text__, ...) GlobalServerLogger.LogF(__level__, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOG_TRACE(__text__, ...) GlobalServerLogger.LogF(uns::llTrace, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOG_DEBUG(__text__, ...) GlobalServerLogger.LogF(uns::llDebug, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOG_INFO(__text__, ...) GlobalServerLogger.LogF(uns::llInfo, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOG_WARNING(__text__, ...) GlobalServerLogger.LogF(uns::llWarning, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOG_ERROR(__text__, ...) GlobalServerLogger.LogF(uns::llError, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOG_FATAL(__text__, ...) GlobalServerLogger.LogF(uns::llFatal, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOG_SHORT_WRITE(__level__, __text__, ...) GlobalServerLogger.Log(__level__, __text__, ##__VA_ARGS__) #define SCLOG_SHORT_TRACE(__text__, ...) GlobalServerLogger.Log(uns::llTrace, __text__, ##__VA_ARGS__) #define SCLOG_SHORT_DEBUG(__text__, ...) GlobalServerLogger.Log(uns::llDebug, __text__, ##__VA_ARGS__) #define SCLOG_SHORT_INFO(__text__, ...) GlobalServerLogger.Log(uns::llInfo, __text__, ##__VA_ARGS__) #define SCLOG_SHORT_WARNING(__text__, ...) GlobalServerLogger.Log(uns::llWarning, __text__, ##__VA_ARGS__) #define SCLOG_SHORT_ERROR(__text__, ...) GlobalServerLogger.Log(uns::llError, __text__, ##__VA_ARGS__) #define SCLOG_SHORT_FATAL(__text__, ...) GlobalServerLogger.Log(uns::llFatal, __text__, ##__VA_ARGS__) #define SCLOGF_WRITE(__level__, __text__, ...) GlobalServerLogger.LogFMT_F(__level__, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOGF_TRACE(__text__, ...) GlobalServerLogger.LogFMT_F(uns::llTrace, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOGF_DEBUG(__text__, ...) GlobalServerLogger.LogFMT_F(uns::llDebug, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOGF_INFO(__text__, ...) GlobalServerLogger.LogFMT_F(uns::llInfo, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOGF_WARNING(__text__, ...) GlobalServerLogger.LogFMT_F(uns::llWarning, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOGF_ERROR(__text__, ...) GlobalServerLogger.LogFMT_F(uns::llError, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOGF_FATAL(__text__, ...) GlobalServerLogger.LogFMT_F(uns::llFatal, __FILENAME__, __LINE__, __text__, ##__VA_ARGS__) #define SCLOGF_SHORT_WRITE(__level__, __text__, ...) GlobalServerLogger.LogFMT(__level__, __text__, ##__VA_ARGS__) #define SCLOGF_SHORT_TRACE(__text__, ...) GlobalServerLogger.LogFMT(uns::llTrace, __text__, ##__VA_ARGS__) #define SCLOGF_SHORT_DEBUG(__text__, ...) GlobalServerLogger.LogFMT(uns::llDebug, __text__, ##__VA_ARGS__) #define SCLOGF_SHORT_INFO(__text__, ...) GlobalServerLogger.LogFMT(uns::llInfo, __text__, ##__VA_ARGS__) #define SCLOGF_SHORT_WARNING(__text__, ...) GlobalServerLogger.LogFMT(uns::llWarning, __text__, ##__VA_ARGS__) #define SCLOGF_SHORT_ERROR(__text__, ...) GlobalServerLogger.LogFMT(uns::llError, __text__, ##__VA_ARGS__) #define SCLOGF_SHORT_FATAL(__text__, ...) GlobalServerLogger.LogFMT(uns::llFatal, __text__, ##__VA_ARGS__) #define SCLOG_ENABLE(__level__) GlobalServerLogger.EnableLog(__level__) #define SCLOG_DISABLE() GlobalServerLogger.DisableLog() #define SCLOG_CLOSE() GlobalServerLogger.CloseLog()