Nightingale 业务组BusiGroupAPI 指南基于 Skill Gateway 的只读查询与 bgid/gid 溯源【免费下载链接】nightingaleNightingale is to monitoring and alerting what Grafana is to visualization.项目地址: https://gitcode.com/GitHub_Trending/ni/nightingale业务组Business Group简称 BG是 Nightingalen9e中一切监控资源的归属与权限单元告警规则、目标targets、仪表盘、静默、订阅、录屏规则等都必须归属于某个业务组而用户对资源的访问权限也是按业务组授予的。本文围绕aiagent/skill/embedded/builtin/skill-creator/api/busi-groups.md这一份 Skill 内置 API 参考文档完整讲解通过 Skill Gateway 查询业务组的三个只读接口、全部查询参数与响应字段并结合仓库源码models/busi_group.go、center/router/router_busi_group.go、models/user.go深入解析其 RBAC 行为与底层实现。读完本文你将能正确构造bgid/gid/gids参数去调用其它 n9e 只读接口并能安全地在自己的 Skill 脚本中完成按业务组发现与筛选资源的流程。一、业务组n9e 的 RBAC 与资源归属单元在 Nightingale 中每个告警规则alert rule、目标target、仪表盘board、静默mute、订阅subscribe、录屏规则recording rule等资源都恰好归属于一个业务组用户对这些资源的访问权限则通过团队user-group / teams按组授予。这里有一个贯穿全篇、必须牢记的关键约定业务组的id正是其它接口中所说的bgid、gid或gids。例如/busi-group/id/alert-rules路径中的id/busi-groups/alert-rules、/targets、/alert-his-events/list等接口上的gids/bgid查询参数。因此本文介绍的三个接口是整个查询体系的第一站先从这里发现当前用户可见哪些业务组、它们的 id 是多少再把拿到的 id 传给其它接口做资源过滤。在源码层面这一模型的落点是 models/busi_group.go 中的BusiGroup结构体数据表busi_group与 models/busi_group_member.go 中的BusiGroupMember结构体数据表busi_group_member保存业务组-团队的关联关系及perm_flag权限标志。业务组与团队是多对多关系一个业务组可以由多个团队共同管理一个团队也可以管理多个业务组。二、调用前提Skill Gateway 协议速览本文档描述的接口属于Skill Gateway 调用是只读 GET 请求。正式动手前先了解 n9e-api.md 规定的通用协议写任何脚本前都应先读该索引文件Socket 路径来自环境变量N9E_SKILL_GATEWAY通过它发送换行分隔的 JSONnewline-delimited JSON路径必须包含/api/n9e前缀例如请求{method:GET,path:/api/n9e/busi-groups,...}query中的所有值必须是字符串例如{limit:300,all:true}而不是数字或布尔值这一点只针对querymapPOSTbody内使用原生 JSON 类型响应信封为{ok:true,status:200,data:{dat:payload,err:}}——一定要读取data[dat]若err非空则说明 n9e API 报错列表的两种形态Pattern A 为dat {list:[...],total:N}分页用于高频事件/目标接口Pattern B 为dat [...]裸数组无 total一次性返回用于配置对象列表。本文的业务组接口属于Pattern B路径不能凭空猜测错误路径不会返回 404n9e 会把 SPA 的index.htmlHTML 字符串放进data导致静默失败。脚本必须校验ok为 true、data是 dict 且data[err]为空后再使用data[dat]Deny-list/datasource*、/notify-channel*、/users、SSO/IdP 等携带密钥或涉及写操作的路径会被网关以ok:false拒绝不要试图绕过完整清单见 n9e-api.md 末尾的 Blocked 一节。三、三个核心端点一览busi-groups.md定义了三个端点覆盖了列表 → 详情 → 标签的完整发现链路Path用途dat形态/busi-groups当前用户可见的业务组管理员全部其它用户其团队所拥有的组Pattern B——BusiGroup裸数组/busi-group/:id单个业务组附带其所属团队user_groups被填充:id位于路径中单个BusiGroup对象/busi-groups/tags跨业务组去重后的目标标签集合字符串裸数组三条端点分别解决三个问题/busi-groups用于枚举和发现 id/busi-group/:id用于查看某个组的完整归属信息谁在管理、读写权限如何/busi-groups/tags用于我要按标签筛选目标场景下的标签字典获取。四、/busi-groups列表查询与查询参数4.1 查询参数参数类型必填默认值含义querystring否对组name的不区分大小写子串匹配。隐藏回退对管理员若按名字无匹配则会把它当作目标ident重试一次以找到该主机所属的业务组。limitint字符串否300返回的最大行数。allbool字符串否falsetrue 列出系统中的每一个业务组管理员无论此标志如何都始终看到全部否则仅列出当前用户团队所拥有的组。注意通过网关传参时所有值都是字符串例如{limit:300,all:true}。4.2 可见性规则与隐藏的 ident 回退/busi-groups的可见性并非全量返回其 RBAC 逻辑在 models/user.go 的User.BusiGroups方法中体现得淋漓尽致管理员u.IsAdmin()或传了alltrue直接按name like %query%查询全部业务组普通用户先通过MyGroupIds拿到用户所属的团队 id再经BusiGroupIds见 models/busi_group_member.go反查出这些团队有权限的业务组 id 集合最后限定id in ?过滤——用户永远只能看到自己团队所拥有的组隐藏的 ident 回退当query按名字查不到任何组时代码会把query当作目标ident主机标识再查一次TargetGet(ctx, ident?, query)若命中则返回该主机所属的业务组普通用户还会额外校验该主机的组是否与busiGroupIds有交集t.MatchGroupId(busiGroupIds...)。源码注释戏称这是一般不告诉别人的隐藏功能但它确实是一个实用的逆向查找入口。4.3 列表返回的注意事项/busi-groups会填充update_by_nickname计算字段但不会填充user_groups保持为空/null当你需要所属团队及其权限标志时请改用/busi-group/:id。update_by_nickname的填充由 models/user.go 的FillUpdateByNicknames泛型函数完成它通过反射读取每个元素的UpdateBy字段批量查用户名→昵称映射UserNicknameMap再写回UpdateByNickname字段避免了对数据库的 N 次查询。路由层在 center/router/router_busi_group.go 的busiGroupGets中调用它。五、/busi-group/:id单个业务组与其所属团队当需要获取某个业务组的完整归属信息时使用/busi-group/:idid必须放在路径中例如/api/n9e/busi-group/2。该接口与列表接口的关键差异在于user_groups字段被填充。其实现对应 center/router/router_busi_group.go 的busiGroupGet先通过BusiGroup中间件按路径参数拿到目标业务组再调用bg.FillUserGroups(rt.Ctx)。而FillUserGroups的实现在 models/busi_group.go通过BusiGroupMemberGetsByBusiGroupId查出该业务组的所有成员关系busi_group_member表对每条成员关系用UserGroupGetById取回完整的团队对象UserGroup组装成UserGroupWithPermFlag定义于 models/busi_group.go其中PermFlag直接取自成员记录的perm_flag字段。perm_flag只有两个取值rw读写与ro只读。一个业务组通常至少要有一个rw的团队来承担管理职责——路由层busiGroupAddcenter/router/router_busi_group.go在创建业务组时校验members不能为空且必须至少有一个团队是rw权限否则直接报 400。同样DelMembersmodels/busi_group.go在删除成员时会确保业务组至少保留一个团队否则返回 the business group must retain at least one team。六、/busi-groups/tags跨组目标标签字典GET /api/n9e/busi-groups/tags?gids1,2,3返回从所选业务组的目标targets上收集到的去重标签字符串数组[]string例如[envprod,regioncn-east-1]接受可选的gids查询参数逗号分隔的业务组 id为空表示当前用户的所有业务组。其实现链路在 center/router/router_busi_group.go 的busiGroupsGetTags先用TargetIndentsGetByBgidsmodels/target_busi_group.go根据业务组 id 集合查出所有目标 ident再调用TargetGetTagsmodels/target.go聚合并去重出标签。典型用法是拿到标签字典后与/targets接口配合用目标标签做进一步的筛选与分组统计。七、响应对象BusiGroup全字段解析/busi-groups返回裸数组Pattern B数组中的每个元素是一个BusiGroup对象/busi-group/:id则直接返回单个对象。字段定义与源码BusiGroup结构体models/busi_group.go一一对应字段json类型含义idint64业务组 id——即其它接口中使用的bgid/gid/gids的值namestring业务组显示名全局唯一label_enableint1 该业务组还会向目标的指标注入一个标签0 关闭label_valuestringlabel_enable1时注入的标签值否则为空create_atint64创建时间unix 秒create_bystring创建者用户名update_atint64最后更新时间unix 秒update_bystring最后更新者用户名update_by_nicknamestring计算字段由update_by解析出的显示昵称user_groupsarray计算字段所属团队 权限标志。仅由/busi-group/:id填充在/busi-groups列表中为空/null。每个元素形如{user_group: UserGroup, perm_flag: ro\|rw}关于user_groups中内嵌的UserGroup对象它携带id、name、note、create_at、create_by、update_at、update_by、update_by_nickname以及在此处通常为空的users/busi_groups字段。7.1 关于 label_enable / label_value 的补充label_enable与label_value是业务组上比较容易忽略但影响深远的字段。从 models/busi_group.go 的Update与BusiGroupAddmodels/busi_group.go可以看出其约束name全局唯一创建/更新时会做BusiGroupExists校验当label_enable1时label_value全局唯一——即不允许两个业务组注入相同的标签值否则会报 BusiGroup already exists当label_enable0时label_value会被强制清空为。这意味着业务组具备向归属目标的指标注入固定标签的能力可用于在查询指标时区分数据来源归属源码中以bgLabelKey参数贯穿TargetGetTags等目标处理逻辑。八、完整请求 / 响应示例8.1 列表/busi-groups请求{method:GET,path:/api/n9e/busi-groups,query:{limit:300}}响应已裁剪{ ok: true, status: 200, data: { dat: [ { id: 2, name: default-busi-group, label_enable: 0, label_value: , create_at: 1700000000, create_by: root, update_at: 1700000000, update_by: root, update_by_nickname: Administrator, user_groups: null } ], err: } }8.2 详情/busi-group/2附带所属团队请求{method:GET,path:/api/n9e/busi-group/2,query:{}}响应{ ok: true, status: 200, data: { dat: { id: 2, name: default-busi-group, label_enable: 0, label_value: , create_at: 1700000000, create_by: root, update_at: 1700000000, update_by: root, update_by_nickname: Administrator, user_groups: [ {user_group: {id: 1, name: admins, note: }, perm_flag: rw} ] }, err: } }对比两份响应可以直观看到差异列表接口中user_groups为null而详情接口中它被填充为一个包含{user_group: {...}, perm_flag: rw}的数组。示例中id2、namedefault-busi-group是安装初始化时自动创建的默认业务组由名为admins的团队以rw读写权限管理。九、脚本中的实战用法响应校验与 id 溯源9.1 响应校验模板由于错误路径会静默返回 HTML脚本中应始终先做三段式校验再取数模板见 n9e-api.md 的 Validate every response 一节import json, os, socket def call(path, queryNone): req {method: GET, path: /api/n9e/ path.lstrip(/), query: query or {}} s socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s.connect(os.environ[N9E_SKILL_GATEWAY]) s.sendall((json.dumps(req) \n).encode()) buf b while True: chunk s.recv(65536) if not chunk: break buf chunk if b\n in buf: break resp json.loads(buf.split(b\n)[0].decode()) if not resp.get(ok) or not isinstance(resp.get(data), dict): raise RuntimeError(fgateway call failed: {str(resp)[:200]}) env resp[data] if env.get(err): raise RuntimeError(fn9e api error: {env[err]}) return env[dat]9.2 典型流程发现 → 溯源 → 过滤一个典型的业务组驱动查询流程如下发现/busi-groups?limit300拿到全部可见组的id/name映射溯源对某个不确定归属的资源如告警事件返回的bgid可用/busi-group/id反查组名与管理团队过滤把选定的gids逗号分隔字符串传给/busi-groups/alert-rules、/targets、/alert-his-events/list等资源端点实现只看某几个业务组的查询按标签分组/busi-groups/tags?gids...获取标签字典后再结合目标标签做汇总统计。注意业务组相关接口的两种作用域惯用法见 n9e-api.md 的 Business-group scoping idiom跨组资源用/busi-groups/resource?gids...空gids 当前用户 RBAC 允许的所有组单组资源用/busi-group/id/resourceid必填于路径。9.3 权限边界只读与 Deny-list通过 Skill Gateway 调用时业务组接口仅为只读 GET。网关会以发起对话的用户的身份执行请求n9e 自身的路由中间件会做常规 RBAC 与业务组权限校验而携带密钥或写操作的路径如/datasource*、/notify-channel*、/users、SSO 相关等会被网关以ok:false拒绝。业务组的创建、更新、成员管理等写操作不在网关能力范围内应在 n9e Web 控制台的业务组管理界面完成。十、延伸阅读调用协议、响应信封、列表形态与 Deny-list 总览n9e-api.md业务组数据模型与增删改查、删除级联检查models/busi_group.go、models/busi_group_member.go业务组 HTTP 路由与参数解析列表/详情/标签/成员管理center/router/router_busi_group.go业务组可见性的 RBAC 核心逻辑admin/all/ident 回退models/user.go配套资源接口按组过滤的实际应用场景api/alert-rules.md、api/targets.md、api/alert-events.md、api/user-groups.md编写调用这些接口的 Skill 脚本的完整规范SKILL.md【免费下载链接】nightingaleNightingale is to monitoring and alerting what Grafana is to visualization.项目地址: https://gitcode.com/GitHub_Trending/ni/nightingale创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考