style: Format source code and support grouping client
This commit is contained in:
330
common/logger.h
330
common/logger.h
@@ -21,204 +21,222 @@
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
inline bool stringToBool(const std::string& str) {
|
||||
std::string lower = str;
|
||||
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
|
||||
return (lower == "true" || lower == "1");
|
||||
inline bool stringToBool(const std::string& str)
|
||||
{
|
||||
std::string lower = str;
|
||||
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
|
||||
return (lower == "true" || lower == "1");
|
||||
}
|
||||
|
||||
class Logger {
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
enum LogLevel {
|
||||
InfoLevel, WarningLevel, ErrorLevel
|
||||
};
|
||||
enum LogLevel {
|
||||
InfoLevel, WarningLevel, ErrorLevel
|
||||
};
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>ģʽ
|
||||
static Logger& getInstance() {
|
||||
static Logger instance;
|
||||
if (instance.pid.empty()) {
|
||||
char buf[16] = {};
|
||||
sprintf_s(buf, "%d", GetCurrentProcessId());
|
||||
instance.pid = buf;
|
||||
instance.InitLogFile("C:\\Windows\\Temp", instance.pid);
|
||||
// <20><><EFBFBD><EFBFBD>ģʽ
|
||||
static Logger& getInstance()
|
||||
{
|
||||
static Logger instance;
|
||||
if (instance.pid.empty()) {
|
||||
char buf[16] = {};
|
||||
sprintf_s(buf, "%d", GetCurrentProcessId());
|
||||
instance.pid = buf;
|
||||
instance.InitLogFile("C:\\Windows\\Temp", instance.pid);
|
||||
#ifdef _WINDOWS
|
||||
instance.enable = true; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־Ĭ<D6BE>ϴ<EFBFBD><CFB4><EFBFBD>
|
||||
instance.enable = true; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־Ĭ<D6BE>ϴ<EFBFBD><CFB4><EFBFBD>
|
||||
#else
|
||||
char var[32] = {};
|
||||
const char* name = skCrypt("ENABLE_LOG");
|
||||
DWORD size = GetEnvironmentVariableA(name, var, sizeof(var));
|
||||
instance.enable = stringToBool(var);
|
||||
instance.log("logger.h", __LINE__, "GetEnvironmentVariable: %s=%s\n", name, var);
|
||||
char var[32] = {};
|
||||
const char* name = skCrypt("ENABLE_LOG");
|
||||
DWORD size = GetEnvironmentVariableA(name, var, sizeof(var));
|
||||
instance.enable = stringToBool(var);
|
||||
instance.log("logger.h", __LINE__, "GetEnvironmentVariable: %s=%s\n", name, var);
|
||||
#endif
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// <20><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
||||
Logger(const Logger&) = delete;
|
||||
Logger& operator=(const Logger&) = delete;
|
||||
// <20><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
||||
Logger(const Logger&) = delete;
|
||||
Logger& operator=(const Logger&) = delete;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
|
||||
void setLogFile(const std::string& filename) {
|
||||
std::lock_guard<std::mutex> lock(fileMutex);
|
||||
logFileName = filename;
|
||||
}
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
|
||||
void setLogFile(const std::string& filename)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fileMutex);
|
||||
logFileName = filename;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־
|
||||
void usingLog(bool b = true) {
|
||||
enable = b;
|
||||
}
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־
|
||||
void usingLog(bool b = true)
|
||||
{
|
||||
enable = b;
|
||||
}
|
||||
|
||||
// д<><D0B4>־<EFBFBD><D6BE>֧<EFBFBD><D6A7> printf <20><>ʽ<EFBFBD><CABD>
|
||||
void log(const char* file, int line, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
// д<><D0B4>־<EFBFBD><D6BE>֧<EFBFBD><D6A7> printf <20><>ʽ<EFBFBD><CABD>
|
||||
void log(const char* file, int line, const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
std::string message = formatString(format, args);
|
||||
std::string message = formatString(format, args);
|
||||
|
||||
va_end(args);
|
||||
va_end(args);
|
||||
|
||||
auto timestamp = getCurrentTimestamp();
|
||||
std::string id = pid.empty() ? "" : "[" + pid + "]";
|
||||
auto timestamp = getCurrentTimestamp();
|
||||
std::string id = pid.empty() ? "" : "[" + pid + "]";
|
||||
|
||||
std::string logEntry = id + "[" + timestamp + "] [" + file + ":" + std::to_string(line) + "] " + message;
|
||||
if (enable)
|
||||
{
|
||||
if (running) {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
logQueue.push(logEntry);
|
||||
} else {
|
||||
writeToFile(logEntry);
|
||||
}
|
||||
}
|
||||
std::string logEntry = id + "[" + timestamp + "] [" + file + ":" + std::to_string(line) + "] " + message;
|
||||
if (enable) {
|
||||
if (running) {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
logQueue.push(logEntry);
|
||||
} else {
|
||||
writeToFile(logEntry);
|
||||
}
|
||||
}
|
||||
#ifndef _WINDOWS
|
||||
#ifdef _DEBUG
|
||||
printf(logEntry.c_str());
|
||||
printf(logEntry.c_str());
|
||||
#endif
|
||||
#endif
|
||||
cv.notify_one(); // ֪ͨд<D6AA>߳<EFBFBD>
|
||||
}
|
||||
cv.notify_one(); // ֪ͨд<D6AA>߳<EFBFBD>
|
||||
}
|
||||
|
||||
// ֹͣ<CDA3><D6B9>־ϵͳ
|
||||
void stop() {
|
||||
if (!running) return;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
running = false; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬
|
||||
}
|
||||
cv.notify_one();
|
||||
if (workerThread.joinable()) {
|
||||
workerThread.join();
|
||||
}
|
||||
for (int i = 0; threadRun && i++ < 1000; Sleep(1));
|
||||
}
|
||||
// ֹͣ<CDA3><D6B9>־ϵͳ
|
||||
void stop()
|
||||
{
|
||||
if (!running) return;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
running = false; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬
|
||||
}
|
||||
cv.notify_one();
|
||||
if (workerThread.joinable()) {
|
||||
workerThread.join();
|
||||
}
|
||||
for (int i = 0; threadRun && i++ < 1000; Sleep(1));
|
||||
}
|
||||
|
||||
private:
|
||||
// <20><>־<EFBFBD><D6BE><EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
void InitLogFile(const std::string & dir, const std::string& pid) {
|
||||
time_t currentTime = time(nullptr);
|
||||
tm* localTime = localtime(¤tTime);
|
||||
char timeString[32];
|
||||
strftime(timeString, sizeof(timeString), "%Y-%m", localTime);
|
||||
char fileName[100];
|
||||
// <20><>־<EFBFBD><D6BE><EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
void InitLogFile(const std::string & dir, const std::string& pid)
|
||||
{
|
||||
time_t currentTime = time(nullptr);
|
||||
tm* localTime = localtime(¤tTime);
|
||||
char timeString[32];
|
||||
strftime(timeString, sizeof(timeString), "%Y-%m", localTime);
|
||||
char fileName[100];
|
||||
#ifdef _WINDOWS
|
||||
sprintf_s(fileName, "\\YAMA_%s_%s.txt", timeString, pid.c_str());
|
||||
sprintf_s(fileName, "\\YAMA_%s_%s.txt", timeString, pid.c_str());
|
||||
#else
|
||||
sprintf_s(fileName, "\\log_%s_%s.txt", timeString, pid.c_str());
|
||||
sprintf_s(fileName, "\\log_%s_%s.txt", timeString, pid.c_str());
|
||||
#endif
|
||||
logFileName = dir + fileName;
|
||||
}
|
||||
std::string logFileName; // <20><>־<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
|
||||
bool enable; // <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
bool threadRun; // <20><>־<EFBFBD>߳<EFBFBD>״̬
|
||||
std::queue<std::string> logQueue; // <20><>־<EFBFBD><D6BE><EFBFBD><EFBFBD>
|
||||
std::mutex queueMutex; // <20><><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD>
|
||||
std::condition_variable cv; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
std::atomic<bool> running; // <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
std::thread workerThread; // <20><>̨<EFBFBD>߳<EFBFBD>
|
||||
std::mutex fileMutex; // <20>ļ<EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>
|
||||
std::string pid; // <20><><EFBFBD><EFBFBD>ID
|
||||
logFileName = dir + fileName;
|
||||
}
|
||||
std::string logFileName; // <20><>־<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
|
||||
bool enable; // <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
bool threadRun; // <20><>־<EFBFBD>߳<EFBFBD>״̬
|
||||
std::queue<std::string> logQueue; // <20><>־<EFBFBD><D6BE><EFBFBD><EFBFBD>
|
||||
std::mutex queueMutex; // <20><><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD>
|
||||
std::condition_variable cv; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
std::atomic<bool> running; // <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
std::thread workerThread; // <20><>̨<EFBFBD>߳<EFBFBD>
|
||||
std::mutex fileMutex; // <20>ļ<EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>
|
||||
std::string pid; // <20><><EFBFBD><EFBFBD>ID
|
||||
|
||||
Logger() : enable(false), threadRun(false), running(true), workerThread(&Logger::processLogs, this) {}
|
||||
Logger() : enable(false), threadRun(false), running(true), workerThread(&Logger::processLogs, this) {}
|
||||
|
||||
~Logger() {
|
||||
stop();
|
||||
}
|
||||
~Logger()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
// <20><>̨<EFBFBD>̴߳<DFB3><CCB4><EFBFBD><EFBFBD><EFBFBD>־
|
||||
void processLogs() {
|
||||
threadRun = true;
|
||||
while (running) {
|
||||
std::unique_lock<std::mutex> lock(queueMutex);
|
||||
cv.wait(lock, [this]() {
|
||||
return !running || !logQueue.empty();
|
||||
});
|
||||
// <20><>̨<EFBFBD>̴߳<DFB3><CCB4><EFBFBD><EFBFBD><EFBFBD>־
|
||||
void processLogs()
|
||||
{
|
||||
threadRun = true;
|
||||
while (running) {
|
||||
std::unique_lock<std::mutex> lock(queueMutex);
|
||||
cv.wait(lock, [this]() {
|
||||
return !running || !logQueue.empty();
|
||||
});
|
||||
|
||||
while (running && !logQueue.empty()) {
|
||||
std::string logEntry = logQueue.front();
|
||||
logQueue.pop();
|
||||
lock.unlock();
|
||||
while (running && !logQueue.empty()) {
|
||||
std::string logEntry = logQueue.front();
|
||||
logQueue.pop();
|
||||
lock.unlock();
|
||||
|
||||
// д<><D0B4><EFBFBD><EFBFBD>־<EFBFBD>ļ<EFBFBD>
|
||||
writeToFile(logEntry);
|
||||
// д<><D0B4><EFBFBD><EFBFBD>־<EFBFBD>ļ<EFBFBD>
|
||||
writeToFile(logEntry);
|
||||
|
||||
lock.lock();
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
threadRun = false;
|
||||
}
|
||||
lock.lock();
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
threadRun = false;
|
||||
}
|
||||
|
||||
// д<><D0B4><EFBFBD>ļ<EFBFBD>
|
||||
void writeToFile(const std::string& logEntry) {
|
||||
std::lock_guard<std::mutex> lock(fileMutex);
|
||||
std::ofstream logFile(logFileName, std::ios::app);
|
||||
if (logFile.is_open()) {
|
||||
logFile << logEntry << std::endl;
|
||||
}
|
||||
}
|
||||
// д<><D0B4><EFBFBD>ļ<EFBFBD>
|
||||
void writeToFile(const std::string& logEntry)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fileMutex);
|
||||
std::ofstream logFile(logFileName, std::ios::app);
|
||||
if (logFile.is_open()) {
|
||||
logFile << logEntry << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// <20><>ȡ<EFBFBD><C8A1>ǰʱ<C7B0><CAB1><EFBFBD><EFBFBD>
|
||||
std::string getCurrentTimestamp() {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto in_time_t = std::chrono::system_clock::to_time_t(now);
|
||||
// <20><>ȡ<EFBFBD><C8A1>ǰʱ<C7B0><CAB1><EFBFBD><EFBFBD>
|
||||
std::string getCurrentTimestamp()
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto in_time_t = std::chrono::system_clock::to_time_t(now);
|
||||
|
||||
std::tm tm;
|
||||
std::tm tm;
|
||||
#ifdef _WIN32
|
||||
localtime_s(&tm, &in_time_t); // Windows <20><>ȫ<EFBFBD>汾
|
||||
localtime_s(&tm, &in_time_t); // Windows <20><>ȫ<EFBFBD>汾
|
||||
#else
|
||||
localtime_r(&in_time_t, &tm); // POSIX <20><>ȫ<EFBFBD>汾
|
||||
localtime_r(&in_time_t, &tm); // POSIX <20><>ȫ<EFBFBD>汾
|
||||
#endif
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
|
||||
return ss.str();
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
|
||||
std::string logLevelToString(LogLevel level) {
|
||||
switch (level) {
|
||||
case InfoLevel: return "INFO";
|
||||
case WarningLevel: return "WARNING";
|
||||
case ErrorLevel: return "ERROR";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
// <20><><EFBFBD><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
|
||||
std::string logLevelToString(LogLevel level)
|
||||
{
|
||||
switch (level) {
|
||||
case InfoLevel:
|
||||
return "INFO";
|
||||
case WarningLevel:
|
||||
return "WARNING";
|
||||
case ErrorLevel:
|
||||
return "ERROR";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
// <20><>ʽ<EFBFBD><CABD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
|
||||
std::string formatString(const char* format, va_list args) {
|
||||
char buffer[1024];
|
||||
vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
return std::string(buffer);
|
||||
}
|
||||
// <20><>ʽ<EFBFBD><CABD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
|
||||
std::string formatString(const char* format, va_list args)
|
||||
{
|
||||
char buffer[1024];
|
||||
vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
return std::string(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
inline const char* getFileName(const char* path) {
|
||||
const char* fileName = strrchr(path, '\\');
|
||||
if (!fileName) {
|
||||
fileName = strrchr(path, '/');
|
||||
}
|
||||
return fileName ? fileName + 1 : path;
|
||||
inline const char* getFileName(const char* path)
|
||||
{
|
||||
const char* fileName = strrchr(path, '\\');
|
||||
if (!fileName) {
|
||||
fileName = strrchr(path, '/');
|
||||
}
|
||||
return fileName ? fileName + 1 : path;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS
|
||||
|
||||
Reference in New Issue
Block a user