210 lines
9.6 KiB
C++
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() |