#头文件
#include <co/log.h>
API 在 log 命名空间。
#初始化与关闭
log 内部使用 flag 组件定义了一些配置项,可通过命令行参数或配置文件控制日志行为。另外,日志线程在命令行参数解析后才会启动。因此必须在 main 函数开头调用:
flag::parse(argc, argv);
关闭 API:
void log::close();
- 刷新日志缓冲区,退出日志线程。
- 用户一般不需要显示调用此函数。
#打印日志
使用如下函数打印不同级别的日志:
log::debug(...);
log::info(...);
log::warn(...);
log::error(...);
log::fatal(...);
- 上述函数均线程安全,接受任意数量参数;
- 参数可以是
co::string::operator<<支持的任意类型; - 日志尾部自动添加换行;
fatal级别日志会终止程序。
示例:
log::info("hello ", false, ' ', 23);
支持的参数类型有:
- bool,输出 false 或 true;
- 字符类型:
char, signed char, unsigned char; - 整数类型;
- 浮点数类型:
double, float; - 字符串类型:
const char*,co::string,std::string,std::string_view; - 指针类型:
void*, T*,输出0x加十六进制值; - STL 容器:
std::vector, std::map, co::vector, co::map等,需包含co/stl.h。
自定义类型需实现 operator<<(co::string&, const T&),如:
struct Point {
int x, y;
};
inline co::string& operator<<(co::string& s, const Point& p) {
s << "Point(" << p.x << ", " << p.y << ")";
return s;
}
int main(int argc, char** argv) {
flag::parse(argc, argv);
Point p{1, 2};
co::println("point: ", p);
log::info("point: ", p);
return 0;
}
#断言
log::check(cond, ...);
log::check_eq(a, b, ...);
log::check_ne(a, b, ...);
log::check_lt(a, b, ...);
log::check_gt(a, b, ...);
log::check_le(a, b, ...);
log::check_ge(a, b, ...);
- check 失败,会刷新日志缓冲,打印堆栈信息,调用
abort()终止程序; - check 成功,不会输出任何信息。
示例:
log::check(1 + 1 == 2, "1+1 should be 2");
log::check_eq(1 + 1, 2, "1+1 must == 2");
log::check_ne(1 + 1, 3, "1+1 != 3");
log::check_lt(1, 2, "1 < 2");
log::check_gt(2, 1, "2 > 1");
log::check_le(2, 2, "2 <= 2");
log::check_ge(2, 2, "2 >= 2");
#打印堆栈信息
coost 会捕捉程序中产生的异常或异常信号,在程序崩溃退出前打印堆栈信息。
非 Windows 平台需要 libbacktrace。Linux 上 GCC 一般已内置 backtrace 库,macOS 通常需要用户手动安装。
非 Windows 平台构建时用下述方式启用此功能:
# xmake
xmake f --with_backtrace=true # 使用 backtrace 库
xmake # 编译 libco
xmake b stack # 编译 test/stack.cc
xmake r stack # 执行 stack 测试程序
# cmake
mkdir cmakebuild && cd cmakebuild
cmake .. -DWITH_BACKTRACE=ON
make -j8
#写日志回调
coost 日志默认写本地文件,用户可以设置一个 callback 写日志:
void log::set_write_cb(
void(*cb)(const void* data, size_t size),
bool also_log2local=false
);
data中可能包含多条日志,size可能较大,用UDP发送日志需注意。- callback 日志线程中执行(仅单个线程写日志)。
- 若
also_log2local == true,日志也写本地文件。
需要在flag::parse前调用,flag::parse解析命令行参数后会启动日志线程,在日志线程启动前设置 callback 更安全。
示例:
#include <co/log.h>
#include <stdio.h>
static void my_write_cb(const void* data, size_t size) {
fwrite(data, 1, size, stderr);
}
int main(int argc, char** argv) {
log::set_write_cb(my_write_cb, false);
flag::parse(argc, argv);
log::info("hello ", 23);
log::warn("warn ", false);
return 0;
}
#日志配置项
| flag 名 | 类型 | 默认值 | 含义 |
|---|---|---|---|
log_dir |
string | "logs" |
日志目录 |
min_log_level |
uint32 | 0 |
输出日志的最小级别,0-4 对应 debug/info/warn/error/fatal |
max_log_size |
uint32 | 4096 |
单条日志最大大小 |
max_log_file_size |
int64 | 256 << 20,即 256MB |
日志文件最大大小 |
max_log_file_num |
uint32 | 8 |
日志文件最大数量 |
max_log_buffer_size |
uint32 | 32 << 20,即 32MB |
日志缓存最大大小 |
log_flush_ms |
uint32 | 128 |
刷新日志缓存的时间间隔,单位毫秒 |
also_log2console |
bool | false |
日志也输出到终端 |
log_daily |
bool | false |
日志文件按天轮转 |
min_log_level 可以过滤掉低级别的日志,级别大于或等于 min_log_level 的日志才输出。
#最小示例
#include <co/log.h>
int main(int argc, char** argv) {
# parse 是必须的,解析命令行参数后,启动日志线程
flag::parse(argc, argv);
log::debug("This is debug.. ", 23);
log::info("This is info.. ", 23);
log::warn("This is warn.. ", 23);
log::error("This is error.. ", 23);
log::check(1 + 1 == 2, "1+1 should be 2");
log::check_eq(1 + 1, 2, "1+1 must == 2");
log::check_ne(1 + 1, 3, "1+1 != 3");
log::check_lt(1, 2, "1 < 2");
log::check_gt(2, 1, "2 > 1");
log::check_le(2, 2, "2 <= 2");
log::check_ge(2, 2, "2 >= 2");
// log::fatal("fatal.. ", 23); // 会终止程序
return 0;
}
运行示例:
./app -min_log_level=1 -also_log2console=true
命令行参数表示只输出 info 及以上级别日志,并输出到终端。