OneUptime 库存自定义字段(Inventory Custom Fields)完全指南:从资产登记到过滤查询
2026/9/19 21:25:59 网站建设 项目流程

OneUptime 库存自定义字段(Inventory Custom Fields)完全指南:从资产登记到过滤查询

【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime

导读

OneUptime 通过自动发现告诉你环境里有什么设备,而自定义字段(Custom Fields)则是记录这些设备其余一切信息的方式——机身贴纸上的序列号、保修到期的日期、资产归属团队、设备是在役状态还是躺在备件抽屉里。本指南基于 OneUptime 官方文档与开源仓库源码,完整讲解自定义字段的定义、七种字段类型、一套可直接套用的硬件资产登记词汇表、基于字段类型的过滤操作符体系,以及存储与查询层面的实现原理与已知限制。读完你可以在自己的项目中为任意库存条目建立结构化的资产元数据,并像查询数据库一样按字段组合过滤出"下季度到保修的设备"这类精准视图。

概览:发现之外的信息层

OneUptime 的库存(Inventory)模块会持续发现和镜像网络设备、服务器等基础设施资产,回答"你的环境里有什么"。但发现本身是观测:它能看到型号、接口、邻接关系,却看不到刻在设备上的序列号、写在采购单上的保修期限、团队职责分工这类业务元数据。自定义字段就是为这些"观测不到的信息"而生的扩展层。

字段定义在项目(project)维度一次定义,随后在每个条目(item)上逐项填充。定义完成后,它们会自动以三种形态出现在界面中:

  1. 过滤芯片(filter chips)——库存列表上方的筛选条;
  2. 可选的表格列(optional table columns)——默认隐藏,可手动开启;
  3. CSV 导出列(CSV export columns)——随列表导出一并输出。

需要说明的是,自定义字段在 OneUptime 的Growth 及以上套餐中可用。这一限制在数据模型上有直接体现:InventoryItemCustomField.ts 通过@TableBillingAccessControl装饰器为 create / read / update / delete 全部声明了PlanType.Growth,即定义字段本身的操作受套餐等级约束。

定义字段:Inventory → Settings → Custom Fields

进入Inventory → Settings → Custom Fields页面即可新增字段。每个字段由三要素构成:名称(必填)可选描述字段类型

字段类型共有七种,官方文档给出的类型与用途对照如下:

类型适用场景
Text(文本)序列号、资产标签、机架位置、采购订单号
Number(数字)成本、机架单元数、端口数量
Boolean(布尔)是否在支持期内、是否处于 PCI 合规范围
Dropdown(单选下拉)生命周期状态、环境、重要性等级——从固定列表中取一个答案
Multi-select Dropdown(多选下拉)合规范围、标签——从固定列表中取多个答案
Date(日期)采购日期、保修到期日、生命周期结束日期
Date and time(日期时间)最后审计时间、退役时间

下拉选项的每个选项都可以携带一种颜色,该颜色会在表格单元格与过滤芯片中一致呈现,保证两处读到的语义相同。这七种类型在仓库中的权威定义位于 CustomFieldType.ts,枚举成员TextNumberBooleanDropdownMultiSelectDropdownDateDateTime一一对应。该文件有一处值得注意的工程约束:枚举成员值"承重"(load-bearing),CustomFieldsDetail组件会把字段类型直接透传给详情字段和表单字段,因此每个成员的值必须同时匹配详情FieldType与表单FormFieldSchemaType的成员名,否则会渲染出空白单元格和无法输入的控件。

表单层面的实现细节

字段定义的增删改查由通用组件CustomFieldsPageBase承载(CustomFieldsPageBase.tsx),库存模块通过薄封装调用它(CustomFields.tsx)。从源码可以提取以下实操要点:

  • Field Name必填,最小长度为 2 个字符,占位示例为internal-service
  • Field Description可选,长文本;
  • Field Type必填下拉,选项正是上述七种类型;
  • Dropdown Options仅在类型为下拉时才显示,可逐条录入选项并为每个选项选择颜色;
  • 字段名称在项目内唯一——数据模型用@UniqueColumnBy("projectId")声明了name字段(InventoryItemCustomField.ts),同一项目下不能出现两个同名字段。

此外,InventoryItemCustomField模型的权限设计复用了 Telemetry 服务权限族(CreateTelemetryService/ReadTelemetryService/EditTelemetryService/DeleteTelemetryService),并默认开放给 ProjectOwner、ProjectAdmin、ProjectMember、Viewer 等角色读取(见 InventoryItemCustomField.ts),也就是说项目内所有成员都能看到已定义的字段。

一套可落地的资产词汇表(Worked Asset Vocabulary)

一份典型的硬件资产登记册(asset register)几乎可以直接映射到这些字段类型上。官方文档给出的示范词汇表如下:

字段名类型示例值
Serial Number文本FDO24160ABC
Asset Tag文本IT-004821
Purchase Date日期2024-03-11
Warranty Expiry日期2027-03-10
Lifecycle Status下拉(单选)In Service / Spare / In Repair / Retired
Assigned Site下拉(单选)London DC / Frankfurt DC / Office HQ
Owner Team下拉(单选)Network / Platform / Security
Cost Centre文本CC-4410

其中Purchase DateWarranty Expiry这类字段务必使用Date 类型而不是文本——这是官方文档反复强调的一个反直觉陷阱:文本字段会"欣然"存下2026-10-01,但当你想问"未来三个月内哪些设备保修到期"时,它却无法回答。日期类型之所以能做到这一点,依赖于存储层约定(详见下文"存储与查询原理"一节)。

在条目上填充值

字段值在每个条目的 Custom Fields 选项卡下设置(对应页面实现 CustomFields.tsx,其底层使用通用组件CustomFieldsDetail)。关键能力在于:无论条目来源如何,任何条目都可以设置自定义字段值。无论是自动发现的交换机、镜像的网络设备,还是手动添加的设备,都能承载同一套资产词汇——这保证了发现数据与人工录入数据在元数据层面完全对齐。

过滤:把字段变成列表上方的芯片

每个已定义的自定义字段都会自动变成库存列表上方的过滤芯片(filter chip),并且可用的操作符随字段类型变化。官方文档给出的操作符矩阵如下:

  • 文本—— 是、不是、包含、不包含、以…开头、以…结尾、为空、不为空
  • 数字—— 是、不是、大于、大于或等于、小于、小于或等于、为空、不为空
  • 下拉—— 是、不是、为空、不为空
  • 日期 / 日期时间—— 是、在…之前、在…之后、介于…之间、为空、不为空

多个芯片之间以AND逻辑组合。因此"Warranty Expiry 在 2026-10-01 之前Lifecycle Status 为 In Service"就是一个单一视图。这正是资产登记册存在的意义——回答这类组合查询。

过滤芯片的源码级实现

过滤芯片的实现位于 CustomFieldFacets.ts,其中有若干值得展开的设计细节:

  • 统一查询字段:所有自定义字段芯片都写入同一个查询字段customFields(常量CUSTOM_FIELD_QUERY_FIELD,见该文件第 70 行)。每个芯片的查询值是一个以字段名作为键的对象(如{ "Warranty Expiry": LessThan(...) }),多个芯片通过mergeCustomFieldQueryValue以浅展开方式 AND 合并,而不是"后写覆盖先写"(见 CustomFieldFacets.ts)。合并函数对"普通对象"做了原型链校验,避免把IsNullIncludes等查询操作符对象误当成可展开对象而悄悄丢掉约束。
  • 键名前缀防冲突:芯片键统一加customField:前缀(CUSTOM_FIELD_FACET_KEY_PREFIX),这样名为 "labels" 的自定义字段不会与筛选条自带的 Labels 芯片冲突。
  • "为空"的特殊语义:因为值存放在单一 JSON 列内,"为空"必须理解为"这个键未设置"而不是"整列为空",因此芯片声明了handlesValuelessOperators并自行构造该谓词。
  • 布尔字段的芯片:布尔字段以真实 JSON 布尔值存储,芯片下拉固定为 Yes / No 两个选项,与表格单元格的渲染文案保持一致。
  • 无选项下拉的降级:若下拉字段没有配置任何选项,芯片会降级为文本输入而非渲染一个空选择器——因为字段本身存在且有值,让用户直接输入比给出一个无可选项的控件更好。
  • 排序稳定性:芯片由按名称排序的定义列表构建,合并后对象的键序稳定,表格通过JSON.stringify(query)判断是否重新拉取数据,键序不稳定会导致请求循环。

操作符到查询谓词的映射关系(buildCustomFieldFacetQuery,见 CustomFieldFacets.ts)同样可在源码中验证:文本类的containsSearchnot_containsNotContainsstarts_withStartsWithends_withEndsWith;数字类的比较 →GreaterThan/GreaterThanOrEqual/LessThan/LessThanOrEqual,且对非法数字做了Number.isFinite防护(防止手改 URL 传入 NaN 导致谓词恒假);单/多选下拉的is→ 等于或Includes(多选语义为"包含任意一个")、is_notNotEqualIncludesNone

自定义字段列

自定义字段列默认隐藏,可通过表格的**列选择器(column picker)**开启。需要明确的一点是:这些列不支持排序。原因在于字段值全部存放于一条customFieldsJSON 列内,查询路径无法基于 JSON 内部的键进行排序——这是官方文档明示的限制,也从侧面解释了为什么"序列号唯一性"等需求不能依赖排序来人工核对。

存储与查询原理:一个 customFields jsonb 列

从 CustomFieldFacets.ts 的注释可以确认:自定义字段值并不各自独立成列,而是以字段名为键,全部存放在每行记录的一个customFieldsjsonb 列中。这一设计带来两个全局性后果:

  1. 所有芯片写同一个查询字段,靠对象合并实现多条件 AND;
  2. 日期比较依赖 ISO-8601 的文本序等价性——日期输入统一通过OneUptimeDate.toString()(即toISOString())规范化为 ISO-8601 UTC 字符串再进入customFields包,而 ISO-8601 作为文本排序与作为时间瞬间排序结果一致,因此 jsonb 键上的范围过滤无需类型转换即可正确工作。这也正是 CustomFieldType.ts 中 Date/DateTime 注释所强调的"可比较性"来源。

服务端 JSON 列查询

服务端把{ "Warranty Expiry": LessThan("2026-10-01") }这类对象编译为一条 AND 连接的 WHERE 片段,实现在 JSONColumnQuery.ts 的buildJSONColumnQuery。几个边界行为值得了解:

  • 空对象{}保留历史语义"该列为空",即(column IS NULL OR column = '{}')
  • 所有条件都未形成有效约束时返回(1 = 1)(匹配全部),避免把整张表藏在一个已清空的过滤条件后面;
  • 单个 JSON 过滤键数量与键长均有上限(超限抛BadDataException);
  • 该查询构建器在 QueryHelper.ts 中被通用查询路径调用,说明这套 jsonb 过滤能力不只服务于库存模块。

注意事项与限制

官方文档明确列出的边界如下,均在仓库实现中可找到对应证据:

  • 值按字段名存储:每个条目的值存放在字段名称之下。重命名字段不会迁移旧名称下已存的值——改名后旧数据会"原地不动",新名称下不会有任何数据。实践中应避免改名,或在改名后重新填充。
  • 没有唯一性约束:两个条目可以携带相同序列号,系统不会阻止。若需要唯一性,只能靠流程制度保障,或考虑通过外部 CMDB 同步施加约束(见文末链接)。
  • 日期以 ISO-8601 UTC 时间戳存储,按本地时区显示:数据层面固定为 UTC 规范化字符串,界面显示时转换为你自己的时区。
  • 删除字段定义只是移除"可见性":删除定义后,字段从列表和过滤栏消失,但已写入的值仍保留在底层记录中,并不会被物理清除。这一行为与"值按名称存放"的设计一致,也意味着误删定义后的数据仍可通过底层记录恢复/导出。

下一步:导出到 CMDB

自定义字段的价值最终要回流到更大的资产治理体系。OneUptime 提供了将库存导出到 CMDB 的集成能力,官方文档将其作为自定义字段的延伸阅读入口:导出到 CMDB。当自定义字段承载了完整的资产词汇后,CMDB 同步即成为把发现数据与业务元数据一并交付给外部系统的通道。

参考文件索引

  • 官方文档(英文):App/FeatureSet/Docs/Content/en/inventory/custom-fields.md
  • 官方文档(波斯文):App/FeatureSet/Docs/Content/fa/inventory/custom-fields.md
  • 字段类型枚举:Common/Types/CustomField/CustomFieldType.ts
  • 字段定义数据模型:Common/Models/DatabaseModels/InventoryItemCustomField.ts
  • 字段定义管理页:App/FeatureSet/Dashboard/src/Pages/Inventory/Settings/CustomFields.tsx 与 CustomFieldsPageBase.tsx
  • 条目自定义字段详情页:App/FeatureSet/Dashboard/src/Pages/Inventory/View/CustomFields.tsx
  • 过滤芯片构建与操作符映射:App/FeatureSet/Dashboard/src/Components/CustomFields/CustomFieldFacets.ts 与 useCustomFieldFacets.ts
  • 服务端 jsonb 查询编译:Common/Server/Types/Database/JSONColumnQuery.ts

【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询