日志
Goose 实现了一套日志机制,可为用户提供查询执行、性能指标、系统事件等详细信息。
基础用法
Goose 日志机制可通过专用函数 enable_logging 启用或关闭。日志存储在名为 goose_logs 的特殊视图中,可像标准表一样查询。
示例:
CALL enable_logging();
-- Run some queries...
SELECT * FROM goose_logs;
关闭日志可执行:
CALL disable_logging();
清空当前日志可执行:
CALL truncate_goose_logs();
日志级别
Goose 支持多种日志级别,用于控制日志详细程度:
ERROR:仅记录错误信息WARN:记录警告和错误INFO:记录一般信息、警告和错误(默认)DEBUG:记录详细调试信息TRACE:记录非常详细的追踪信息
可通过如下方式设置日志级别:
CALL enable_logging(level = 'debug');
日志类型
在 Goose 中,日志消息可关联日志类型。日志类型主要提供两项能力:
- 对日志生成进行细粒度控制
- 支持结构化日志
按类型记录日志
若只记录某一类型日志:
CALL enable_logging('HTTP');
上述函数会自动设置合适的日志级别,并将 HTTP 加入 enabled_log_types 配置,从而确保仅写入 HTTP 类型日志。
若要启用多个日志类型,直接传入:
CALL enable_logging(['HTTP', 'QueryLog']);
结构化日志
部分日志类型(如 HTTP)带有对应消息 schema。要让 Goose 自动解析消息,可使用 goose_logs_parsed() 宏。例如:
SELECT request.headers FROM goose_logs_parsed('HTTP');
若要查看某个结构化日志类型的 schema,可执行:
DESCRIBE FROM goose_logs_parsed('HTTP');
可用日志类型列表
下面是 Goose 中可用日志类型的(非完整)列表。
| 日志类型 | 说明 | 是否结构化 |
|---|---|---|
QueryLog | 记录 Goose 中执行了哪些查询 | 否 |
FileSystem | 记录 Goose 文件系统相关的所有交互 | 是 |
HTTP | 记录 Goose 内部 HTTP 客户端的所有 HTTP 流量 | 是 |
日志存储
默认情况下,Goose 将日志写入内存日志存储(memory)。Goose 支持不同日志存储类型,目前 core Goose 中实现了以下类型:
| 日志存储 | 说明 |
|---|---|
memory | (默认)写入内存缓冲区 |
stdout | 写入当前进程的 stdout(CSV 格式) |
file | 写入一个或多个 csv 文件 |
注意:goose_logs 视图会自动指向当前激活的日志存储。因此切换日志存储后,goose_logs 返回结果可能变化。
输出到 stdout
CALL enable_logging(storage = 'stdout');
输出到文件
CALL enable_logging(storage = 'file', storage_config = {'path': 'path/to/store/logs'});
或使用等价简写:
CALL enable_logging(storage_path = 'path/to/store/logs');
高级用法
规范化与非规范化日志
Goose 的日志存储支持两种记录方式:规范化(normalized)与非规范化(denormalized)。
在非规范化日志中,上下文信息会直接附加到每条日志;在规范化日志中,日志条目与上下文分开存储,并通过 context_ids 关联上下文信息。
| 日志存储 | 是否规范化 |
|---|---|
memory | 是 |
file | 可配置 |
stdout | 否 |
对于文件存储,可通过路径是否以 .csv 结尾在规范化与非规范化间切换(.csv 为规范化;非 .csv 为非规范化)。文件日志通常建议使用非规范化,因为性能更高且日志总体积更小。配置 file 日志存储规范化方式如下:
-- normalized: creates `/tmp/goose_log_contexts.csv` and `/tmp/goose_log_entries.csv`
CALL enable_logging(storage_path = '/tmp');
-- denormalized: creates `/tmp/logs.csv`
CALL enable_logging(storage_path = '/tmp/logs.csv');
注意:规范化与非规范化的差异通常会被 goose_logs 函数屏蔽,因为它会自动将规范化表 join 成统一结果。也就是说,上述两种配置都可通过 FROM goose_logs; 查询,并得到一致结果。
缓冲区大小
Goose 日志存储实现了缓冲机制以优化日志性能。该机制会在日志生成与实际写入之间引入潜在延迟。这种延迟会模糊真实写入时点,尤其在排查崩溃时会带来问题,因为崩溃前刚产生的日志可能尚未落盘。可通过如下方式配置缓冲区大小:
CALL enable_logging(storage_config = {'buffer_size': 0});
或使用等价简写:
CALL enable_logging(storage_buffer_size = 0);
注意,不同日志存储的默认缓冲区大小不同:
| 日志存储 | 默认缓冲区大小 |
|---|---|
memory | STANDARD_VECTOR_SIZE (2048) |
file | STANDARD_VECTOR_SIZE (2048) |
stdout | 关闭(0) |
例如,若要提升 stdout 日志性能,可开启缓冲以显著(>10x)加速日志写入:
CALL enable_logging(storage = 'stdout', storage_buffer_size = 2048);
或者,假设你正在排查 Goose 崩溃并希望用 file 日志器定位问题:
可按如下方式配置缓冲参数:
CALL enable_logging(storage_path = '/tmp/mylogs', storage_buffer_size = 2048);
语法糖
Goose 提供了一些语法糖以简化常见写法。例如,下面语句是等价的:
-- regular invocation
CALL enable_logging(storage = 'file', storage_config = {'path': 'path/to/store/logs'});
-- using shorthand for common path storage config param
CALL enable_logging(storage = 'file', storage_path = 'path/to/store/logs');
-- omitting `storage = 'file'` -> is implied from presence of `storage_config`
CALL enable_logging(storage_config = {'path': 'path/to/store/logs'});