Older/ToolKit/Util/logger.h

446 lines
13 KiB
C
Raw Normal View History

2024-09-28 23:55:00 +08:00
/*
* Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
*
* This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef UTIL_LOGGER_H_
#define UTIL_LOGGER_H_
#include <cstdarg>
#include <set>
#include <map>
#include <fstream>
#include <thread>
#include <memory>
#include <mutex>
#include "util.h"
#include "List.h"
#include "Thread/semaphore.h"
namespace toolkit {
class LogContext;
class LogChannel;
class LogWriter;
class Logger;
using LogContextPtr = std::shared_ptr<LogContext>;
typedef enum {
LTrace = 0, LDebug, LInfo, LWarn, LError
} LogLevel;
Logger &getLogger();
void setLogger(Logger *logger);
/**
*
*/
class Logger : public std::enable_shared_from_this<Logger>, public noncopyable {
public:
friend class AsyncLogWriter;
using Ptr = std::shared_ptr<Logger>;
/**
*
* @return
*/
static Logger &Instance();
explicit Logger(const std::string &loggerName);
~Logger();
/**
* 线
* @param channel log通道
*/
void add(const std::shared_ptr<LogChannel> &channel);
/**
* 线
* @param name log通道名
*/
void del(const std::string &name);
/**
* 线
* @param name log通道名
* @return 线
*/
std::shared_ptr<LogChannel> get(const std::string &name);
/**
* log器线
* @param writer log器
*/
void setWriter(const std::shared_ptr<LogWriter> &writer);
/**
* log等级
* @param level log等级
*/
void setLevel(LogLevel level);
/**
* logger名
* @return logger名
*/
const std::string &getName() const;
/**
*
* @param ctx
*/
void write(const LogContextPtr &ctx);
private:
/**
* channelAsyncLogWriter调用
* @param ctx
*/
void writeChannels(const LogContextPtr &ctx);
void writeChannels_l(const LogContextPtr &ctx);
private:
LogContextPtr _last_log;
std::string _logger_name;
std::shared_ptr<LogWriter> _writer;
std::shared_ptr<LogChannel> _default_channel;
std::map<std::string, std::shared_ptr<LogChannel> > _channels;
};
///////////////////LogContext///////////////////
/**
*
*/
class LogContext : public std::ostringstream {
public:
//_file,_function改成string保存目的是有些情况下指针可能会失效
//比如说动态库中打印了一条日志,然后动态库卸载了,那么指向静态数据区的指针就会失效
LogContext() = default;
LogContext(LogLevel level, const char *file, const char *function, int line, const char *module_name, const char *flag);
~LogContext() = default;
LogLevel _level;
int _line;
int _repeat = 0;
std::string _file;
std::string _function;
std::string _thread_name;
std::string _module_name;
std::string _flag;
struct timeval _tv;
const std::string &str();
private:
bool _got_content = false;
std::string _content;
};
/**
*
*/
class LogContextCapture {
public:
using Ptr = std::shared_ptr<LogContextCapture>;
LogContextCapture(Logger &logger, LogLevel level, const char *file, const char *function, int line, const char *flag = "");
LogContextCapture(const LogContextCapture &that);
~LogContextCapture();
/**
* std::endl()
* @param f std::endl()
* @return
*/
LogContextCapture &operator<<(std::ostream &(*f)(std::ostream &));
template<typename T>
LogContextCapture &operator<<(T &&data) {
if (!_ctx) {
return *this;
}
(*_ctx) << std::forward<T>(data);
return *this;
}
void clear();
private:
LogContextPtr _ctx;
Logger &_logger;
};
///////////////////LogWriter///////////////////
/**
*
*/
class LogWriter : public noncopyable {
public:
LogWriter() = default;
virtual ~LogWriter() = default;
virtual void write(const LogContextPtr &ctx, Logger &logger) = 0;
};
class AsyncLogWriter : public LogWriter {
public:
AsyncLogWriter();
~AsyncLogWriter();
private:
void run();
void flushAll();
void write(const LogContextPtr &ctx, Logger &logger) override;
private:
bool _exit_flag;
semaphore _sem;
std::mutex _mutex;
std::shared_ptr<std::thread> _thread;
List<std::pair<LogContextPtr, Logger *> > _pending;
};
///////////////////LogChannel///////////////////
/**
*
*/
class LogChannel : public noncopyable {
public:
LogChannel(const std::string &name, LogLevel level = LTrace);
virtual ~LogChannel();
virtual void write(const Logger &logger, const LogContextPtr &ctx) = 0;
const std::string &name() const;
void setLevel(LogLevel level);
static std::string printTime(const timeval &tv);
protected:
/**
*
* @param ost
* @param enable_color
* @param enable_detail ()
*/
virtual void format(const Logger &logger, std::ostream &ost, const LogContextPtr &ctx, bool enable_color = true, bool enable_detail = true);
protected:
std::string _name;
LogLevel _level;
};
/**
* 广
*/
class EventChannel : public LogChannel {
public:
//输出日志时的广播名
static const std::string kBroadcastLogEvent;
//toolkit目前仅只有一处全局变量被外部引用减少导出相关定义导出以下函数避免导出kBroadcastLogEvent
static const std::string& getBroadcastLogEventName();
//日志广播参数类型和列表
#define BroadcastLogEventArgs const Logger &logger, const LogContextPtr &ctx
EventChannel(const std::string &name = "EventChannel", LogLevel level = LTrace);
~EventChannel() override = default;
void write(const Logger &logger, const LogContextPtr &ctx) override;
};
/**
* android logcat
*/
class ConsoleChannel : public LogChannel {
public:
ConsoleChannel(const std::string &name = "ConsoleChannel", LogLevel level = LTrace);
~ConsoleChannel() override = default;
void write(const Logger &logger, const LogContextPtr &logContext) override;
};
/**
*
*/
class FileChannelBase : public LogChannel {
public:
FileChannelBase(const std::string &name = "FileChannelBase", const std::string &path = exePath() + ".log", LogLevel level = LTrace);
~FileChannelBase() override;
void write(const Logger &logger, const LogContextPtr &ctx) override;
bool setPath(const std::string &path);
const std::string &path() const;
protected:
virtual bool open();
virtual void close();
virtual size_t size();
protected:
std::string _path;
std::ofstream _fstream;
};
class Ticker;
/**
*
* 30
*/
class FileChannel : public FileChannelBase {
public:
FileChannel(const std::string &name = "FileChannel", const std::string &dir = exeDir() + "log/", LogLevel level = LTrace);
~FileChannel() override = default;
/**
*
* @param logger
* @param stream
*/
void write(const Logger &logger, const LogContextPtr &ctx) override;
/**
*
* @param max_day
*/
void setMaxDay(size_t max_day);
/**
*
* @param max_size MB
*/
void setFileMaxSize(size_t max_size);
/**
*
* @param max_count
*/
void setFileMaxCount(size_t max_count);
private:
/**
*
*/
void clean();
/**
*
*/
void checkSize(time_t second);
/**
*
*/
void changeFile(time_t second);
private:
bool _can_write = false;
//默认最多保存30天的日志文件
size_t _log_max_day = 30;
//每个日志切片文件最大默认128MB
size_t _log_max_size = 128;
//最多默认保持30个日志切片文件
size_t _log_max_count = 30;
//当前日志切片文件索引
size_t _index = 0;
int64_t _last_day = -1;
time_t _last_check_time = 0;
std::string _dir;
std::set<std::string> _log_file_map;
};
#if defined(__MACH__) || ((defined(__linux) || defined(__linux__)) && !defined(ANDROID))
class SysLogChannel : public LogChannel {
public:
SysLogChannel(const std::string &name = "SysLogChannel", LogLevel level = LTrace);
~SysLogChannel() override = default;
void write(const Logger &logger, const LogContextPtr &logContext) override;
};
#endif//#if defined(__MACH__) || ((defined(__linux) || defined(__linux__)) && !defined(ANDROID))
class BaseLogFlagInterface {
protected:
virtual ~BaseLogFlagInterface() {}
// 获得日志标记Flag
const char* getLogFlag(){
return _log_flag;
}
void setLogFlag(const char *flag) { _log_flag = flag; }
private:
const char *_log_flag = "";
};
class LoggerWrapper {
public:
template<typename First, typename ...ARGS>
static inline void printLogArray(Logger &logger, LogLevel level, const char *file, const char *function, int line, First &&first, ARGS &&...args) {
LogContextCapture log(logger, level, file, function, line);
log << std::forward<First>(first);
appendLog(log, std::forward<ARGS>(args)...);
}
static inline void printLogArray(Logger &logger, LogLevel level, const char *file, const char *function, int line) {
LogContextCapture log(logger, level, file, function, line);
}
template<typename Log, typename First, typename ...ARGS>
static inline void appendLog(Log &out, First &&first, ARGS &&...args) {
out << std::forward<First>(first);
appendLog(out, std::forward<ARGS>(args)...);
}
template<typename Log>
static inline void appendLog(Log &out) {}
//printf样式的日志打印
static void printLog(Logger &logger, int level, const char *file, const char *function, int line, const char *fmt, ...);
static void printLogV(Logger &logger, int level, const char *file, const char *function, int line, const char *fmt, va_list ap);
};
//可重置默认值
extern Logger *g_defaultLogger;
//用法: DebugL << 1 << "+" << 2 << '=' << 3;
#define WriteL(level) ::toolkit::LogContextCapture(::toolkit::getLogger(), level, __FILE__, __FUNCTION__, __LINE__)
#define TraceL WriteL(::toolkit::LTrace)
#define DebugL WriteL(::toolkit::LDebug)
#define InfoL WriteL(::toolkit::LInfo)
#define WarnL WriteL(::toolkit::LWarn)
#define ErrorL WriteL(::toolkit::LError)
//只能在虚继承BaseLogFlagInterface的类中使用
#define WriteF(level) ::toolkit::LogContextCapture(::toolkit::getLogger(), level, __FILE__, __FUNCTION__, __LINE__, getLogFlag())
#define TraceF WriteF(::toolkit::LTrace)
#define DebugF WriteF(::toolkit::LDebug)
#define InfoF WriteF(::toolkit::LInfo)
#define WarnF WriteF(::toolkit::LWarn)
#define ErrorF WriteF(::toolkit::LError)
//用法: PrintD("%d + %s = %c", 1 "2", 'c');
#define PrintLog(level, ...) ::toolkit::LoggerWrapper::printLog(::toolkit::getLogger(), level, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define PrintT(...) PrintLog(::toolkit::LTrace, ##__VA_ARGS__)
#define PrintD(...) PrintLog(::toolkit::LDebug, ##__VA_ARGS__)
#define PrintI(...) PrintLog(::toolkit::LInfo, ##__VA_ARGS__)
#define PrintW(...) PrintLog(::toolkit::LWarn, ##__VA_ARGS__)
#define PrintE(...) PrintLog(::toolkit::LError, ##__VA_ARGS__)
//用法: LogD(1, "+", "2", '=', 3);
//用于模板实例化的原因,如果每次打印参数个数和类型不一致,可能会导致二进制代码膨胀
#define LogL(level, ...) ::toolkit::LoggerWrapper::printLogArray(::toolkit::getLogger(), (LogLevel)level, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define LogT(...) LogL(::toolkit::LTrace, ##__VA_ARGS__)
#define LogD(...) LogL(::toolkit::LDebug, ##__VA_ARGS__)
#define LogI(...) LogL(::toolkit::LInfo, ##__VA_ARGS__)
#define LogW(...) LogL(::toolkit::LWarn, ##__VA_ARGS__)
#define LogE(...) LogL(::toolkit::LError, ##__VA_ARGS__)
} /* namespace toolkit */
#endif /* UTIL_LOGGER_H_ */