extern_interface/include/logging/logger.hpp

149 lines
3.7 KiB
C++
Raw Normal View History

#ifndef _INCLUDE_LOGGER_
#define _INCLUDE_LOGGER_
#include <stdint.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <vector>
#include <memory>
#include <iostream>
#include <chrono>
#include <unordered_map>
#include "level.h"
namespace logging {
struct Record;
class LoggerOStream;
class LoggerStreamBuf;
class Logger
{
public:
enum class Level: uint8_t
{
UNKNOWN = 0,
DEBUG = LOG_LEVEL_DEBUG,
INFO = LOG_LEVEL_INFO,
WARN = LOG_LEVEL_WARN,
ERROR = LOG_LEVEL_ERROR,
FATAL = LOG_LEVEL_FATAL
};
constexpr static const char* namesep = "::";
explicit Logger(Level level = Level::INFO);
Logger(const Logger&) = delete;
virtual ~Logger() = default;
void add_stream(std::ostream& stream);
Level level() const;
const std::string& name() const;
Logger* parent() const;
size_t children_count() const;
void set_level(Level level);
template<Level level>
void log(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vlog(level, fmt, args);
va_end(args);
}
template<Level level>
void vlog(const char* fmt, va_list args) {
vlog(level, fmt, args);
}
template<typename E = std::runtime_error>
void raise_from_errno(const char* msg) {
error("%s: %s", msg, strerror(errno));
throw E(msg);
}
void log(Level level, const char* fmt, ...);
void debug(const char* fmt, ...);
void info(const char* fmt, ...);
void warn(const char* fmt, ...);
void error(const char* fmt, ...);
void fatal(const char* fmt, ...);
void vlog(Level level, const char* fmt, va_list args);
virtual void log_message(Level level, const std::string& msg);
LoggerOStream operator[](Level level);
LoggerOStream operator[](int level);
Logger* get_child(const std::string& name, Level level = Level::UNKNOWN);
protected:
explicit Logger(const std::string& name, Level level = Level::INFO, Logger* parent = nullptr);
virtual void log_record(const Record& record);
virtual void write_record(std::ostream& os, const Record& record);
static constexpr std::ostream& default_stream = std::cerr;
std::vector<std::unique_ptr<std::ostream>> _streams;
Logger* _parent;
private:
std::unordered_map<std::string, std::unique_ptr<Logger>> logger_cache;
std::string _name;
Level _level;
};
class LoggerStreamBuf : public std::streambuf {
public:
LoggerStreamBuf(Logger& logger, Logger::Level level);
LoggerStreamBuf(const LoggerStreamBuf&) = delete;
LoggerStreamBuf(LoggerStreamBuf&& loggerStream) = default;
protected:
int overflow(int c) override;
std::streamsize xsputn(const char* s, std::streamsize n) override;
int sync() override;
private:
void flush_line(); // 将当前行写入日志
Logger& _logger;
Logger::Level _level;
std::string _lineBuffer; // 行缓存
};
class LoggerOStream : public std::ostream {
public:
LoggerOStream(Logger& logger, Logger::Level level);
LoggerOStream(const LoggerOStream&) = delete;
LoggerOStream(LoggerOStream&& loggerStream);
private:
LoggerStreamBuf _streamBuf;
};
struct Record
{
std::string name;
std::chrono::system_clock::time_point time;
Logger::Level level;
std::string msg;
Record(const std::string& name, Logger::Level level, const std::string& msg);
};
std::ostream& operator<<(std::ostream& os, const Logger::Level level);
Logger::Level str2level(const char* level);
extern std::unique_ptr<Logger> global_logger;
using LogLevel = Logger::Level;
static inline Logger* get_logger(const std::string& name, LogLevel level = LogLevel::UNKNOWN)
{
return global_logger->get_child(name, level);
}
}
#endif