Files
UNSWebServerCore_LinuxSO/ServerLogger.h
T
2026-06-30 17:49:51 +08:00

210 lines
9.6 KiB
C++

#pragma once
#pragma warning(disable : 4996)
#include <deque>
#include <mutex>
#include <thread>
#include <string>
#include <atomic>
#include <cstring>
#include <fstream>
#include "LogArg.h"
#include "Export.h"
#include <condition_variable>
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<uns::ServerLogLevel> CurrentLevel; //避免数据竟态UB
// 异步队列与线程控制
std::deque<std::string> 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<std::string>& 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<typename... Args>
void Log(uns::ServerLogLevel level, const std::string& format, Args&&... args);
template<typename... Args>
void LogF(uns::ServerLogLevel level, const std::string& filename, int line_num, const std::string format, Args&&... args);
template<typename... Args>
void LogFMT(uns::ServerLogLevel level, const std::string& format, Args&&... args);
template<typename... Args>
void LogFMT_F(uns::ServerLogLevel level, const std::string& filename, int line_num, const std::string format, Args&&... args);
};
template<typename... Args>
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>(args))... };
LogImpl(level, format, packed_args, sizeof...(Args));
}
}
template<typename... Args>
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>(args))... };
LogFImpl(level, filename, line_num, format, packed_args, sizeof...(Args));
}
}
template<typename ...Args>
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>(args))... };
LogFMTImpl(level, format, packed_args, sizeof...(Args));
}
}
template<typename ...Args>
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>(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()