上一篇展示了 Task Manager 调度的一种用途——驱动 Alerting Rule 周期执行。这一篇进入 Reporting,核心问题是:headless Chromium 渲染、报表任务队列、CSV 导出走的是搜索而非截图。

两条完全不同的生成路径

Kibana Reporting 对外提供两类产物,但底层实现路径截然不同:

1
2
3
4
5
6
7
8
类型          触发源         生成方式                存储
─────────────────────────────────────────────────────────────────
PDF / PNG Dashboard headless Chromium .kibana + blob
Visualize 截图 → PDF 合并
Canvas

CSV Saved Search ES scroll / search_after .kibana + blob
Discover 纯数据,无渲染

CSV 路径不涉及浏览器,CPU 和内存消耗远低于 PDF/PNG 路径。两条路径都通过 Task Manager 异步执行,请求方通过轮询获取任务状态。

headless Chromium 渲染链路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
用户点击 "Generate PDF"


Kibana server 接收请求
→ 创建 reporting job Saved Object (status: pending)
→ 提交 Task Manager task


Task Manager 分配 worker 执行 task


ReportingPlugin 启动 headless Chromium
├── 以 Kibana 内部 URL 导航到目标 Dashboard
│ URL 携带 session cookie (kibana_reported_user)
├── 注入 waitForRenderComplete hook
│ 轮询 window.__renderComplete === true
├── 截图(每个 panel 或整页)
└── puppeteer-core → PDF 合并 / PNG 输出


将结果写入 .kibana Saved Object + 外部存储(默认本地 FS 或 S3)
更新 job status: completed

waitForRenderComplete 是 Kibana 客户端在所有 Embeddable 渲染完成后设置的全局标志,Chromium 端通过 page.evaluate() 轮询该标志,超时(默认 60 秒)则报错。

CSV 导出链路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
用户触发 "Export as CSV"(来自 Discover 或 Saved Search


Kibana server 接收请求
→ 读取 Saved Searchindex pattern + query + filter + sort
→ 创建 reporting job Saved Object (status: pending)
→ 提交 Task Manager task


Task Manager 分配 worker


CsvSearchSourceExportType.runTask()
├── 构建 SearchSource(index, query, fields, sort
├── 调用 ES search_after 分页
│ 每页 500 行(xpack.reporting.csv.maxSizeBytes 控制总量上限)
├── 逐行转换为 CSV(含表头、日期格式化、值转义)
└── 写入 blob 存储


job status: completed,客户端 download link 可用

CSV 无 Chromium 依赖,在内存受限环境中是安全替代方案。字段顺序来自 Saved Search 中配置的列顺序,未配置时按 index pattern 字段顺序输出。

报表任务的生命周期状态

1
2
pending → processing → completed
└→ failed (可重试)

状态存在 .kibana 索引中 type=reporting-job 的 Saved Object 字段 statuscompleted 后 blob 可下载;failedoutput.content 字段含错误信息。

存储后端

配置项 默认值 说明
xpack.reporting.encryptionKey 随机 加密报表 content
xpack.reporting.kibanaServer.* 继承主配置 Chromium 回连的 Kibana URL
xpack.reporting.capture.timeouts.waitForElements 30000ms 等待 DOM 元素超时
xpack.reporting.capture.timeouts.renderComplete 60000ms 等待渲染完成超时
xpack.reporting.csv.maxSizeBytes 10485760 (10MB) CSV 最大字节数

8.x 默认将报表文件存在 Kibana 本地文件系统的临时目录,生产环境建议配置 S3 外部存储(xpack.reporting.s3.*)以支持多实例共享。

实验:生成 PDF 并观察 Task Manager

以下实验需要 Kibana 8.x,且已有至少一个 Dashboard。

第一步:触发 PDF 报表生成

1
2
3
4
POST kbn:/api/reporting/generate/printablePdfV2
{
"jobParams": "(browserTimezone:Asia/Shanghai,layout:(dimensions:(height:768,width:1280),id:preserve_layout),objectType:dashboard,relativeUrls:!('/app/dashboards#/view/<dashboard_id>?_g=()'),title:'My Dashboard')"
}

返回字段 path 即报表任务路径,例如 /api/reporting/jobs/download/kjo_...,以及 job.id

第二步:轮询状态

1
GET kbn:/api/reporting/jobs/info/<job_id>

status 字段从 pendingprocessingcompletedcompleted 时出现 output.size

第三步:查看 Task Manager 任务

1
2
3
4
5
6
GET .kibana_task_manager/_search
{
"query": {
"term": { "task.taskType": "report:printablePdfV2" }
}
}

任务文档包含 task.runAttask.attemptstask.state 字段。报表任务是一次性任务(task.schedule 为空),与 Alerting 的循环任务不同。

第四步:下载报表

1
GET kbn:/api/reporting/jobs/download/<job_id>

响应 Content-Type 为 application/pdf,Content-Disposition 含文件名。

映射到内部对象

实验观测 内部对象
POST /generate 响应 .kibana 中 type=reporting-job 的 Saved Object 被创建
Task Manager 执行报表 .kibana_task_manager 中 taskType=report:* 的 task 文档
PDF/PNG 文件内容 Kibana 本地 FS 或 S3(xpack.reporting.output.*
CSV 数据来源 ES search_after,不经过 Chromium
渲染超时 waitForRenderComplete 全局标志超时,job 状态变 failed

模式提炼

Kibana Reporting 的设计原则是"报表即异步任务"。同步生成 PDF 对 Kibana 服务器影响过大,异步队列让用户可以提交后离开、稍后下载,且多个报表任务可以在容量范围内并发执行。

headless Chromium 路径的本质是"让 Kibana 自己访问自己":Chromium 以内部 URL 导航,携带服务账户 cookie,等待客户端 JavaScript 完成渲染后截图。这意味着报表中看到的内容与浏览器中看到的内容完全一致,包括所有 Embeddable 插件的渲染效果。

CSV 路径绕过渲染层,直接从 Elasticsearch 拉取原始数据,适合数据分析场景而不适合视觉报告。

工程迁移表

需求 方案
定时发送 PDF 报表给管理层 Reporting + Alerting 联动(Alerting action 调用 reporting API),或外部 cron 调用 API
导出百万行数据 CSV 导出,调大 csv.maxSizeBytes;超出限制需分批
多 Kibana 实例共享报表文件 配置 S3 外部存储
Chromium 内存不足导致报表失败 减少 Dashboard panel 数量;或调高 capture.browser.chromium.inspect 选项进行诊断
报表中中文字符乱码 确保 Kibana server 的字体配置包含 CJK 字体(xpack.reporting.capture.browser.chromium.env.LANG

常见误解

CSV 导出与 PDF 导出共用同一个"报表"入口,但内部实现完全不同。CSV 不使用 Chromium,也不受 capture.timeouts 影响;超时或截图失败的排查方向不适用于 CSV。

Kibana Reporting 的 PDF 中看不到 panel 的原因通常是 waitForRenderComplete 超时,而不是 Chromium 问题。增大 renderComplete 超时是第一步排查手段。

报表 Saved Object 与实际文件内容是分开存储的。删除 Saved Object 不会释放文件系统空间;8.x 提供 xpack.reporting.cleanupInterval 自动清理过期报表。

练习

  1. 通过 API 触发 CSV 报表,在 .kibana_task_manager 中确认 task 类型与 PDF 报表的 task 类型不同。
  2. 修改 xpack.reporting.csv.maxSizeBytes 为 1024(1KB),触发一个结果集较大的 CSV,观察 job 状态和 output.content 中的截断提示。
  3. 在 Dashboard 中添加一个渲染较慢的自定义 Vega panel,观察 PDF 生成时间与 waitForRenderComplete 超时的关系。
  4. 查询 .kibana/_search 过滤 type=reporting-job,对比 pending 和 completed 状态的 Saved Object 字段差异。

系列导航

参考资料

  1. Elastic 官方文档,Kibana Reporting - https://www.elastic.co/guide/en/kibana/current/reporting-getting-started.html
  2. Elastic 官方文档,Reporting settings in Kibana - https://www.elastic.co/guide/en/kibana/current/reporting-settings-kb.html
  3. Elastic 官方文档,Reporting API - https://www.elastic.co/guide/en/kibana/current/reporting-api.html
  4. Kibana 源码,x-pack/plugins/reporting/server/export_types/ - https://github.com/elastic/kibana