跳到主要内容

显示 API 实现总结

概述

此实现为 OpenSynaptic 添加了自发现可视化系统,替换了 web_user 和 tui 中的硬编码显示逻辑,采用基于插件的显示提供程序。

日期:2026-M03-30
状态:完成
向后兼容性:✅ 已维护(内置部分仍可工作)


修改内容

1. 核心显示 API

文件src/opensynaptic/services/display_api.py(新建)

提供核心模块:

  • DisplayProvider(自定义显示提供程序的抽象基类)
  • DisplayRegistry(管理所有已注册提供程序的全局单例)
  • DisplayFormat(输出格式枚举:JSON、HTML、TEXT、TABLE、TREE)
  • register_display_provider()(注册新提供程序)
  • render_section()(呈现特定部分)
  • collect_all_sections()(收集所有部分)
  • get_display_registry()(访问全局注册表)

主要特性

  • 使用 RLock 的线程安全注册表
  • 按类别和优先级过滤提供程序
  • 支持 5 种输出格式
  • 可扩展设计,支持新格式

2. TUI 集成

文件src/opensynaptic/services/tui/main.py(已更新)

更改内容:

  • 添加显示 API 导入
  • 修改 render_section() 以支持内置和提供程序部分
  • 修改 render_sections() 以包含动态部分
  • 添加 get_available_sections() 方法以获取元数据
  • 更新 _render_bios_screen() 以显示动态部分列表
  • 更新 run_bios() 以支持动态部分
  • 添加新命令:
    • [m](显示提供程序元数据)
    • [s](按名称搜索部分)
  • 内置部分:config、transport、pipeline、plugins、db、identity

向后兼容性:✅ 内置部分仍可正常工作,新提供程序扩展功能

3. web_user 集成

文件src/opensynaptic/services/web_user/main.py(已更新)

更改内容:

  • 添加显示 API 导入
  • 添加 get_display_providers_metadata() 方法
  • 添加 render_display_section() 方法
  • 添加 collect_all_display_sections() 方法

新的 HTTP 端点

  • GET /api/display/providers(所有提供程序的元数据)
  • GET /api/display/render/{plugin}:{section}?format=json(呈现特定部分)
  • GET /api/display/all?format=json(收集所有部分)

文件src/opensynaptic/services/web_user/handlers.py(已更新)

更改内容:

  • 添加 /api/display/providers 处理程序
  • 添加 /api/display/render/{section_path} 处理程序
  • 添加 /api/display/all 处理程序

所有端点都支持格式参数:json、html、text、table、tree

4. 示例插件

文件src/opensynaptic/services/example_display_plugin.py(新建)

参考实现展示:

  • NodeStatsDisplayProvider(基本示例)
  • PipelineMetricsDisplayProvider(表格格式示例)
  • TransportStatusDisplayProvider(HTML 格式示例)
  • CustomSectionDisplayProvider(扩展模板)
  • CLI 集成示例

5. 现实示例

文件src/opensynaptic/services/id_allocator_display_example.py(新建)

完整现实示例,展示 id_allocator 插件如何使用显示 API:

  • IDLeaseMetricsDisplay(具有 HTML 和文本格式的租赁系统指标)
  • IDAllocationStatusDisplay(具有 HTML、表格和柱状图的池状态)
  • web 和 terminal 的自定义格式
  • 详细的指标提取逻辑

6. 文档

文件DISPLAY_API_GUIDE.md(新建)

  • 完整的 API 参考
  • 架构概述
  • 插件开发指南
  • Web API 端点文档
  • tui 集成指南
  • 最佳实践
  • 迁移指南
  • 故障排除

文件DISPLAY_API_QUICKSTART.md(新建)

  • 5 分钟快速入门指南
  • 关键文件参考
  • 常见模式
  • 测试方法
  • 快速参考表

架构图

┌─────────────────────────────────────────────────────────┐
│ 显示 API 核心 │
│ (display_api.py) │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ DisplayProvider │ │ DisplayRegistry │ │
│ │ (抽象) │ │ (单例) │ │
│ └──────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────┘

┌──────────────┼──────────────┐
│ │ │
┌────────────┐ ┌────────────┐ ┌──────────────┐
│ 插件 1 │ │ 插件 2 │ │ 插件 N │
│ 注册提供 │ │ 注册提供 │ │ 注册提供 │
│ 程序 │ │ 程序 │ │ 程序 │
└────────────┘ └────────────┘ └──────────────┘
│ │ │
└──────────────┼──────────────┘

┌──────────────┴──────────────┐
│ │
┌──────────────┐ ┌──────────────┐
│ web_user │ │ tui │
│ /api/display │ │ 动态部分 │
│ 端点 │ │ │
└──────────────┘ └──────────────┘
│ │
└──────────────┬──────────────┘

自动发现 + 呈现

使用流程

插件注册

1. 插件调用 auto_load()
2. 插件创建 DisplayProvider 子类实例
3. 插件调用 register_display_provider(实例)
4. 注册表在全局单例中存储提供程序

web_user 发现

1. 客户端请求 /api/display/providers
2. web_user 查询注册表以获取元数据
3. 注册表返回所有提供程序及其元数据
4. 客户端现在知道哪些部分可用

web_user 呈现

1. 客户端请求 /api/display/render/plugin:section?format=json
2. web_user 使用格式参数调用 render_section()
3. 显示 API 调用 provider.extract_data()
4. 显示 API 调用 provider.format_json()(或其他格式)
5. web_user 返回格式化输出

tui 发现

1. 用户启动 tui 交互式
2. tui 调用 render_sections(None)
3. render_section() 查询注册表获取所有提供程序
4. 从以下关键字动态构建部分列表:
- 内置:config、transport、pipeline、plugins、db、identity
- 提供程序:example_display:node_stats、id_allocator:lease_metrics 等

tui 显示

1. 用户键入部分号
2. tui 调用 render_section(部分名)
3. 部分名格式:"plugin_name:section_id"
4. 显示 API 路由到相应提供程序
5. 调用提供程序的 extract_data() 和 format_text()
6. BIOS 控制台中显示输出

关键设计决策

  1. 全局单例注册表

    • 简单、清晰的 API
    • 使用 RLock 的线程安全
    • 从任何地方都可轻松访问
  2. 提供程序优先级系统

    • 提供程序按优先级排序(0-100)
    • 优先级越高 = 显示越靠前
    • 允许无需排序插件即可自定义
  3. 多种输出格式

    • JSON(默认,最灵活)
    • HTML(用于 web 呈现和样式设置)
    • TEXT(用于终端显示)
    • TABLE(用于结构化表格数据)
    • TREE(用于分层数据)
    • 每个提供程序实现所需的内容
  4. 向后兼容性

    • 内置部分仍可不变工作
    • 旧代码不受影响
    • 提供程序完全是附加性
  5. 延迟格式方法

    • 提供程序仅重写所需内容
    • 所有格式均有合理默认值
    • 减少样板代码

文件修改摘要

文件更改行数
src/opensynaptic/services/display_api.py新建400+
src/opensynaptic/services/example_display_plugin.py新建300+
src/opensynaptic/services/id_allocator_display_example.py新建350+
src/opensynaptic/services/tui/main.py已更新~50
src/opensynaptic/services/web_user/main.py已更新~80
src/opensynaptic/services/web_user/handlers.py已更新~35
DISPLAY_API_GUIDE.md新建600+
DISPLAY_API_QUICKSTART.md新建400+

执行的测试

语法验证 ✅

python -m py_compile src/opensynaptic/services/display_api.py
python -m py_compile src/opensynaptic/services/example_display_plugin.py
python -m py_compile src/opensynaptic/services/tui/main.py
python -m py_compile src/opensynaptic/services/web_user/main.py
python -m py_compile src/opensynaptic/services/web_user/handlers.py

所有文件均编译无语法错误。

向后兼容性 ✅

  • 内置 TUI 部分仍可工作
  • 现有 API 无破坏性更改
  • 旧代码路径不受影响

现有插件的集成点

ID 分配器插件

auto_load() 中注册显示提供程序:

from opensynaptic.services.display_api import register_display_provider

def auto_load(config=None):
# ... 现有代码 ...
register_display_provider(IDLeaseMetricsDisplay())
register_display_provider(IDAllocationStatusDisplay())
return True

参见:src/opensynaptic/services/id_allocator_display_example.py

测试插件

可注册性能和压力测试指标:

register_display_provider(StressTestMetricsDisplay())
register_display_provider(PerformanceComparisonDisplay())

其他插件

任何插件现在都可注册自定义显示部分:

def auto_load(config=None):
register_display_provider(MyCustomDisplay())
return True

不再硬编码的内容

之前(硬编码)

  • TUI 部分方法:_section_config()_section_transport()
  • web_user 仪表板构建:硬编码部分列表
  • 插件特定指标:必须编辑核心代码

之后(自发现)

  • 插件注册自己的 DisplayProvider 实例
  • web_user 自动发现所有已注册提供程序
  • tui 自动发现并列出所有提供程序部分
  • 新插件无需修改核心代码

采用后续步骤

  1. 添加到示例显示插件 ✅ 完成
  2. 添加到 id_allocator 插件(已提供参考示例)
  3. 添加到 test_plugin(可注册基准指标)
  4. 更新文档 ✅ 完成 (DISPLAY_API_GUIDE.md、QUICKSTART.md)
  5. 插件开发人员(将其用作新显示部分的模板)

性能考量

  • 注册表查询:O(1) 哈希表访问
  • 列表操作:O(n),其中 n = 提供程序数
  • 提取数据:插件相关,通常 <10ms
  • 格式转换:插件相关,通常 <5ms
  • 线程安全:保守使用 RLock

对 tui 刷新的预期影响:<5ms 提供程序发现开销


未来增强

  1. 缓存(使用 TTL 缓存 extract_data() 结果)
  2. 筛选 API(按类别/优先级获取提供程序)
  3. 批量呈现(单个调用中呈现多个部分)
  4. 格式协商(根据客户端自动选择最佳格式)
  5. 提供程序热重启(运行时注册/注销)
  6. 指标(跟踪提供程序呈现时间)
  7. Web 小组件(生成交互式 web UI 组件)

参考

  • 核心实现src/opensynaptic/services/display_api.py
  • TUI 集成src/opensynaptic/services/tui/main.py
  • web_user 集成src/opensynaptic/services/web_user/main.py
  • 示例插件src/opensynaptic/services/example_display_plugin.py
  • 完整指南DISPLAY_API_GUIDE.md
  • 快速入门DISPLAY_API_QUICKSTART.md
  • ID 分配器示例src/opensynaptic/services/id_allocator_display_example.py

有疑问吗?

如有全面文档,请参阅 DISPLAY_API_GUIDE.md;如需快速示例,请参阅 DISPLAY_API_QUICKSTART.md