skillhub/docs/observability-decision-map.md
XiaoSeS 55e5c1e10e
feat(observability): add generic request correlation and tracing foundation (#664)
* feat(observability): establish request correlation boundary

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

* feat(observability): add selectable tracing modes

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

* feat(observability): propagate async trace context

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

* docs(observability): document tracing deployment modes

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

* fix(observability): tighten tracing integration boundaries

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

* fix(observability): harden operational log privacy

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

* feat(observability): propagate message trace context

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

* fix(observability): document message propagation semantics

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

* test(auth): isolate security context between tests

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

* fix(observability): skip otlp exporter without endpoint

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

---------

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-08-04 10:26:42 +08:00

135 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 通用可观测性决策图
目标:为 SkillHub 建立独立、通用、可插拔的日志关联、指标和链路追踪基础设施。
当前实现覆盖 HTTP、SkillHub 管理的线程池、Redis Stream 和明确接入的内部 HTTP Client
普通定时任务没有上游 carrier仍是独立后台边界。Redis Stream 上下文只进入 transport
metadata不进入业务模型和业务载荷。
边界:
- Servlet Filter、执行器装饰器、消息 Observation 和明确接入的 Client Builder 负责
建立/恢复上下文。
- Redis Stream Producer 注入、Consumer/Reclaimer 逐条提取;定时任务不继承任意请求。
- 业务代码不读写 MDC不负责创建通用 Span也不负责统计任务生命周期指标。
- 使用 W3C Trace Context日志后端、Metrics 后端和 Trace Exporter 均可替换。
- 上下文是有长度限制的基础设施元数据,不进入业务 payload。
- Collector、Exporter 或 Metrics 后端不可用时,主业务和任务内核继续工作。
必须满足的不变量:
- 每个已纳入本期的执行边界都正确建立作用域并在 `finally` 清理,线程复用不得串号。
- 日志稳定输出 `requestId``traceId``spanId`(存在时);任务执行资源标识不由本期
可观测性自动生成。
- Trace 与 Metrics 可关闭、可替换;关闭后不得改变业务行为。
- 指标只使用低基数维度,业务 ID 不进入标签。
- 采集端不可用必须异步、限时、限队列并 fail-open。
## #1可观测性是否与业务和任务状态机彻底分离
Blocked by: 无
Type: Grilling
### Question
可观测性是否只通过通用执行边界和生命周期信号接入,不进入业务处理器?
### Answer
已确认。可靠任务内核只发布通用生命周期信号;可观测性拦截器把执行资源标识加入日志、
Span 和指标。搜索处理器只处理搜索,不认识 MDC、OpenTelemetry 或 Prometheus。
## #2通用关联身份和传播协议是什么
Blocked by: #1
Type: Research
### Question
如何区分现有 `X-Request-Id`、W3C `traceId/spanId` 和执行资源标识,并跨 HTTP、线程池
边界传播?
### Answer
已确定:
- `requestId` 是 SkillHub 的请求/审计关联标识,不冒充分布式 Trace。
- `traceId/spanId` 由 Tracer 生成,跨进程只使用 W3C `traceparent/tracestate`
- 定时任务或可靠任务的执行资源 ID 只作为当前执行作用域属性,不进入业务 payload。
- HTTP、线程池和消息 carrier 的注入/提取位于基础设施层;消息上下文是 transport
metadata不是任务业务字段。
- 不传播任意 MDC Mapbaggage 默认关闭,任何允许项都必须低敏、限长、显式配置。
- 无效或不可信的公网 Trace Context 按 W3C 规则丢弃,服务端控制采样。
常见方案和候选组合见
[Java / Spring 通用日志关联与链路追踪方案调研](./research/2026-07-31-observability-common-solutions.md)。
## #3采用 Micrometer Observation、OpenTelemetry API/SDK 还是 Java Agent
Blocked by: #2
Type: Research
### Question
哪种组合最适配 Spring Boot 3.2.3,并同时支持无 Collector 运行、可选 OTLP 和稳定日志关联?
### Answer
已选择三模式:
- `none`:不创建应用内 OTel SDK 或 Exporter只保留 Request ID。
- `otel-sdk`:使用 Micrometer Tracing + OTel Bridge配置 OTLP endpoint 时才导出。
- `external-agent`:应用内使用 NOOP Tracer由部署环境提供唯一的外部 Agent。
应用代码只依赖 Micrometer/Observation 边界,不依赖 OTel SDK 或 SkyWalking API。
自动配置测试已证明三种模式互斥,错误的 endpoint/mode 组合会在启动时失败。
## #4如何证明上下文传播、日志输出和故障降级正确
Blocked by: #3
Type: Prototype
### Question
验证线程复用隔离、嵌套作用域、异步任务边界、消息传播、采样、Exporter 超时、
Collector 中断、队列打满和关闭观测能力等场景。调度任务验证不继承请求上下文;
Redis Stream 验证逐条注入、提取和清理。
### Answer
本地原型已证明:
- Request ID Scope 在线程复用、嵌套 Scope、异常退出和 `CallerRunsPolicy` 下均能恢复并
清理。
- Micrometer 手工 Span 和 Observation 均能随 `skillhubEventExecutor` 传播。
- Redis Stream Producer/Consumer 通过通用消息 Observation 传播 W3C Trace Context 和
受控 Request IDReclaimer 从原消息重新提取。
- Scanner 使用 Spring 管理的 `WebClient.Builder` 传播 W3C `traceparent`
- 面向用户配置的 GitLab 外部 Client 不传播 Trace Context。
- `none / otel-sdk / external-agent` 的应用上下文和 Exporter 条件符合设计。
- `@Scheduled` 保持独立后台执行边界Redis Stream/Reclaimer 不继承线程上下文,而是
从每条消息的 transport metadata 恢复。
Collector 中断、日志背压、采样率和关闭行为仍由 `big-main` 精确 SHA 镜像的远端原型验证。
## #5如何形成可部署闭环
Blocked by: #4
Type: Research
### Question
确定 stdout 格式、可选 JSON、Prometheus 或 OTLP Metrics、Trace Exporter、暴露边界、
低基数告警和运维文档。
### Answer
已确定最小交付:
- 文本日志用于本地开发ECS 风格 JSON stdout 用于部署环境。
- JSON 日志只输出白名单关联字段,通过有界非阻塞 AsyncAppender 保护业务线程。
- Trace 可经 OTLP Collector 路由到 SkyWalking需要 SkyWalking 原生能力时改用唯一的
Java Agent。
- Prometheus 继续作为可选 Metrics 后端,不是本期链路关联的前置条件。
部署配置和三模式操作说明写入 `docs/09-deployment.md`;远端实测结果只保存在本地私有
中文报告中。