Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
pi_logger
pi_logger 是一个 Rust 日志与可观测性库。当前项目同时保留旧的 log4rs HTTP/SLS appender 能力,并新增了基于 tracing 的 observability 统一接口。
Observability 初始化后同时支持 tracing::...! 和标准日志门面 log::...!。
新接口重点支持:
- 控制台日志;
- 本地 rolling 日志;
- 远端 OpenTelemetry logs 上传;
- OpenTelemetry traces 上传;
- OpenTelemetry metrics 上传;
- 默认等级 + override 覆盖规则;
- target/span 模糊匹配;
- event 字段过滤;
- 运行时动态修改过滤规则;
- 按 override
name动态启用/禁用规则; - 本地/控制台与远端 logs 可使用不同过滤配置。
1. 模块概览
src/
observability/ # 新 tracing/OTel 可观测性接口
ali_sls.rs # 旧 log4rs 阿里云 SLS appender
http.rs # 旧 log4rs HTTP appender
encode_json.rs # 旧 JsonEncoder
encode_json_str.rs # 旧 JsonStrEncoder
encode_sls.rs # 旧 SLSEncoder
opentelemetry.rs # 旧 OpenTelemetry 初始化接口
推荐新项目优先使用:
observability
旧接口仍保留,避免破坏现有调用。
2. 快速开始
2.1 Cargo.toml
[]
= "1"
= { = "../pi_logger" }
= "0.8"
= "0.1"
如果使用当前仓库内的 demo,可参考:
../pi_logger_demo
3. observability.toml 示例
[]
= "json"
[]
= "info"
[[]]
= "decoder_trace_by_id"
= true
= "trace"
= 100
= [
{ = "target", = "contains", = "decoder" },
]
= [
{ = "id", = "eq", = 100 },
{ = "msg", = "contains", = "decode" },
{ = "protocol", = "in", = ["ton", "eth"] },
{ = "payload_len", = "lte", = 4096 },
{ = "sampled", = "eq", = true },
]
[[]]
= "noisy_db_warn"
= true
= "warn"
= 50
= [
{ = "target", = "contains", = "db" },
]
[]
= true
[]
= true
= "logs"
= "app.log"
[]
= true
= "http://127.0.0.1:4318"
[]
= "off"
[[]]
= "remote_decoder_id_100"
= true
= "info"
= 100
= [
{ = "target", = "contains", = "decoder" },
]
= [
{ = "id", = "eq", = 100 },
{ = "test_kind", = "contains", = "remote" },
{ = "module", = "starts_with", = "remote" },
{ = "status", = "in", = ["ok", "retry"] },
{ = "retry_count", = "lte", = 3 },
{ = "sampled", = "eq", = true },
]
[]
= true
[]
= true
= "otlp"
= "http://127.0.0.1:4318"
= "my-rust-service"
= "0.1.0"
[]
= "off"
[[]]
= "trace_test_on"
= true
= "info"
= 100
= [
{ = "target", = "contains", = "trace_test" },
]
[]
= true
= "otlp"
= "http://127.0.0.1:4318"
= "my-rust-service"
= "0.1.0"
4. 初始化
use Result;
use init_observability_from_optional_path;
use Path;
注意:
guards必须保活到进程退出前,否则 non-blocking 本地日志可能丢失。guards.shutdown()会刷新并关闭 OpenTelemetry logs/traces/metrics provider。- 不要重复调用
init_observability初始化全局 subscriber。
配置路径行为:
- 路径存在:读取配置,并启动文件监听;
- 文件修改并稳定 10 秒后,自动 reload local、remote、trace 过滤规则;
- 文件解析或过滤规则校验失败时,旧规则继续生效;
- 路径为
None或文件不存在:使用RUST_LOG创建仅控制台日志配置; console/local/remote/trace/metrics enabled、endpoint、格式和文件路径不支持热更新,需要重启。- remote filter 在“复用 local”和“独立
[log.remote.filter]”之间切换需要重启。
RUST_LOG 支持转换为 ordered filter:
RUST_LOG=info,my_app=debug,hyper=warn
default_level = info
my_app target prefix override = debug
hyper target prefix override = warn
外部系统可以在应用配置前调用检查接口:
use validate_observability_config_path;
let config = validate_observability_config_path?;
该接口只读取、解析和校验配置,不连接 Collector,也不会修改当前日志状态。
4.1 使用 pi_config 初始化
启用可选 feature:
[]
= { = "0.7", = ["pi-config"] }
= "0.6"
应用总配置可以将日志配置放在 observability 子树中。pi_logger 使用
Config::sub_value("observability") 一次读取合并后的完整子树,因此 TOML、CLI、
ENV、DEFAULT 和 overlay 的优先级处理仍由 pi_config 负责。
use Result;
use ConfigBuilder;
use init_observability_from_pi_config;
pi_config 更新通知到达后,配置管理器将最新配置交给日志库:
use Config;
use ;
更新接口会先读取并校验完整 observability 子树,再更新 local、remote、trace
过滤规则。校验失败时旧规则继续生效。enabled、endpoint、格式、文件路径和
metrics 配置仍然需要重启后生效。
5. 过滤规则模型
完整规则说明见:
核心模型:
default_level + overrides
- 没有命中 override 时使用
default_level。 - 多条 override 命中时选择
priority最大的一条。 - override 内的
fuzzy_rules是 OR 关系。 - override 内的
field_rules是 AND 关系。 - 最高优先级 override 一旦选中,字段不匹配不会回退默认等级或较低优先级规则。
6. default_level
支持 trace、debug、info、warn、error、off。生产环境通常使用
info,排查问题时通过 overrides 临时提升部分模块。
7. overrides
Override 按 target/span 选择一批日志并覆盖默认等级。name 必须唯一,
priority 越大优先级越高,enabled = false 时规则不参与匹配。
8. Fuzzy Rules
支持 target/span 的 exact、prefix、contains、glob、regex 匹配。
高流量场景优先使用 target exact 和 prefix。
9. Field Rules
支持 event fields 的相等、字符串、集合、存在性和数值比较。字段规则只读取
tracing event fields,不读取 #[tracing::instrument(fields(...))] 的 span fields。
10. 本地与远端过滤
本地/控制台使用:
[]
= "info"
远端 OpenTelemetry logs 可以使用独立过滤:
[]
= true
= "http://127.0.0.1:4318"
[]
= "off"
[[]]
= "remote_decoder_id_100"
= true
= "info"
= 100
= [
{ = "target", = "contains", = "decoder" },
]
= [
{ = "id", = "eq", = 100 },
{ = "test_kind", = "contains", = "remote" },
{ = "module", = "starts_with", = "remote" },
{ = "status", = "in", = ["ok", "retry"] },
{ = "retry_count", = "lte", = 3 },
{ = "sampled", = "eq", = true },
]
这样可以做到:
- 本地默认保留所有模块
info及以上; - 远端默认不上报 logs;
- 远端只临时上传指定模块、指定字段的日志。
如果不配置 [log.remote.filter],远端 logs 会复用 [log.filter]。
11. 输出格式
[]
= "json"
支持四种格式:
json 结构化 JSON,适合生产采集和机器解析
compact 单行紧凑文本,适合开发时控制台查看
full 完整文本格式,信息比 compact 更充分
pretty 多行美化文本,适合本地调试
format 影响 console 和 local file 输出;远端 OpenTelemetry logs 会转换为 OTel LogRecord,不受该字段影响。
12. 控制台日志
[]
= true
启用后,命中过滤规则的日志会输出到 stdout。实际格式由 [log].format 决定。
13. 本地 rolling 日志
[]
= true
= "logs"
= "app.log"
输出文件示例:
logs/app.log.2026-06-05
format = "json" 时,本地日志包含:
- target;
- file;
- line number;
- thread id;
- thread name;
- current span;
- span list。
14. 远端 OpenTelemetry logs
[]
= true
= "http://127.0.0.1:4318"
实际上传地址会自动拼接为:
http://127.0.0.1:4318/v1/logs
远端日志使用 opentelemetry-appender-tracing 将 tracing event 转换为 OpenTelemetry LogRecord。
15. OpenTelemetry traces
[]
= true
= "otlp"
= "http://127.0.0.1:4318"
= "my-rust-service"
= "0.1.0"
实际上传地址会自动拼接为:
http://127.0.0.1:4318/v1/traces
trace layer 基于 tracing-opentelemetry,兼容 #[tracing::instrument]。
traces pipeline 与 logs pipeline 独立。关闭某个 target 的日志 event,不会阻止 #[tracing::instrument] 创建的 span 上传到 traces pipeline。
16. 业务埋点示例
16.1 使用 log 宏
Observability 初始化会安装 tracing-log 兼容桥接,以下日志进入相同的
console、local 和 remote 日志层:
info!;
debug!;
warn!;
log target 可以使用现有 fuzzy target 规则过滤。未显式指定 target 时,默认使用
Rust 模块路径。
桥接后的事件在格式化输出中顶层 tracing target 显示为 log,原始 target 保存在
log.target 字段。Observability target 过滤会自动使用原始 log.target。
普通 log::...! 主要提供等级、target 和 message,不支持 tracing::info! 的结构化
业务字段语法。需要按 id、status 等字段过滤时,应使用 tracing::...!。
Observability 会把 log 门面的最大等级设置为 trace,最终过滤交给 observability
规则,因此运行时 reload 到 debug/trace 后,log::debug! 和 log::trace! 可以立即生效。
Rust 进程只能安装一个全局 log logger。Observability 不能与已初始化的 log4rs、
env_logger 或其他全局 logger 同时使用;发生冲突时初始化会返回明确错误。
说明:
target可用于 target fuzzy rule;decode_transactionspan 名可用于 span fuzzy rule;id、msg、payload_len是 event fields,可用于field_rules;#[tracing::instrument(fields(...))]中的字段是 span 字段,主要用于 trace/span 上下文。
17. 动态 reload
初始化后会返回 ObservabilityReloadHandle:
let = init_observability?;
reload 分为三个过滤作用域:
reload.local; // console 和本地文件日志
reload.remote?; // 远端 OTLP logs
reload.trace?; // 远端 OTLP traces
metrics 暂不支持动态 reload。
17.1 修改默认等级
reload.local.reload_default_level?;
reload.remote?.reload_default_level?;
reload.trace?.reload_default_level?;
旧的无作用域方法仍然保留,并代理到 local:
reload.reload_default_level?;
17.2 替换全部 overrides
use ;
reload.trace?.reload_overrides?;
17.3 按 name 启用或禁用 override
reload.local.set_override_enabled?;
reload.remote?.set_override_enabled?;
reload.trace?.set_override_enabled?;
name 不存在会返回错误。更新失败时,旧规则继续生效。
17.4 替换完整 filter
reload.local.reload_filter?;
reload.remote?.reload_filter?;
reload.trace?.reload_filter?;
reload 行为:
- 新规则会先解析、校验、预编译 regex;
- override
name必须唯一; - 成功后才替换当前规则;
- 失败时旧规则继续生效;
- 错误链会尽量带上具体 override
name。 - 配置文件监听使用 10 秒防抖,连续修改会重新计时;
- 文件监听自动 reload 不受手动 API 的
log.dynamic.enabled限制; log.dynamic.enabled = false只禁止外部代码主动调用 reload API。reload_observability_filters和reload_observability_filters_from_pi_config用于配置文件监听或配置中心通知,只更新 local、remote、trace 过滤规则;
作用域说明:
- remote logs 未配置独立
[log.remote.filter]时,会复用 local filter,因此 local 和 remote reload 指向同一过滤状态; - trace 未配置
[trace.filter]时默认使用default_level = "trace",保持全部 spans/events 上传; - trace filter 与日志 filter 独立,开启日志
trace等级不会自动开启 traces,反之亦然。
18. 多进程动态调整
reload 只影响当前进程内的 subscriber。多进程场景下,推荐使用共享配置文件或配置中心:
配置文件/配置中心更新
-> 每个进程各自监听
-> 每个进程读取并校验新配置
-> 每个进程调用 reload_filter/reload_overrides
不要假设一个进程的 reload 会自动影响其他进程。
19. 验证方式
当前项目建议使用:
observability 过滤器基准测试参考 tracing / tracing-subscriber 官方 benchmark:
只编译 benchmark,不执行:
当前 benchmark 使用 no-op layer 隔离文件和网络 IO,主要覆盖:
- tracing no-op subscriber baseline;
- 默认等级通过/拒绝;
1 / 10 / 100条 override 的命中与未命中;- 单字段和多字段过滤;
- 默认等级 reload;
- 按 name 动态开关 override;
- 重新加载 100 条 overrides。
默认工具链 nightly-2026-06-01 在当前依赖 pi_share 0.5.2 上可能失败,这是既有依赖与最新 nightly API 的兼容问题,不是 observability 代码导致。
20. observability 示例
当前 crate 内置 observability 示例:
examples/observability_demo.rs
examples/observability.toml
运行:
PI_LOGGER_OBSERVABILITY_CONFIG=examples/observability.toml \
不传配置路径时使用 RUST_LOG,并只启用控制台日志:
RUST_LOG=info,pi_logger_example::trace_test=debug \
示例演示:
- 本地/控制台默认等级;
- 远端 logs 独立过滤;
- 多种 field_rules 字段过滤:数字、字符串、数组、布尔;
#[tracing::instrument]调用链上传 traces;- 独立
[trace.filter]控制应用跟踪上传; - counter、histogram、up_down_counter 指标上传 metrics;
- logs pipeline、traces pipeline 与 metrics pipeline 独立。
21. 旧接口说明
旧接口仍然保留:
pi_logger::http::HttpAppenderpi_logger::ali_sls::SLSAppenderpi_logger::ali_sls::SLBatchConfigpi_logger::encode_json::JsonEncoderpi_logger::encode_json_str::JsonStrEncoderpi_logger::encode_sls::SLSEncoderpi_logger::opentelemetry::{init, is_init, reload_trace_level, create_baggage}
这些接口主要服务于已有 log4rs 接入方式。新项目建议优先使用 pi_logger::observability。
22. 注意事项
- override
name必须唯一。 enabled = false的 override 不参与匹配。- 多条 override 命中时,最高
priority生效。 - 同一 override 内,
fuzzy_rules是 OR 语义。 - 同一 override 内,
field_rules是 AND 语义。 - regex/glob 规则会预编译,并有数量和长度限制。
- field_rules 会读取 event fields,只建议挂在需要临时收敛的 override 上。
- remote logs/traces 需要 OpenTelemetry Collector。
- 本地日志使用 non-blocking writer,必须持有
ObservabilityGuards。 - demo 中固定
time = "=0.3.45"是为了兼容nightly-2025-03-20。