logger.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
  3. *
  4. * This file is part of ZLToolKit(https://github.com/xia-chu/ZLToolKit).
  5. *
  6. * Use of this source code is governed by MIT license that can be found in the
  7. * LICENSE file in the root of the source tree. All contributing project authors
  8. * may be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef UTIL_LOGGER_H_
  11. #define UTIL_LOGGER_H_
  12. #include <time.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <set>
  16. #include <map>
  17. #include <deque>
  18. #include <iostream>
  19. #include <fstream>
  20. #include <sstream>
  21. #include <thread>
  22. #include <memory>
  23. #include <mutex>
  24. #include "Util/util.h"
  25. #include "Util/List.h"
  26. #include "Thread/semaphore.h"
  27. using namespace std;
  28. namespace toolkit {
  29. class LogContext;
  30. class LogChannel;
  31. class LogWriter;
  32. class Logger;
  33. typedef std::shared_ptr<LogContext> LogContextPtr;
  34. typedef enum {
  35. LTrace = 0, LDebug, LInfo, LWarn, LError
  36. } LogLevel;
  37. Logger &getLogger();
  38. void setLogger(Logger *logger);
  39. /**
  40. * 日志类
  41. */
  42. class Logger : public std::enable_shared_from_this<Logger>, public noncopyable {
  43. public:
  44. friend class AsyncLogWriter;
  45. typedef std::shared_ptr<Logger> Ptr;
  46. /**
  47. * 获取日志单例
  48. * @return
  49. */
  50. static Logger &Instance();
  51. Logger(const string &loggerName);
  52. ~Logger();
  53. /**
  54. * 添加日志通道,非线程安全的
  55. * @param channel log通道
  56. */
  57. void add(const std::shared_ptr<LogChannel> &channel);
  58. /**
  59. * 删除日志通道,非线程安全的
  60. * @param name log通道名
  61. */
  62. void del(const string &name);
  63. /**
  64. * 获取日志通道,非线程安全的
  65. * @param name log通道名
  66. * @return 线程通道
  67. */
  68. std::shared_ptr<LogChannel> get(const string &name);
  69. /**
  70. * 设置写log器,非线程安全的
  71. * @param writer 写log器
  72. */
  73. void setWriter(const std::shared_ptr<LogWriter> &writer);
  74. /**
  75. * 设置所有日志通道的log等级
  76. * @param level log等级
  77. */
  78. void setLevel(LogLevel level);
  79. /**
  80. * 获取logger名
  81. * @return logger名
  82. */
  83. const string &getName() const;
  84. /**
  85. * 写日志
  86. * @param ctx 日志信息
  87. */
  88. void write(const LogContextPtr &ctx);
  89. private:
  90. /**
  91. * 写日志到各channel,仅供AsyncLogWriter调用
  92. * @param ctx 日志信息
  93. */
  94. void writeChannels(const LogContextPtr &ctx);
  95. private:
  96. map<string, std::shared_ptr<LogChannel> > _channels;
  97. std::shared_ptr<LogWriter> _writer;
  98. string _loggerName;
  99. };
  100. ///////////////////LogContext///////////////////
  101. /**
  102. * 日志上下文
  103. */
  104. class LogContext : public ostringstream {
  105. public:
  106. //_file,_function改成string保存,目的是有些情况下,指针可能会失效
  107. //比如说动态库中打印了一条日志,然后动态库卸载了,那么指向静态数据区的指针就会失效
  108. LogContext(LogLevel level, const char *file, const char *function, int line);
  109. ~LogContext() = default;
  110. LogLevel _level;
  111. int _line;
  112. string _file;
  113. string _function;
  114. string _thread_name;
  115. struct timeval _tv;
  116. };
  117. /**
  118. * 日志上下文捕获器
  119. */
  120. class LogContextCapturer {
  121. public:
  122. typedef std::shared_ptr<LogContextCapturer> Ptr;
  123. LogContextCapturer(Logger &logger, LogLevel level, const char *file, const char *function, int line);
  124. LogContextCapturer(const LogContextCapturer &that);
  125. ~LogContextCapturer();
  126. /**
  127. * 输入std::endl(回车符)立即输出日志
  128. * @param f std::endl(回车符)
  129. * @return 自身引用
  130. */
  131. LogContextCapturer &operator<<(ostream &(*f)(ostream &));
  132. template<typename T>
  133. LogContextCapturer &operator<<(T &&data) {
  134. if (!_ctx) {
  135. return *this;
  136. }
  137. (*_ctx) << std::forward<T>(data);
  138. return *this;
  139. }
  140. void clear();
  141. private:
  142. LogContextPtr _ctx;
  143. Logger &_logger;
  144. };
  145. ///////////////////LogWriter///////////////////
  146. /**
  147. * 写日志器
  148. */
  149. class LogWriter : public noncopyable {
  150. public:
  151. LogWriter() {}
  152. virtual ~LogWriter() {}
  153. virtual void write(const LogContextPtr &ctx, Logger &logger) = 0;
  154. };
  155. class AsyncLogWriter : public LogWriter {
  156. public:
  157. AsyncLogWriter();
  158. ~AsyncLogWriter();
  159. private:
  160. void run();
  161. void flushAll();
  162. void write(const LogContextPtr &ctx, Logger &logger) override;
  163. private:
  164. bool _exit_flag;
  165. mutex _mutex;
  166. semaphore _sem;
  167. std::shared_ptr<thread> _thread;
  168. List<std::pair<LogContextPtr,Logger *> > _pending;
  169. };
  170. ///////////////////LogChannel///////////////////
  171. /**
  172. * 日志通道
  173. */
  174. class LogChannel : public noncopyable {
  175. public:
  176. LogChannel(const string &name, LogLevel level = LTrace);
  177. virtual ~LogChannel();
  178. virtual void write(const Logger &logger, const LogContextPtr &ctx) = 0;
  179. const string &name() const;
  180. void setLevel(LogLevel level);
  181. static std::string printTime(const timeval &tv);
  182. protected:
  183. /**
  184. * 打印日志至输出流
  185. * @param ost 输出流
  186. * @param enableColor 是否启用颜色
  187. * @param enableDetail 是否打印细节(函数名、源码文件名、源码行)
  188. */
  189. virtual void format(const Logger &logger, ostream &ost, const LogContextPtr &ctx, bool enableColor = true, bool enableDetail = true);
  190. protected:
  191. string _name;
  192. LogLevel _level;
  193. };
  194. /**
  195. * 输出日志至终端,支持输出日志至android logcat
  196. */
  197. class ConsoleChannel : public LogChannel {
  198. public:
  199. ConsoleChannel(const string &name = "ConsoleChannel", LogLevel level = LTrace);
  200. ~ConsoleChannel();
  201. void write(const Logger &logger, const LogContextPtr &logContext) override;
  202. };
  203. /**
  204. * 输出日志至文件
  205. */
  206. class FileChannelBase : public LogChannel {
  207. public:
  208. FileChannelBase(const string &name = "FileChannelBase", const string &path = exePath() + ".log", LogLevel level = LTrace);
  209. ~FileChannelBase();
  210. void write(const Logger &logger, const LogContextPtr &ctx) override;
  211. bool setPath(const string &path);
  212. const string &path() const;
  213. protected:
  214. virtual bool open();
  215. virtual void close();
  216. virtual size_t size();
  217. protected:
  218. string _path;
  219. ofstream _fstream;
  220. };
  221. class Ticker;
  222. /**
  223. * 自动清理的日志文件通道
  224. * 默认最多保存30天的日志
  225. */
  226. class FileChannel : public FileChannelBase {
  227. public:
  228. FileChannel(const string &name = "FileChannel", const string &dir = exeDir() + "log/", LogLevel level = LTrace);
  229. ~FileChannel() override;
  230. /**
  231. * 写日志时才会触发新建日志文件或者删除老的日志文件
  232. * @param logger
  233. * @param stream
  234. */
  235. void write(const Logger &logger, const LogContextPtr &ctx) override;
  236. /**
  237. * 设置日志最大保存天数
  238. * @param max_day 天数
  239. */
  240. void setMaxDay(size_t max_day);
  241. /**
  242. * 设置日志切片文件最大大小
  243. * @param max_size 单位MB
  244. */
  245. void setFileMaxSize(size_t max_size);
  246. /**
  247. * 设置日志切片文件最大个数
  248. * @param max_count 个数
  249. */
  250. void setFileMaxCount(size_t max_count);
  251. private:
  252. /**
  253. * 删除日志切片文件,条件为超过最大保存天数与最大切片个数
  254. */
  255. void clean();
  256. /**
  257. * 检查当前日志切片文件大小,如果超过限制,则创建新的日志切片文件
  258. */
  259. void checkSize(time_t second);
  260. /**
  261. * 创建并切换到下一个日志切片文件
  262. */
  263. void changeFile(time_t second);
  264. private:
  265. bool _can_write = false;
  266. //默认最多保存30天的日志文件
  267. size_t _log_max_day = 30;
  268. //每个日志切片文件最大默认128MB
  269. size_t _log_max_size = 128;
  270. //最多默认保持30个日志切片文件
  271. size_t _log_max_count = 30;
  272. //当前日志切片文件索引
  273. size_t _index = 0;
  274. int64_t _last_day = -1;
  275. time_t _last_check_time = 0;
  276. string _dir;
  277. set<string> _log_file_map;
  278. };
  279. #if defined(__MACH__) || ((defined(__linux) || defined(__linux__)) && !defined(ANDROID))
  280. class SysLogChannel : public LogChannel {
  281. public:
  282. SysLogChannel(const string &name = "SysLogChannel" , LogLevel level = LTrace) ;
  283. ~SysLogChannel();
  284. void write(const Logger &logger , const LogContextPtr &logContext) override;
  285. };
  286. #endif//#if defined(__MACH__) || ((defined(__linux) || defined(__linux__)) && !defined(ANDROID))
  287. //可重置默认值
  288. extern Logger *g_defaultLogger;
  289. #define TraceL LogContextCapturer(getLogger(), LTrace, __FILE__,__FUNCTION__, __LINE__)
  290. #define DebugL LogContextCapturer(getLogger(),LDebug, __FILE__,__FUNCTION__, __LINE__)
  291. #define InfoL LogContextCapturer(getLogger(),LInfo, __FILE__,__FUNCTION__, __LINE__)
  292. #define WarnL LogContextCapturer(getLogger(),LWarn,__FILE__, __FUNCTION__, __LINE__)
  293. #define ErrorL LogContextCapturer(getLogger(),LError,__FILE__, __FUNCTION__, __LINE__)
  294. #define WriteL(level) LogContextCapturer(getLogger(),level,__FILE__, __FUNCTION__, __LINE__)
  295. } /* namespace toolkit */
  296. #endif /* UTIL_LOGGER_H_ */