扩展与集成(面向 Keel 与适配器实现者)
1. 实现 LogWriterAdapter
集成 Vert.x、日志文件、ELK、OpenTelemetry 等时,核心是实现:
void accept(String topic, SpecificLog<?> log);
约定:
topic:通常对应子系统、类名或业务域,便于过滤与路由。log:读取timestamp()、level()、message()、threadInfo()、context().toMap()、exception()、classification()、extra()等组装目标格式。
注意:SpecificLog 的 level 在便捷方法路径上由框架设置;若从外部直接 log 自定义实例,请自行保证 level() 与业务一致。
2. 文本渲染:LogTextRender 与继承 BaseLogWriter
BaseLogWriter 同时实现 LogWriterAdapter 与 LogTextRender。默认
render(topic, log) 输出多行文本(时间、级别、topic、线程、分类、消息、异常、上下文、extra)。
自定义格式的常见做法:
- 继承
BaseLogWriter; - 覆盖
render或write(例如改为 JSON 行、或写入PrintStream); - 使用单例或工厂把该实例传给
BaseLogger/BaseLoggerFactory子类。
LogTextRender 中的 renderThrowable 默认走 ThrowableRender.renderThrowableChain;若需不同堆栈策略,可在子类覆盖
renderThrowable 或完全自定义 render。
3. 自定义 SpecificLog 与 BaseSpecificLogger
业务审计、安全事件等可扩展字段:
public final class AuditLog extends SpecificLog<AuditLog> {
public AuditLog actor(String v) {
return extra("actor", v); // 或新增字段 + getter
}
}
通过工厂创建:
SpecificLogger<AuditLog> audit = factory.createLogger("audit", AuditLog::new);
audit.
info(log ->log.
message("访问").
actor("user-1"));
extra() 在默认文本渲染中会出现在 Extra as following: 段落;JSON 适配器可将 extra() 与 context() 合并或分字段输出。
normalizedLogger():BaseSpecificLogger 会懒初始化一个 BaseLogger(同 topic、同适配器),并在后续
visibleLevel(...) 时同步级别。当某 API 只接受 Logger 时,可用 specificLogger.normalizedLogger() 过渡。
4. 自定义 LoggerFactory
BaseLoggerFactory 的 protected BaseLoggerFactory(LogWriterAdapter) 允许子类化并配合 replaceShared 在 Keel 启动时注册:
public final class KeelLoggerFactory extends BaseLoggerFactory {
public KeelLoggerFactory(LogWriterAdapter adapter) {
super(adapter);
}
}
// 启动时
LoggerFactory.
replaceShared(new KeelLoggerFactory(new MyJsonLogWriter()));
此后 LoggerFactory.getShared() 创建的 Logger 均使用同一适配器。
5. MetricRecorder 实现要点
- 接口极小,适合桥接到 Micrometer、Prometheus Push、自研 Agent。
MetricRecord.labels()返回的是实现内部 map,调用方应避免长期缓存引用并在多线程下无同步修改;如需不变快照可在实现中拷贝。
6. 堆栈折叠配置
LoggingStackSpecification.IgnorableCallStackPackageSet 为 static 可变集合。框架启动早期可:
LoggingStackSpecification.IgnorableCallStackPackageSet.add("com.mycompany.noise.");
仅影响 默认 ThrowableRender 路径;完全自定义渲染可忽略该集合。
7. LateObject 使用注意
LateObject 用于 BaseSpecificLogger 内部懒创建 BaseLogger。公开类型,但一般业务少用。
set/get:非并发安全语义(重复 set、未 set 即 get 会抛IllegalStateException)。ensure(Supplier):在synchronized块内初始化;文档说明并发下 supplier 可能被多次调用,需幂等或可接受重复执行。
8. 沉默策略选型(集成侧)
| 场景 | 建议 |
|---|---|
| 全局关闭输出且减少对象创建 | visibleLevel(SILENT) 或使用 SilentLogger |
| 保留调用代码路径、但不落库 | SilentLogWriter + 合适 visibleLevel,或 SilentLoggerFactory |
| 单测 | 自定义 LogWriterAdapter 收集列表,或 SilentLogWriter |
9. 与 Lombok / 序列化
本库 不使用 Lombok;集成方 DTO 若对 SpecificLog 做序列化,需自行定义字段映射(本 API 未提供 JSON 注解)。
10. 参考源码位置
关键类型与包路径均以 io.github.sinri.keel.logger.api 为前缀,可直接在 IDE 中跳转阅读;发布件附带
-sources.jar 与 Javadoc。