1. 页面概览
1.1 是什么
数据血缘页面(LineagePage.vue)用于查询 LightFoundry 平台内的数据血缘关系图。它以"节点 + 边"的形式回答"某条数据从哪来、流向哪":data_lineage 表记录 上游(源表/管道/对象/Action)→ 下游(管道/对象/指标/报表)的边,构成四级血缘链路 源 → 管道 → 对象 → 指标 → 报表;Action 写操作本身也是一条血缘边(对象 → 动作),支撑"谁在何时改了什么"的审计与回溯。
页面的查询入口是「节点类型 + 节点 ID(稳定标识)+ 方向 + 深度 + 字段筛选」五元组:节点 ID 是稳定标识——对象填对象名(api_name)、管道填管道名、源填表名、指标填指标名;方向可选 downstream(下游)/ upstream(上游);深度 depth 控制 BFS 展开层数;字段 filter 填列名后仅保留 field_map 涉及该列的边(列级血缘)。查询结果分三部分展示:血缘图(ECharts graph 关系图,节点-边图谱)+ 节点表(类型 / ID / 标签)与边表(上游 from → 下游 to,含字段映射 field_map)。
血缘数据由各写路径自动打点产生:元数据导入、管道执行、Action 执行、指标定义、报表创建、数据集同步成功链都会调用血缘服务写入边(打点失败仅记日志、不阻断主流程)。页面本身是只读查询页,不提供写操作。
1.2 核心价值
| 价值点 | 说明 |
|---|---|
| 双向追踪 | downstream 下溯"数据流向哪"、upstream 上溯"数据从哪来",异常数据一键回溯 |
| 图谱可视化 | ECharts graph 关系图(force 布局,可拖拽/缩放),节点按类型着色、箭头指向下游 |
| 四级链路 | 源 → 管道 → 对象 → 指标 → 报表 全链路可视化 |
| 字段级映射 | 边带 field_map(源列 → 目标列),可看清列级血缘;字段 filter 可按列过滤 |
| 稳定标识 | 对象名/表名/管道名等稳定标识,跨系统可引用(G20) |
| 自动打点 | 各写路径自动记录血缘,无需人工维护 |
| 自动重查 | 方向 / 深度变更自动重新查询,交互流畅 |
1.3 一句话总结
数据血缘页面以"节点 + 边"的图模型回答数据的来龙去脉,支撑影响分析与审计回溯。
2. 访问入口
2.1 路由与菜单
| 项 | 值 |
|---|---|
| 路由 path | /foundry/lineage |
| 路由 name | FoundryLineage |
| meta.title | Foundry 数据血缘 |
| 侧边栏入口 | FoundryLayout 侧边栏「数据血缘」(位于「数据源」之后、「数据质量」之前) |
| 前端源码 | action/web/src/views/LineagePage.vue |
| API 客户端 | action/web/src/api/client.js(baseURL /api/v1,30s 超时) |
路由注册见 action/web/src/router/index.js:
{ path: 'lineage', name: 'FoundryLineage', component: LineagePage, meta: { title: 'Foundry 数据血缘', requiresAuth: true } },
侧边栏入口见 action/web/src/views/FoundryLayout.vue 的 menuItems 数组 { path: '/foundry/lineage', label: '数据血缘' }。
2.2 认证与权限
- 路由
requiresAuth: true:未登录访问被前端路由守卫拦截跳转登录页。 - 后端
GET /lineage挂在 protected 组:authMiddleware校验Authorization: Bearer <token>,缺失/非法返回 401{"code":"AUTH_ERROR","error":"..."}。 - Token 类型:
aip_token。client.js 请求拦截器自动读取 localStorage 的aip_token并附加Bearer ${token};401 响应统一移除 token 并跳转/login(不在登录页时)。 - 角色限制:血缘查询本身无额外对象级权限过滤(血缘边数据为全局只读查询);但血缘数据的产生受各写路径的对象级安全约束。
- 404 排错提示:若访问
/foundry/lineage404,检查 Foundry 后端(18081)是否启动、GET /lineage路由是否注册(server.go 中protected.GET("/lineage", s.handleLineageTrace))。
2.3 端口与 API 前缀
- Foundry 后端端口:18081。
- API 前缀:
/api/v1(client.js baseURL 为/api/v1,Vite 代理/api→ 18081)。 - 血缘查询端点:
GET /api/v1/lineage。 - 对象候选辅助端点:
GET /api/v1/ontology/objects(type=object 时加载对象名下拉候选)。
3. 界面布局
+--------------------------------------------------------------+
| 数据血缘 |
+--------------------------------------------------------------+
| [alert 操作结果提示条(可关闭)] |
+--------------------------------------------------------------+
| [血缘查询卡片] |
| 节点类型* | 节点 ID(稳定标识)* | 方向 | 深度 depth | [查询] |
| (type=object 时 ID 右侧出现对象候选下拉) |
| 提示:节点 ID 为稳定标识——对象填对象名(api_name)、管道填管道名、 |
| 源填表名、指标填指标名。方向 / 深度变更会自动重新查询; |
| 字段 filter 填列名后仅保留 field_map 涉及该列的边。 |
+--------------------------------------------------------------+
| [血缘图卡片] 血缘图(N 节点 / M 边) |
| ECharts graph(force 布局,节点按类型着色、箭头指向下游,可拖拽/缩放) |
+--------------------------------------------------------------+
| [节点卡片] 节点(N) |
| # | 类型 | ID | 标签 |
+--------------------------------------------------------------+
| [血缘边卡片] 血缘边(N,方向 from → to) |
| # | 上游 from | 下游 to | 字段映射 field_map |
+--------------------------------------------------------------+
| [空结果提示](queried 但 result 为 null 时) |
| 请填写节点类型与 ID 后点击"查询"。 |
+--------------------------------------------------------------+
各板块职责:
- 页头:标题「数据血缘」。
- 操作结果提示条:查询失败 / 对象候选加载失败以 alert 呈现,右侧「关闭」按钮清空。
- 血缘查询卡片:五元组查询表单——节点类型下拉、节点 ID 输入框(+ 对象候选下拉)、方向下拉、深度数字输入框、字段 filter 输入框、查询按钮。
- 血缘图卡片:ECharts graph(force 布局)把
nodes/edges渲染成节点-边图谱,节点按 type 着色、箭头指向下游、悬停显示字段映射;空节点显示提示(详见 4.3)。 - 节点表格:展示查询命中的节点集合(类型徽章按 type 着色 + ID + 标签),空集显示「无节点」。
- 边表格:展示血缘边(from → to 方向),每行含上游节点、下游节点、字段映射 field_map(JSON 文本,空显示
-),空集显示「无血缘边(该节点在此方向没有关联关系)」。 - 空结果提示:已查询但 result 为 null(查询失败被清空)时提示填写节点类型与 ID。
4. 交互元素详解
4.1 查询表单
| 元素 | 含义 | 必填/默认 | 操作效果 | 触发的后端调用 |
|---|---|---|---|---|
| 节点类型下拉 | 查询节点类型 | 必填,默认 object;选项:source(源表)/ pipeline(管道)/ object(本体对象)/ metric(指标)/ report(报表)/ action(动作) | 切换触发 onTypeChange:type=object 且 id 为空时自动填入第一个对象名 | 无(切换本身不发请求) |
| 节点 ID 输入框 | 稳定标识 | 必填,placeholder「对象名 / 表名 / 管道名...」,回车(@keyup.enter)触发查询 | 写入 form.id | 查询时 GET /api/v1/lineage?type=&id=&direction=&depth= |
| 对象候选下拉 | type=object 时显示 | 可选,选项来自 GET /ontology/objects | 选择后把对象名填入 form.id | 页面加载时 GET /api/v1/ontology/objects |
| 方向下拉 | 追踪方向 | 默认 downstream(下游);选项:downstream / upstream | 变更自动重查(存在历史查询时) | GET /api/v1/lineage |
| 深度 depth | BFS 展开层数 | type=number,min=1,默认 10 | 变更自动重查(存在历史查询时) | GET /api/v1/lineage |
| 字段 filter(可选) | 列级血缘过滤:仅保留 field_map 涉及该列(作为源列键或目标列值)的边 | 选填;placeholder「列名,如 amount」;回车触发查询 | 非空时在查询参数中加 field(映射后端 TraceField,列级影响分析) | GET /api/v1/lineage?field=<列名> |
| 「查询」按钮 | 提交查询 | 查询中禁用并显示「查询中...」 | handleQuery:id 为空提示「请填写节点 ID(对象名/表名/管道名等稳定标识)」 | GET /api/v1/lineage |
4.2 结果表格
| 元素 | 含义 |
|---|---|
| 节点表 # | 序号(1 起) |
| 节点表 类型 | 类型徽章,着色:source 黄、pipeline 蓝、object 青绿、metric 紫、report 红、action 灰 |
| 节点表 ID | 稳定标识(对象名/表名/管道名/指标名/报表名/动作名) |
| 节点表 标签 | n.label || n.id,label 缺失时退化为 ID |
| 边表 # | 序号 |
| 边表 上游 from | 上游节点类型徽章 + 展示名(label || id) |
| 边表 下游 to | 下游节点类型徽章 + 展示名 |
| 边表 字段映射 field_map | JSON.stringify(fm),空对象/无映射显示 - |
4.3 血缘图(ECharts graph)
结果就绪且节点数 > 0 时,在节点表上方渲染一张 ECharts graph 关系图(renderGraph):
| 元素 | 说明 |
|---|---|
| 容器 | .lineage-graph,宽 100%、高 420px(ECharts 需显式高度);节点数 0 时显示「无节点,无法渲染血缘图。」 |
| 节点 | graph.nodes 映射为图节点,id = type|id(去重键)、name = label || id;按 type 分成 6 个 category 并着色(source 黄 / pipeline 蓝 / object 绿 / metric 紫 / report 红 / action 灰,与表格 type 徽章口径一致),symbolSize=34 |
| 边 | graph.edges 映射为 links(source=from、target=to),edgeSymbol=['none','arrow'] 箭头指向下游;lineStyle.curveness=0.08 |
| 布局 | layout: 'force'(repulsion:260、edgeLength:130、gravity:0.08);roam:true 支持滚轮缩放/平移,draggable:true 支持拖拽节点 |
| 交互 | 悬停节点显示 label || id;悬停边显示 上游 → 下游 与 字段映射 field_map;emphasis.focus='adjacency' 高亮相邻节点/边 |
| 图例 | 底部图例按 6 类节点类型列出 |
| 生命周期 | watch(result) 在结果变化后 nextTick 重渲染;结果被清空(查询失败)时 dispose 实例;window resize 触发 resize();组件卸载移除监听并 dispose |
依赖说明:使用项目已有依赖 echarts(action/web/package.json 的 "echarts": "^6.1.0"),未新增任何第三方依赖;GraphChart 在共享注册表 action/web/src/utils/echartsRegistry.js 中按需注册(与 Bar/Line/Pie… 同处,属既有按需引入机制的扩展)。该注册表被 ChartRender.vue / Notebook / 报表等复用,新增 GraphChart 为纯增量、不影响其它图表类型。
5. 后端关联
5.1 API 客户端
client.js 为共享 axios 实例:
- baseURL:
/api/v1 - timeout:30000(30 秒)
- 请求拦截器:从 localStorage 读
aip_token,附加Authorization: Bearer ${token} - 响应拦截器:401 时移除
aip_token/aip_username并跳转/login
本页使用(apiClient 直接调用):
apiClient.get('/lineage', { params: { type, id, direction, depth } })apiClient.get('/ontology/objects')
5.2 端点表
| 方法 | 路径 | 请求参数 | 响应要点 |
|---|---|---|---|
| GET | /api/v1/lineage | query: type(必填)、id(必填)、direction(upstream|downstream,默认 downstream)、depth(<=0 用默认上限防环)、field(可选,列名过滤) | {code:0, data:{nodes:[...], edges:[...]}} |
| GET | /api/v1/ontology/objects | — | {code:0, data:[{object_type:{name,...}, ...}]}(对象候选) |
5.3 响应结构
血缘查询响应:
{
"code": 0,
"data": {
"nodes": [
{ "type": "source", "id": "orders", "label": "orders" },
{ "type": "object", "id": "order", "label": "order" },
{ "type": "metric", "id": "order_amount", "label": "order_amount" }
],
"edges": [
{
"from": { "type": "source", "id": "orders", "label": "orders" },
"to": { "type": "object", "id": "order", "label": "order" },
"field_map": { "order_id": "order_id", "amount": "amount" }
},
{
"from": { "type": "object", "id": "order", "label": "order" },
"to": { "type": "metric", "id": "order_amount", "label": "order_amount" },
"field_map": { "amount": "total" }
}
]
}
}
对象候选响应:
{ "code": 0, "data": [ { "object_type": { "name": "order", "api_name": "order", ... }, ... } ] }
前端 fetchObjects 取 objectTypes.value = data.data || [],再映射 objectNames = objectTypes.map(item => item.object_type?.name).filter(Boolean)。
5.4 关联模块表
| 后端包 | 职责 |
|---|---|
products/foundry/lineage | LineageService:Record 打点(幂等)、Trace/TraceField/GetFullLineage 图展开、便捷打点方法 |
products/foundry/server(pipeline_handlers.go) | handleLineageTrace:解析 query 参数、调 Trace 或 TraceField、{code:0,data} 包装 |
products/foundry/pipeline | 管道执行打点(RecordSourceToPipeline / RecordPipelineToObject) |
products/foundry/metric | 指标定义打点(RecordObjectToMetric) |
products/foundry/report | 报表创建打点(RecordMetricToReport) |
products/foundry/writepath | Action 执行打点(RecordActionWrite) |
products/foundry/sync | 同步成功链打点(RecordFieldMapping source→dataset) |
products/foundry/ontology | 对象类型查询(/ontology/objects 候选下拉) |
5.5 关键机制
图模型:血缘图 LineageGraph{Nodes, Edges}。节点 Node{Type, ID, Label}(Type/ID 为稳定标识),边 Edge{From, To, FieldMap}(From=上游,To=下游,数据流方向)。
BFS 展开(Trace):从起始节点沿 direction 逐层 BFS,层数受 depth 限制(depth<=0 用默认上限 defaultTraceDepth=10 防环);nodeSeen 按 type|id 去重防环。direction 为 upstream 时从 downstream_type/id 查直接上游边,为 downstream 时从 upstream_type/id 查直接下游边。
六类节点类型:source(源表)/ pipeline(管道)/ object(本体对象)/ metric(指标)/ report(报表)/ action(动作),ValidType 校验,非法类型返回校验错误。
字段级过滤(TraceField):field query 参数存在时,仅保留 field_map 涉及该列的边(作为源列键或目标列值),是列级影响分析(支撑 lineage?field=amount);为空时等价于 Trace。
打点幂等:Record 写入前查重——同 upstream/downstream 组合已存在时,field_map 非空则更新、否则保持原样,均不重复插入。
自动重查:前端 watch([direction, depth]) 在 lastQuery 存在时自动调用 handleQuery 重新查询,无需手动点「查询」。
6. 核心流程详解
6.1 查询血缘主流程
- 页面加载(onMounted)调用
fetchObjects():GET /ontology/objects加载对象候选(失败仅提示「加载对象候选失败」,不阻断功能)。 - 选择节点类型(默认 object);type=object 且 id 为空时自动填入第一个对象名。
- 填写节点 ID(对象名/表名/管道名等稳定标识),可回车触发查询。
- 点击「查询」(
handleQuery):id 为空先提示;组装 params{type, id: id.trim(), direction: direction || 'downstream', depth: depth || 10},若「字段 filter」非空则追加field(后端TraceField只保留 field_map 涉及该列的边);GET /lineage。 - 成功:
result.value = data.data || {nodes:[], edges:[]},记录lastQuery,queried = true,渲染血缘图、节点表与边表。 - 失败:alert「血缘查询失败:错误详情」,
result.value = null(空结果提示区出现)。 - 之后修改方向或深度:watch 检测
lastQuery存在则自动重查。
6.2 对象候选选择分支
- 节点类型为 object 时,ID 输入框右侧出现对象候选下拉(
GET /ontology/objects加载)。 - 下拉值为对象名(
object_type.name);选择后把对象名写入form.id。 - 候选加载失败(网络/权限)不影响查询功能,仅顶部提示。
6.3 血缘数据从哪来(打点链路)
| 打点时机 | 便捷方法 | 边 |
|---|---|---|
| 元数据导入 / 管道执行成功 | RecordSourceToPipeline | source → pipeline |
| 管道执行成功且目标对象映射存在 | RecordPipelineToObject | pipeline → object |
| 指标定义创建 | RecordObjectToMetric | object → metric |
| 报表创建 | RecordMetricToReport | metric → report |
| Action 写操作执行 | RecordActionWrite | object → action |
| 同步引擎成功链 | RecordFieldMapping | source → dataset |
打点失败仅记日志、不阻断主流程(对齐 pipeline 包约定)。
7. 权限与安全
7.1 认证
- JWT Bearer 认证(
aip_token);401 统一跳转登录页。 - 后端
authMiddleware双路径:lfk_前缀走 API Key 校验,否则走securityService.ParseToken解析 JWT。
7.2 数据级安全
- 血缘查询为全局只读,无额外 RLS/CLS 过滤(血缘边的可见性与对象级查询解耦)。
- 血缘数据本身的产生受写路径安全约束(Action 执行需对象级写权限等),故血缘图反映的是"被授权的写操作"留下的痕迹。
field_map中的列名来自各写路径的映射配置,页面仅做 JSON 展示,不做执行。
7.3 写操作防护
本页为纯只读页,无写操作;查询参数 type/id/direction/depth 均只读校验(type 非法返回校验错误,depth<=0 用默认上限防环)。
8. 常见问题与排错
8.1 查询结果为空(有节点、无边)
- 现象:节点表有起始节点,但边表显示「无血缘边(该节点在此方向没有关联关系)」。
- 原因:该节点在此方向没有已打点的边;或方向选反(如应查 upstream 却选了 downstream);或打点链路未覆盖该节点类型。
- 排查步骤:
- 确认方向语义:想查"数据从哪来"选 upstream,想查"数据流向哪"选 downstream;
- 确认节点 ID 与打点时的稳定标识完全一致(大小写、命名规则);
- 确认该节点的打点时机已发生(如对象指标定义是否创建、管道是否成功执行、同步是否成功);
- 用
GET /api/v1/lineage?field=列名做字段级过滤,排查是否只是 field_map 为空导致边无字段映射。
8.2 提示「血缘查询失败:invalid lineage type」
- 现象:查询失败,错误为「invalid lineage type ...」。
- 原因:节点类型不在合法集合(source/pipeline/object/metric/report/action)内。
- 排查步骤:确认前端下拉选择的是合法类型(typeOptions 六项);若手工构造 API 请求,检查 type 参数拼写;depth 传非数字时也会被忽略(strconv.Atoi 失败回退 0 → 默认 10)。
8.3 对象候选下拉为空
- 现象:type=object 时对象候选下拉没有选项,且顶部提示「加载对象候选失败」。
- 原因:
GET /ontology/objects失败(后端未启动、路由未注册、或对象类型表为空)。 - 排查步骤:
- 打开 DevTools Network 确认
/api/v1/ontology/objects的响应状态; - 确认 Foundry 后端 18081 已启动、
/ontology/objects路由已注册; - 确认平台已创建对象类型(本体工作台)——候选来自对象类型列表;
- 候选加载失败不阻断功能:手动输入对象名(api_name)仍可查询。
8.4 深度很大时响应慢 / 图过大
- 现象:depth 调大后查询变慢,或返回节点/边非常多。
- 原因:BFS 按 depth 层展开,深链路的节点数指数增长;depth<=0 时会用默认上限 10 兜底防环。
- 排查步骤:从较小 depth(如 3~5)开始逐层加大;优先用方向 + 小深度定位关键链路;需要全链路时再用大 depth。
9. 已知缺陷与边界
| 缺陷/边界 | 说明 |
|---|---|
| 字段级血缘为超集 | TraceField 按全部边展开后过滤字段边,结果可能包含经"非字段边"到达深层的字段边(列级精准链路待收敛) |
| 字段过滤 UI(已于 2026-09-13 补齐) | 查询表单已暴露「字段 filter」输入框,非空时下发 field 查询参数(后端 TraceField,lineage/service.go:345-373)。边界:输入需与 field_map 中的列名完全一致(大小写敏感、无补全);列级血缘为超集(见上行) |
| 血缘边无权限过滤 | 查询不区分当前用户的可见性,返回全量血缘边 |
| 节点无去重展示合并 | 同一 type|id 出现多次时节点表按查询结果顺序展示,无合并折叠 |
| 打点失败静默 | 各写路径打点失败仅记日志,页面无法感知缺失的边 |
| 图谱可视化(已于 2026-09-13 补齐) | 已用项目既有依赖 echarts(package.json 的 echarts:^6.1.0,未新增依赖)渲染 ECharts graph(force 布局)血缘图,节点按类型着色、箭头指向下游、悬停显示字段映射;GraphChart 在共享 echartsRegistry.js 按需注册。边界:无「节点/边双向高亮筛选、按层级分层布局、导出图片到服务端」等高级图能力;节点极多时 force 布局渲染开销较高 |
| 候选加载失败仅提示 | /ontology/objects 失败不阻断查询,但对象下拉不可用 |
10.2 后端文件
action/products/foundry/lineage/service.go(Trace / TraceField / GetFullLineage / Record)action/products/foundry/lineage/model.go(data_lineage 表结构)action/products/foundry/server/pipeline_handlers.go(handleLineageTrace)action/products/foundry/server/server.go(GET /lineage 路由注册)
10.3 项目文档
action/wiki/design/design_foundry.md(§3.4 血缘设计)action/wiki/upgrade-v5/dev-story/stage-1.md(血缘打点接入说明)action/wiki/frontend-intro-v5/markdown/foundry/index.md(页面索引)
10.4 相邻页面
- 管道构建(pipelines) — 管道执行打点血缘边的来源
- 数据质量(quality) — 质量问题可结合血缘回溯根因
- 数据同步(sync) — 同步成功自动打点 source→dataset 边
- 数据源(data-sources) — 元数据导入参与血缘链路
- 数据集(datasets) — 数据集作为血缘下游节点