玩转小项目之日志库

2023-09-02 10:44:08 浏览数 (1)

玩转小项目之日志库

今天分享arrow日志库的设计与实现,所有源码均在星球提供(加入方式见末尾),本次项目重写arrow日志库,将arrow日志库提取出来,整个项目基于bazel构建。

目前支持的特性有:

  • 默认日志格式
  • spdlog日志格式
  • 支持堆栈输出
  • 支持日志在终端打印
  • 支持日志输出至文件
  • 支持日志高亮显示
  • 支持日志插件扩展
  • 支持多种日志级别

先来看第一个特性:默认日志格式输出与终端打印:

代码语言:javascript复制
➜  light-log bazel-bin/tests/log_test    
tests/log_test.cc:13: This is the INFO message
tests/log_test.cc:15: This is the WARNING message
tests/log_test.cc:17: This is the ERROR message
This is the DEBUG message
tests/log_test.cc:13: This is the INFO message
tests/log_test.cc:15: This is the WARNING message
tests/log_test.cc:17: This is the ERROR message
===============================================================================
test cases: 1 | 1 passed
assertions: - none -

第二个特性:spdlog终端与文件输出:

编译时,通过宏参数控制,只需要传递ARROW_USE_SPDLOG即可。

代码语言:javascript复制
 bazel test //tests:log_test --define ARROW_WITH_BACKTRACE=true --define ARROW_USE_SPDLOG=true
  • 终端打印
代码语言:javascript复制
[2023-08-16 07:15:14,660 I 21004 41898222] log_test.cc:13: This is the INFO message
[2023-08-16 07:15:14,660 W 21004 41898222] log_test.cc:15: This is the WARNING message
[2023-08-16 07:15:14,661 E 21004 41898222] log_test.cc:17: This is the ERROR message
===============================================================================
test cases: 1 | 1 passed
assertions: - none -
  • 文件输出

堆栈特性输出:

代码语言:javascript复制
➜  light-log bazel-bin/main                                                                       
0   main                                0x0000000105e8d8fb _ZN5arrow4util14PrintBackTraceERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEE   75
1   main                                0x0000000105ef1937 _ZN5arrow4util13SpdLogMessage5FlushEv   231
2   main                                0x0000000105ef180c _ZN5arrow4util13SpdLogMessageD2Ev   28
3   main                                0x0000000105e8f395 _ZN5arrow4util13SpdLogMessageD1Ev   21
4   main                                0x0000000105e8f34e _ZN5arrow4util8ArrowLogD2Ev   78
5   main                                0x0000000105e8f3b5 _ZN5arrow4util8ArrowLogD1Ev   21
6   main                                0x0000000105e8c131 main   113
7   libdyld.dylib                       0x00007fff2041cf3d start   1
[2023-08-16 07:20:05,798 C 21937 41909787] test:10: hello logginghello2 logginghello3 logging
*** StackTrace Information ***

[1]    21937 abort      bazel-bin/main

1.实现

1.1 可插拔

通过使用宏:

代码语言:javascript复制
ARROW_USE_SPDLOG

来达到开关spdlog库的功能。

通过使用宏:

代码语言:javascript复制
ARROW_WITH_BACKTRACE

来达到堆栈是否输出的功能。

实现层面,抽象出公共基类:

代码语言:javascript复制
class ARROW_EXPORT ArrowLogBase {
 public:
  virtual ~ArrowLogBase() {}

  virtual bool IsEnabled() const { return false; }

  template <typename T>
  ArrowLogBase& operator<<(const T& t) {
    if (IsEnabled()) {
      Stream() << t;
    }
    return *this;
  }

 protected:
  virtual std::ostream& Stream() = 0;
};

所有日志扩展通过继承的方式实现这些接口。

对于所有的扩展,采用typedef来实现可扩展性。

代码语言:javascript复制
#ifdef ARROW_USE_SPDLOG
typedef SpdLogMessage LoggingProvider;
#else
typedef CerrLog LoggingProvider;
#endif

1.2 宏

沿用arrow原始的宏定义,只需要简单的ARROW_LOG便可以输出各种日志级别的日志。

代码语言:javascript复制
ARROW_LOG(ARROW_DEBUG) << "This is the"
                         << " DEBUG"
                         << " message";

1.3 日志级别

通过枚举实现,覆盖所有日志级别。

代码语言:javascript复制
enum class ArrowLogLevel : int {
  ARROW_TRACE = -2,
  ARROW_DEBUG = -1,
  ARROW_INFO = 0,
  ARROW_WARNING = 1,
  ARROW_ERROR = 2,
  ARROW_FATAL = 3
};

0 人点赞