news 2026/9/15 19:37:46

Nightingale Skill Gateway 数据查询 API 完全指南:指标与日志的只读 POST 查询协议

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Nightingale Skill Gateway 数据查询 API 完全指南:指标与日志的只读 POST 查询协议

Nightingale Skill Gateway 数据查询 API 完全指南:指标与日志的只读 POST 查询协议

【免费下载链接】nightingaleNightingale is to monitoring and alerting what Grafana is to visualization.项目地址: https://gitcode.com/GitHub_Trending/ni/nightingale

数据查询是 Nightingale 技能网关(Skill Gateway)中唯一被允许使用POST方法的一组接口:技能(Skill)通过它们读取数据源中的真实时序数据与日志数据,而不是平台自身的告警、规则等配置对象。本文以 api/data-query.md 为核心骨架,结合网关策略源码(policy.go、gateway.go)与中心端查询路由实现(router_proxy.go、router_query.go),完整讲解这组 POST 白名单端点的请求体、响应结构、调用顺序与安全边界。读完本文,你将能编写出经网关代理、受 RBAC 约束、可正确解析结果的指标/日志查询脚本。

一、定位与总体规则:为什么数据查询是"唯一的 POST 例外"

在 Nightingale 的技能网关安全模型中,绝大多数对平台自身数据的读取走 GET(黑名单模型,默认放行、按前缀拒绝敏感路径),而写操作一律被拒绝。唯一的例外是一组只读的数据查询端点——它们之所以被允许 POST,并不是因为它们会修改状态,而是因为它们携带的查询体是结构化的 JSON,体积与结构都远超 query 参数的承载能力。

这一点在 policy.go 中有明确注释与实现:

// postAllowN9eAPIPaths is the allowlist of read-only DATA-query endpoints the // gateway may forward with POST. They are POST only because they carry a JSON // query body that is too large/structured for query params — not because they // mutate state: each runs the query under the caller's RBAC (the handler's // CheckDsPerm) and returns time-series / log DATA, never config or secrets. var postAllowN9eAPIPaths = map[string]bool{ "/ds-query": true, // unified datasource query (metrics/logs by cate) "/query-range-batch": true, // Prometheus range query (batch) "/query-instant-batch": true, // Prometheus instant query (batch) "/logs-query": true, // log query (v2) "/log-query": true, // log query "/log-query-batch": true, // log query (batch) }

1.1 网关调用约定(对>var getAllowExceptions = map[string]bool{ "/datasource/brief": true, }

/datasource/brief是唯一可达的数据源路径,且服务端会调用RedactSecrets对返回内容做密钥脱敏——settings/auth/http字段中的地址、密码、token 全部被剔除。

2.2 端点与响应字段

Path用途dat形状
/datasource/brief列出你能查询的数据源(密钥脱敏)。网关可达的唯一数据源路径/datasource*配置均被拦截)Pattern B(裸数组)

无 query 参数。dat是数据源对象数组,每个对象的json字段含义如下:

字段类型含义
idint64数据源 id——传给查询端点作为datasource_id
namestring显示名称
identifierstring唯一标识
descriptionstring描述
plugin_idint64插件 id
plugin_typestring插件类型——这就是/ds-querycate(如prometheusmysqlelasticsearchlokitdengineck
plugin_type_namestring人类可读插件名(如Prometheus Like
categorystring大类:timeserieslogging等——用于区分指标源与日志源
cluster_namestring集群名(遗留字段)
statusstringenabled/disabled
is_defaultbool是否为默认数据源
settingsobject已脱敏——仅保留非敏感 UI 键,不要期望有地址/凭据
created_at/updated_atint64Unix 秒
created_by/updated_bystring作者

2.3 示例

请求:

{"method":"GET","path":"/api/n9e/datasource/brief"}

响应(已裁剪):

{"ok":true,"status":200,"data":{"dat":[ {"id":1,"name":"prod-prometheus","plugin_type":"prometheus","category":"timeseries","status":"enabled","is_default":true}, {"id":5,"name":"app-loki","plugin_type":"loki","category":"logging","status":"enabled"} ],"err":""}}

拿到id(作为datasource_id)与plugin_type(作为cate)之后,就可以继续下面的查询端点了。

三、POST 白名单端点总览

Path用途Bodydat结果
/query-range-batchPrometheus区间查询(一段时间内的序列)BatchQueryFormqueries对齐的数组;每项是一个 Prometheusmatrix
/query-instant-batchPrometheus瞬时查询(一个时间点)BatchInstantFormqueries对齐的数组;每项是一个 Prometheusvector
/ds-querycate任意数据源(指标或日志)的统一查询QueryParam数据源相关
/logs-query·/log-query·/log-query-batch日志查询QueryParam{"total":N,"list":[...]}

这些路由在 center/router/router.go 中注册(如pages.POST("/query-range-batch", rt.promBatchQueryRange)),并且支持仪表盘限时分享 token 的放行链路(boardTokenDetect()+skipIfBoardToken(...))。

四、Prometheus 指标查询:最简单的路径

如果目标数据源是 Prometheus 类(plugin_type == "prometheus",如 Prometheus / VictoriaMetrics),优先使用区间/瞬时批量查询端点,它们只接受 PromQL 字符串 + 时间窗,形状固定、无歧义。

4.1 区间查询:/query-range-batch

请求体(BatchQueryForm):

{ "datasource_id": 1, "queries": [ {"query": "<PromQL>", "start": 1751330400, "end": 1751334000, "step": 60} ] }

字段说明:

  • datasource_id(int,必填)——来自/datasource/brief
  • queries[](必填)——每项含:query(PromQL 字符串)、start/end(Unix 秒)、step(秒级分辨率)。全部必填

底层实现见 router_proxy.go:服务端将start/endtime.Unix转为时间、step转为time.Duration,逐条调用 Prometheus 客户端的QueryRange,结果按查询顺序追加到数组返回。

dat是与queries一一对应的数组,每项是一个 Prometheusmatrix(序列列表),每个序列含metric标签与values(时间戳-值对):

{"ok":true,"status":200,"data":{"dat":[ [ {"metric":{"__name__":"cpu","ident":"host-01"}, "values":[[1751330400,"6.3"],[1751330460,"7.1"]]} ] ],"err":""}}

step 取值建议(来自 query-datasource/datasources/prometheus.md,可直接套用):

时间范围step
1 小时15s
6 小时60s
24 小时300s
7 天1800s

4.2 瞬时查询:/query-instant-batch

请求体(BatchInstantForm)——注意每项用的是time,而非start/end/step

{"datasource_id": 1, "queries": [{"query": "<PromQL>", "time": 1751334000}]}

字段:datasource_id(int,必填)、queries[](必填)每项为query(PromQL 字符串)与time(Unix 秒,必填)。服务端实现见 router_proxy.go(PromBatchQueryInstant调用cli.Querytime.Unix(item.Time, 0)时刻)。

dat是与queries一一对应的数组,每项是一个 Prometheusvector

[{"metric":{...}, "value":[1751334000,"7.1"]}]

4.3 常用 PromQL 速查(指标查询场景)

需求PromQL
CPU 使用率cpu_usage_active
内存使用率mem_used_percent
磁盘使用率disk_used_percent{path="/"}
入站流量速率rate(net_bytes_recv[5m])
1 分钟负载system_load1
HTTP 请求速率rate(http_requests_total[5m])
某实例全部指标{ident="web-01"}
按实例聚合平均avg by (ident)(cpu_usage_active)
CPU Top 10topk(10, cpu_usage_active)

五、任意数据源统一查询:/ds-query

当目标数据源不是Prometheus 类(MySQL、Elasticsearch、Loki、TDengine、ClickHouse 等),或需要统一入口时,使用/ds-query。它按cate分发到对应数据源插件。

请求体(QueryParam):

{"cate": "<plugin_type>", "datasource_id": <id>, "query": [ <one-or-more query objects> ]}
  • cate——数据源在/datasource/brief中返回的plugin_typeprometheusmysqlelasticsearchlokitdengineck、…)。
  • query[]——查询对象数组;其形状取决于cate,与该数据源的告警规则查询配置一致(每种类型已有文档)。读取方式为:read_file(base="create-alert-rule", path="datasources/<cate>.md"),例如 datasources/prometheus.md、datasources/mysql.mddatasources/elasticsearch.mddatasources/loki.md(同目录下还有clickhouse.mddoris.mdhost.mdpgsql.mdtdengine.mdvictorialogs.md)。

dat的结果是数据源相关的:Prometheus 类数据源返回指标值;SQL 类数据源(mysql/pgsql/ck/tdengine)返回行;ES/Loki 返回日志或聚合结果。

5.1 源码视角:QueryDataConcurrently

统一查询的底层实现在 router_query.go,可以确认几个重要行为:

  1. 权限门:每条 query 在执行前都调用CheckDsPerm(ctx, f.DatasourceId, f.Cate, q)校验当前用户对该数据源的查询权限,未通过直接返回forbidden——这正是文档中"read-only and under your RBAC"的落地。
  2. 数据源解析:通过dscache.DsCache.Get(f.Cate, f.DatasourceId)取到数据源插件,再调用plug.QueryData
  3. 并发与排序:多条 query 通过 goroutine 并发执行(sync.WaitGroup+ mutex 收集结果);返回多条结果时按.Metric字典序排序,确保仪表盘中相同图例曲线颜色一致。
  4. 同一入口还支持仪表盘分享 token 场景(boardTokenQueryContext),命中后跳过基于登录用户的权限校验并置位强只读。

六、日志查询:/logs-query(及/log-query/log-query-batch

请求体同样是QueryParamcate+datasource_id+query[]的形状不变;query 的具体形状按create-alert-rule/datasources/<cate>.md构造)。dat的返回结构为:

{"total": N, "list": [ ...records... ]}

即"总数 + 记录列表"模式。底层实现在 router_query.go(QueryLogBatch/QueryLogConcurrently):逐条logQueryAccess审计,逐条CheckDsPerm校验,再并发调用数据源插件的QueryLog

七、推荐工作流

综合上述端点,一个完整的"从发现数据源到拿到数据"的调用流程如下:

  1. GET /datasource/brief→ 按category/plugin_type挑选数据源 → 记录其id+plugin_type
  2. 若是 Prometheus 类指标源 →POST /query-range-batch(或/query-instant-batch),携带datasource_id+ PromQL 即可。
  3. 若是其他类型数据源,或日志 →POST /ds-query(或/logs-query),携带cate=plugin_type,并按照create-alert-rule/datasources/<cate>.md构造 query 对象形状。

八、安全边界与注意事项

  1. 只读且受你的 RBAC 约束:处理函数会校验数据源查询权限(CheckDsPerm),只返回数据,绝不写任何状态;数据源配置、通知密钥、用户 token、SSO 配置等仍被黑名单拦截(详见 n9e-api.md 的 deny-list 一节)。
  2. 像所有网关调用一样校验响应:先确认ok为 true、data是 dict、data["err"]为空,再取data["dat"]。这同时也是发现"路径写错"的手段——未知路径不会返回 404,而是静默返回 SPA 的 HTML 字符串(data直接是 HTML)。可参考 n9e-api.md 中的 Python 校验片段:
if not resp.get("ok") or not isinstance(resp.get("data"), dict): raise RuntimeError(f"gateway call failed (wrong path? denied?): {str(resp)[:200]}") env = resp["data"] if env.get("err"): raise RuntimeError(f"n9e api error: {env['err']}") dat = env["dat"]
  1. 不要猜 query 形状:如果不知道某个数据源的查询形状,且create-alert-rule/datasources/<cate>.md描述不足,向用户询问,而不是猜测请求体。同样,不要按类比猜测 API 路径——所有路径必须以文档为准。
  2. 网关侧的硬边界:请求体超过 256 KiB 会被拒绝(body_too_large);路径含%(百分号编码)会被拒绝(防黑名单绕过,gateway.go);每次网关调用都有令牌桶限速,超限返回rate limit exceeded for this skill execution。网关测试覆盖见 gateway_test.go。

小结

Nightingale 的数据查询 POST 白名单是技能网关"只读安全模型"中的一个精心设计的例外:它以 JSON body 承载结构化查询、以datasource_id+cate定位数据源、以CheckDsPerm维持 RBAC 边界,最终把真实指标与日志数据安全地交付给技能脚本。掌握/query-range-batch/query-instant-batch/ds-query/logs-query这组端点及"先 brief 发现、再按 cate 查形状"的工作流,你就能编写出可靠、可审计的数据查询技能脚本。

【免费下载链接】nightingaleNightingale is to monitoring and alerting what Grafana is to visualization.项目地址: https://gitcode.com/GitHub_Trending/ni/nightingale

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 19:33:27

WindTerm文件上传功能详解与高效使用技巧

1. WindTerm文件上传功能深度解析WindTerm作为一款现代化的终端工具&#xff0c;其文件传输功能在日常开发运维工作中扮演着重要角色。不同于传统FTP客户端或SCP命令的繁琐操作&#xff0c;WindTerm内置的图形化文件传输界面让跨系统文件交换变得直观高效。我在实际使用中发现&…

作者头像 李华
网站建设 2026/9/15 19:33:06

慢病AI系统如何用可计算数学模块根治大模型幻觉问题

1. 问题拆解&#xff1a;慢病场景下&#xff0c;大模型幻觉为什么这么致命先说结论&#xff1a;慢病AI陪伴系统&#xff0c;和通用聊天机器人最大的区别在于&#xff0c;它犯错的代价完全不是一个量级。普通问答答错了&#xff0c;用户笑一笑就过去了&#xff1b;慢病场景里&am…

作者头像 李华
网站建设 2026/9/15 19:33:06

MIMO雷达主动波形设计:Matlab代码包解析与阻带抑制实现

简介&#xff1a;面向MIMO&#xff08;多入多出&#xff09;雷达与通信波形设计研究者和工程师的Matlab源码包&#xff0c;由李建团队编写&#xff0c;围绕主动感知系统波形设计的前七章内容展开&#xff0c;涵盖波形生成、性能评估、参数扫描等核心环节。压缩包共8个文件&…

作者头像 李华
网站建设 2026/9/15 19:32:20

VulnHub靶机mrrobot完整通关指南:从搭建到提权实战

VulnHub上的 mrrobot 靶机&#xff0c;这几年几乎是所有玩渗透测试入门的“必经一站”。很多朋友想练手&#xff0c;但往往卡在最前面的靶场搭建上&#xff0c;或者明明照着别人的通关笔记一步步操作&#xff0c;却死活打不通&#xff0c;最后只能放弃。其实这个靶机设计得非常…

作者头像 李华
网站建设 2026/9/15 19:31:02

ITIL4与DevOps融合下的真实交付实践

1. ITIL4发布计划背后的运维交付困境最近在梳理团队发布流程时&#xff0c;发现一个令人震惊的现象&#xff1a;超过90%的运维团队都存在"假交付"问题。这就像餐厅后厨把半成品直接端上桌&#xff0c;表面上完成了服务流程&#xff0c;实际上客户根本吃不到真正做熟的…

作者头像 李华