只要include头文件就能使用,单例模式
#ifndef MONITORING_LOGGER_H
#define MONITORING_LOGGER_H
#include <iostream>
#include <string>
#include <sstream>
#include <mutex>
#include <cstdarg>
#include <iomanip>
// Set log level
#define MODE_DEBUG 1
#define MODE_INFO 1
#define MODE_WARN 1
#define MODE_ERROR 1
// Control log prefix
#define LOG_SHOW_LEVEL 1
#define LOG_SHOW_PATH 0
#define LOG_SHOW_FILENAME 1
#define LOG_SHOW_LINE 1
class Logger {
public:
enum LogLevel {
DEBUG,
INFO,
WARN,
ERROR
};
static Logger& getInstance() {
static Logger instance;
return instance;
}
#if MODE_DEBUG
Logger(LogLevel level = DEBUG) : logLevel(level) {}
#elif MODE_INFO
Logger(LogLevel level = INFO) : logLevel(level) {}
#elif MODE_WARN
Logger(LogLevel level = WARN) : logLevel(level) {}
#elif MODE_ERROR
Logger(LogLevel level = ERROR) : logLevel(level) {}
#else
Logger(LogLevel level = DEBUG) : logLevel(level) {}
#endif
void log(LogLevel level, const char* file, int line, const char* format, ...) {
std::lock_guard<std::mutex> lock(mtx);
if (level >= logLevel) {
// Print log prefix
printLogPrefix(level, file, line);
va_list args;
va_start(args, format);
vfprintf(stdout, format, args);
va_end(args);
std::cout << std::endl;
}
}
void log_no_newline(LogLevel level, const char* file, int line, const char* format, ...) {
std::lock_guard<std::mutex> lock(mtx);
if (level >= logLevel) {
// Print log prefix
printLogPrefix(level, file, line);
va_list args;
va_start(args, format);
vfprintf(stdout, format, args);
va_end(args);
}
}
void setLogLevel(LogLevel level) {
logLevel = level;
}
private:
LogLevel logLevel;
std::mutex mtx;
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
void printLogPrefix(LogLevel level, const char* file, int line) {
#if LOG_SHOW_LEVEL
std::cout << "[" << getLevelString(level) << "] ";
#endif
#if LOG_SHOW_PATH
std::cout << file;
#elif LOG_SHOW_FILENAME
std::cout << getFileName(file);
#endif
#if LOG_SHOW_LINE
std::cout << ":" << line;
#endif
if (LOG_SHOW_PATH || LOG_SHOW_FILENAME || LOG_SHOW_LINE) {
std::cout << " ";
}
}
const char* getFileName(const char* path) {
const char* fileName = path;
for (const char* p = path; *p; ++p) {
if (*p == '/' || *p == '\\') {
fileName = p + 1;
}
}
return fileName;
}
const char* getLevelString(LogLevel level) {
switch (level) {
case DEBUG: return "DEBUG";
case INFO: return "INFO ";
case WARN: return "WARN ";
case ERROR: return "ERROR";
default: return "UNKNOWN";
}
}
};
// Helper macros to easily log messages with file and line information
#define LOG_DEBUG(format, ...) Logger::getInstance().log(Logger::DEBUG, __FILE__, __LINE__, format, ##__VA_ARGS__)
#define LOG_DEBUG_(format, ...) Logger::getInstance().log_no_newline(Logger::DEBUG, __FILE__, __LINE__, format, ##__VA_ARGS__)
#define LOG_INFO(format, ...) Logger::getInstance().log(Logger::INFO, __FILE__, __LINE__, format, ##__VA_ARGS__)
#define LOG_INFO_(format, ...) Logger::getInstance().log_no_newline(Logger::INFO, __FILE__, __LINE__, format, ##__VA_ARGS__)
#define LOG_WARN(format, ...) Logger::getInstance().log(Logger::WARN, __FILE__, __LINE__, format, ##__VA_ARGS__)
#define LOG_WARN_(format, ...) Logger::getInstance().log_no_newline(Logger::WARN, __FILE__, __LINE__, format, ##__VA_ARGS__)
#define LOG_ERROR(format, ...) Logger::getInstance().log(Logger::ERROR, __FILE__, __LINE__, format, ##__VA_ARGS__)
#define LOG_ERROR_(format, ...) Logger::getInstance().log_no_newline(Logger::ERROR, __FILE__, __LINE__, format, ##__VA_ARGS__)
#endif //MONITORING_LOGGER_H
标签:头文件,level,LogLevel,C++,logLevel,MODE,gpt,Logger,define
From: https://www.cnblogs.com/aliving/p/18308867