Homepage 集成 Pangolin:站点、资源与流量统计 Widget 配置与实现原理指南
【免费下载链接】homepageA highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.项目地址: https://gitcode.com/GitHub_Trending/ho/homepage
Pangolin 是一款支持 Docker 部署的反向代理与隧道管理平台,在 Homepage 中可以通过pangolin类型 Widget 直接展示某个组织(Organization)下的站点在线状态、资源与目标健康度以及累计流量。本文基于 官方 Widget 文档 并结合仓库源码(widget.js、component.jsx、组件测试 等),完整讲解配置方法、字段含义、统计口径与底层认证/代理实现,帮助你在自托管或云托管 Pangolin 上快速落地这块状态面板。
Widget 功能概览
pangolinWidget 面向一个组织(Organization)维度展示四类核心指标:
- Sites(站点):在线站点数 / 站点总数;
- Resources(资源):健康资源数 / 资源总数;
- Targets(目标):健康目标数 / 目标总数;
- Traffic(流量):所有站点的累计流量统计,并可细分为 In(入站)与 Out(出站)。
其中「资源健康」的判定规则为:一个资源只要其至少一个目标处于健康状态,即视为健康;如果该资源没有任何目标,同样视为健康。这一规则与 component.jsx 中的过滤逻辑完全一致:
const resourcesHealthy = resources.filter( (r) => r.targets?.some((t) => t.healthStatus !== "unhealthy") || !r.targets?.length, ).length;也就是说,只有当资源存在目标且所有目标都不健康时,该资源才被计入不健康。
快速开始:最小配置示例
在 Homepage 的services.yaml(参考 docs/configs/services.md)中为服务添加如下 Widget 配置:
widget: type: pangolin url: https://api.pangolin.net key: your-api-key org: your-org-id| 参数 | 必填 | 说明 |
|---|---|---|
type | 是 | 固定为pangolin |
url | 是 | PangolinAPI 服务地址(通常是https://api.你的域名,而非 Web 控制台地址) |
key | 是 | 具备相应权限的 API Key(见下文「API Key 配置」) |
org | 是 | 目标组织 ID,用于定位站点与资源数据 |
提示:
key、url等敏感字段仅在后端代理请求时使用,前端渲染前会被脱敏处理,详见 widget-helpers.js 中的cleanWidgetGroups。
获取组织 ID(org)
组织 ID 不需要在配置里手工维护——直接登录 Pangolin Web 控制台后从浏览器地址栏 URL 中读取即可。登录后的地址形如:
https://app.pangolin.net/{org-id}/...其中路径中紧随域名后的第一段{org-id}就是本 Widget 需要的org参数值。
API Key 配置
Widget 通过 Pangolin 的 Integration API 读取数据,因此需要预先创建 API Key。创建时至少需要勾选以下两项权限:
- List Sites:读取站点列表(用于站点在线状态与流量统计);
- List Resources:读取资源列表(用于资源与目标的健康统计)。
自托管部署(Self-Hosted)需要额外注意:Pangolin 的 Integration API 默认不开启,必须在 Pangolin 自身的配置中启用 Integration API 后,API Key 才会生效;云端托管版无需此步骤。
可显示字段(fields)与默认值
该 Widget 支持以下六个字段,最多同时显示 4 个:
["sites", "resources", "targets", "traffic", "in", "out"]- 不配置
fields时,默认显示sites、resources、targets、traffic四项; - 配置的字段超过 4 个时,只会保留前 4 个。
上述默认值与截断行为在 component.jsx 中有明确实现:
const MAX_ALLOWED_FIELDS = 4; if (!widget.fields) { widget.fields = ["sites", "resources", "targets", "traffic"]; } else if (widget.fields?.length > MAX_ALLOWED_FIELDS) { widget.fields = widget.fields.slice(0, MAX_ALLOWED_FIELDS); }对应测试 component.test.jsx 也验证了「传入 5 个字段时最终只剩前 4 个」的截断逻辑。示例如下:
widget: type: pangolin url: https://api.pangolin.net key: your-api-key org: your-org-id fields: - sites - resources - in - out各字段的统计口径与换算规则
结合 component.jsx,六个字段的精确统计口径如下:
| 字段 | 统计口径 | 展示形式 |
|---|---|---|
sites | 在线站点数 / 站点总数,即sites.filter(s => s.online).length比上sites.length | 在线 / 总数 |
resources | 健康资源数 / 资源总数(健康判定见上文) | 健康 / 总数 |
targets | 健康目标数 / 目标总数,遍历所有资源的targets汇总 | 健康 / 总数 |
traffic | 所有站点megabytesIn与megabytesOut之和(按字节显示) | 格式化字节数 |
in | 所有站点megabytesIn之和 | 格式化字节数 |
out | 所有站点megabytesOut之和 | 格式化字节数 |
值得注意的细节是流量单位的换算:Pangolin API 返回的megabytesIn/megabytesOut以MB(兆字节)为单位,而 Homepage 组件在渲染前统一乘以1_000_000转换为字节,再交给多语言格式化函数t("common.bytes", ...)展示,见 component.jsx:
const trafficIn = sites.reduce((sum, s) => sum + (s.megabytesIn || 0), 0) * 1_000_000; const trafficOut = sites.reduce((sum, s) => sum + (s.megabytesOut || 0), 0) * 1_000_000; const trafficTotal = trafficIn + trafficOut;组件测试 同样按该换算断言:输入 1MB 与 3MB 入站、2MB 与 4MB 出站时,traffic展示为10_000_000字节。
界面文案(Sites / Resources / Targets / Traffic / In / Out)由多语言文件定义,例如英文翻译位于 public/locales/en/common.json 的pangolin命名空间下,中文等其他语言在对应 locale 目录中同样可用。
底层实现:API 映射与数据请求链路
API 端点映射
Widget 的 API 定义在 src/widgets/pangolin/widget.js,它声明了基础 URL 模板与两个数据端点:
const widget = { api: "{url}/v1/{endpoint}", proxyHandler: credentialedProxyHandler, mappings: { sites: { endpoint: "org/{org}/sites", }, resources: { endpoint: "org/{org}/resources?pageSize=200", }, }, };可以看到:
- 所有请求统一走
/v1/前缀,拼接后实际请求为{url}/v1/org/{org}/sites与{url}/v1/org/{org}/resources?pageSize=200; resources端点固定带上pageSize=200分页参数,最多取回 200 条资源;{url}与{org}占位符分别由配置中的url、org字段填充。
组件在加载时会通过useWidgetAPI同时请求sites与resources两个端点(见 component.jsx),任一请求失败都会在容器中呈现错误状态;两数据均未返回时先渲染占位区块。
Bearer Token 认证
pangolin指定使用credentialedProxyHandler(src/utils/proxy/handlers/credentialed.js)。在该处理器中,pangolin被归类到使用Bearer Token认证的 Widget 名单中(credentialed.js):
} else if ( [ "argocd", "authentik", "cloudflared", ... "pangolin", ... ].includes(widget.type) ) { headers.Authorization = `Bearer ${widget.key}`; }即每次请求都会携带Authorization: Bearer {key}请求头,key即配置中的 API Key。这也解释了为什么 API Key 必须包含 List Sites 与 List Resources 权限——只有具备这两项权限,两个端点才能正常返回数据。
完整请求链路
从配置到界面渲染,完整的数据流为:
services.yaml中的 Widget 配置被加载并注入useWidgetAPI(use-widget-api.js);- 前端向 Homepage 自身代理接口发起请求;
credentialedProxyHandler根据widget.type === "pangolin"注入 Bearer Token,拼接出{url}/v1/org/{org}/...完整 URL 后转发给 Pangolin API(http.js 执行实际 HTTP 调用);- 响应数据经过 validate-widget-data.js 的基础校验后回传前端;
- component.jsx 消费数据并计算上述各项统计,最终由
Container/Block组件渲染为服务卡片上的状态块。
组件通过 src/widgets/components.js 中的dynamic(() => import("./pangolin/component"))按需懒加载,不影响其他 Widget 的首次加载性能。
常见问题排查
- 接口返回 401/403:多为 API Key 权限不足或无效。请确认 Key 已勾选List Sites与List Resources;自托管环境请先确认已启用Integration API。
- 显示「资源全部健康但实际有故障」:检查目标健康判定——资源无任何目标(
targets为空数组)时会被直接视为健康,这是设计规则而非 Bug(component.jsx)。 - 数据不刷新或为空:确认
url填写的是 PangolinAPI 地址(api.*子域),且网络可达;resources端点最多拉取 200 条资源,超大规模组织可关注是否存在截断。 - 字段顺序与预期不符:
fields数组最多保留前 4 项,超出部分会被静默丢弃,请按展示优先级排序。
小结
通过pangolinWidget,你可以把 Pangolin 组织的站点在线率、资源/目标健康度与出入站流量直接聚合到 Homepage 服务面板,实现「网络基础设施状态一屏总览」。配置只需type、url、key、org四个字段,配合正确的 API Key 权限即可运行;其统计口径、Bearer 认证与端点映射均有明确的源码实现可查(widget.js、component.jsx、credentialed.js),便于在出现异常时快速定位问题。更多服务 Widget 的完整清单见 docs/widgets/services/index.md。
【免费下载链接】homepageA highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.项目地址: https://gitcode.com/GitHub_Trending/ho/homepage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考