使用 grafana-foundation-sdk 的类型化构建器(TypeScript 或 Go),以代码方式构建 Grafana 仪表板。适用于创建、修改或生成 Grafana 仪表板。
Grafana Foundation SDK.
功能概述
Grafana Foundation SDK.是一项面向实际任务的技能,主要用于Grafana-foundation-sdk 提供了强大的打字器库,用于定义 Grafana 仪表板为代码. 而不是写原 JSON(它容易出错,而且很硬)。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。
核心要点
- 使用时应结合输入条件选择合适的执行方式,核对必要参数、依赖环境与输出内容,并按原始要求处理异常情况。
- 该技能适合需要稳定复用相关能力的场景,可作为自动化工作流的一部分,也便于后续检查、调整和扩展。
- 从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。
使用与执行
实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。
结果检查与注意事项
执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。
Grafana Foundation SDK
grafana-foundation-sdk 提供强类型的构建器库,用于以代码方式定义 Grafana 仪表板。相比直接编写原始 JSON(易出错且在 diff 中难以评审),你可通过链式调用构建器方法来组装仪表板,最终生成合法的 Grafana JSON。
该 SDK 由 Grafana 内部 CUE 模式通过 cog 工具自动生成,支持 Go、TypeScript、Python、PHP 和 Java。本技能聚焦于 TypeScript(主语言)和 Go(次选语言),因为这是基础设施团队最常用的技术栈。
适用场景
- 从零开始创建新的 Grafana 仪表板
- 将已有的手写仪表板 JSON 迁移为类型安全的代码
- 向仪表板中添加面板、变量或查询
- 构建可复用的仪表板组件(例如封装常见面板模式的辅助函数)
- 基于服务列表或配置动态生成仪表板
安装
SDK 以具体的 v0.0.x 版本标签发布(最新版:v0.0.16)。请显式锁定版本——当前处于 v1.0 前阶段,各版本间 API 可能发生变更(参见“已知注意事项”)。
TypeScript:
npm install '@grafana/grafana-foundation-sdk@~0.0.16' # 或 pnpm add '@grafana/grafana-foundation-sdk@~0.0.16'
Go:
go get github.com/grafana/grafana-foundation-sdk/go@v0.0.16
核心架构
所有功能均遵循 构建器模式(Builder Pattern):创建构建器实例 → 链式调用配置方法 → 调用 .build()(TypeScript)或 .Build()(Go)生成最终对象。输出为标准 Grafana 仪表板 JSON,完全兼容 Grafana API、文件式预配(file-based provisioning)及 Kubernetes ConfigMap。
每种面板类型、查询类型和变量类型均位于独立包中,仅需导入所需模块:
// 各关注点对应独立导入
import { DashboardBuilder, RowBuilder } from '@grafana/grafana-foundation-sdk/dashboard';
import { PanelBuilder as TimeseriesBuilder } from '@grafana/grafana-foundation-sdk/timeseries';
import { PanelBuilder as StatBuilder } from '@grafana/grafana-foundation-sdk/stat';
import { DataqueryBuilder as PromQueryBuilder } from '@grafana/grafana-foundation-sdk/prometheus';
import { DataqueryBuilder as LokiQueryBuilder } from '@grafana/grafana-foundation-sdk/loki';
快速上手 —— TypeScript
import { DashboardBuilder, RowBuilder, QueryVariableBuilder } from '@grafana/grafana-foundation-sdk/dashboard';
import { PanelBuilder as StatBuilder } from '@grafana/grafana-foundation-sdk/stat';
import { PanelBuilder as TimeseriesBuilder } from '@grafana/grafana-foundation-sdk/timeseries';
import { DataqueryBuilder } from '@grafana/grafana-foundation-sdk/prometheus';
import * as common from '@grafana/grafana-foundation-sdk/common';
const dashboard = new DashboardBuilder('My Service Overview')
.uid('my-service-overview')
.tags(['my-service'])
.editable()
.refresh('30s')
.time({ from: 'now-24h', to: 'now' })
.timezone('browser')
.withVariable(
new QueryVariableBuilder('service')
.label('Service')
.query('label_values(up{namespace="default"}, job)')
.datasource({ type: 'prometheus', uid: 'prometheus' })
.refresh(1)
.includeAll(true)
.allValue('.*')
.sort(1)
)
.withRow(new RowBuilder('Overview'))
.withPanel(
new StatBuilder()
.title('Request Rate')
.datasource({ type: 'prometheus', uid: 'prometheus' })
.withTarget(
new DataqueryBuilder()
.expr('sum(rate(http_requests_total{job=~"$service"}[5m]))')
.legendFormat('req/s')
)
.unit('reqps')
.decimals(1)
.height(4)
.span(6)
.colorMode(common.BigValueColorMode.Background)
.graphMode(common.BigValueGraphMode.Area)
.reduceOptions(
new common.ReduceDataOptionsBuilder().calcs(['lastNotNull'])
)
)
.withPanel(
new TimeseriesBuilder()
.title('Request Rate Over Time')
.datasource({ type: 'prometheus', uid: 'prometheus' })
.withTarget(
new DataqueryBuilder()
.expr('sum by (job)(rate(http_requests_total{job=~"$service"}[5m]))')
.legendFormat('{{job}}')
)
.unit('reqps')
.fillOpacity(15)
.height(8)
.span(12)
);
// 输出仪表板 JSON
console.log(JSON.stringify(dashboard.build(), null, 2));
关键模式
1. 封装重复的面板配置逻辑
使用 SDK 最大的收益在于创建可复用的辅助函数,将团队约定固化为代码:
function promDs() {
return { type: 'prometheus', uid: 'prometheus' } as const;
}
function lokiDs() {
return { type: 'loki', uid: 'loki' } as const;
}
function promQuery(expr: string, legend?: string) {
const q = new DataqueryBuilder().expr(expr);
if (legend) q.legendFormat(legend);
return q;
}
function statPanel(title: string, expr: string, opts?: { unit?: string; decimals?: number; color?: string }) {
const panel = new StatBuilder()
.title(title)
.datasource(promDs())
.withTarget(promQuery(expr))
.height(4)
.span(4)
.colorMode(common.BigValueColorMode.Background)
.graphMode(common.BigValueGraphMode.Area)
.reduceOptions(new common.ReduceDataOptionsBuilder().calcs(['lastNotNull']));
if (opts?.unit) panel.unit(opts.unit);
if (opts?.decimals !== undefined) panel.decimals(opts.decimals);
// 如需设置阈值,可调用 .thresholds()
return panel;
}
2. 模板变量
// 查询变量 —— 从 Prometheus 标签中动态填充
new QueryVariableBuilder('service')
.label('Service')
.query('label_values(http_server_duration_count{namespace="x402"}, job)')
.datasource({ type: 'prometheus', uid: 'prometheus' })
.refresh(2) // 1=仪表板加载时刷新,2=时间范围变更时刷新
.includeAll(true)
.allValue('.*')
.sort(1) // 1=按字母升序
// 自定义变量 —— 静态键值对
new CustomVariableBuilder('level')
.label('Log Level')
.query('All : .+, Error : error|fatal, Warning : warn, Info : info, Debug : debug')
.current({ text: 'All', value: '.+' })
在查询中引用变量时,使用标准 Grafana 语法:$service、$__range、$__rate_interval、$__auto。
3. 面板尺寸控制
面板使用 height(h)(网格行数)与 span(w)(24 列栅格中的列宽)控制布局:
- 全宽:
.span(24) - 半宽:
.span(12) - 三分之一宽:
.span(8) - 四分之一宽:
.span(6) - 典型 stat 面板:
.height(4).span(4) - 典型 timeseries 面板:
.height(8).span(12)
4. 阈值(Thresholds)
import { ThresholdsConfigBuilder } from '@grafana/grafana-foundation-sdk/dashboard';
// 第一个步骤必须设为 null(作为基础色)
new StatBuilder()
.thresholds(
new ThresholdsConfigBuilder()
.mode(common.ThresholdsMode.Absolute)
.steps([
{ value: null as any, color: 'green' },
{ value: 80, color: 'yellow' },
{ value: 95, color: 'red' },
])
)
5. 字段覆盖(Field Overrides)
new TimeseriesBuilder()
.overrideByName('Revenue', [
{ id: 'color', value: { fixedColor: 'green', mode: 'fixed' } },
])
.overrideByRegexp('.*5..', [
{ id: 'color', value: { fixedColor: 'red', mode: 'fixed' } },
])
6. 行(Rows),包括折叠行
// 普通行
.withRow(new RowBuilder('Traffic'))
// 折叠行(含嵌套面板)
.withRow(
new RowBuilder('Business Details')
.collapsed()
.withPanel(/* ... */)
.withPanel(/* ... */)
)
7. Loki 日志与指标查询
import { DataqueryBuilder as LokiQueryBuilder } from '@grafana/grafana-foundation-sdk/loki';
// 日志查询
new LokiQueryBuilder()
.expr('{namespace="x402", app=~"$service", level=~"$level"}')
.refId('A')
// 从日志中提取指标
new LokiQueryBuilder()
.expr('sum by (buyer_wallet)(count_over_time({namespace="x402"} | event="request" [$__range]))')
.legendFormat('{{buyer_wallet}}')
.refId('A')
8. 数据转换(Transformations)
由于 SDK 尚未为全部转换类型提供类型化构建器,因此转换需以原始对象形式传入:
new TableBuilder()
.withTransformation({
id: 'reduce',
options: {
reducers: ['lastNotNull'],
mode: 'seriesToRows',
includeTimeField: false,
labelsToFields: true,
},
})
.withTransformation({
id: 'organize',
options: {
excludeByName: { Field: true },
renameByName: { buyer_wallet: 'Buyer Wallet', 'Last not null': 'Requests' },
},
})
.withTransformation({
id: 'sortBy',
options: { sort: [{ field: 'Requests', desc: true }] },
})
生成输出
.build() 方法返回一个符合 Grafana 仪表板 JSON Schema 的纯对象。你可以按需序列化:
// 标准 JSON 文件(用于预配或 ConfigMap)
const fs = require('fs');
const dashboard = builder.build();
fs.writeFileSync('dashboard.json', JSON.stringify(dashboard, null, 2));
// Kubernetes 资源清单(适配 Grafana 的 k8s API)
const manifest = {
apiVersion: 'dashboard.grafana.app/v1beta1',
kind: 'Dashboard',
metadata: { name: dashboard.uid },
spec: dashboard,
};
console.log(JSON.stringify(manifest, null, 2));
已知注意事项
以下问题源自真实使用经验及 SDK 仓库的公开 issue:
SDK 处于 v0.0.x 阶段(公测版) —— Grafana Labs 已在生产环境使用,但各版本间 API 可能变动。请务必显式锁定版本。推荐用于 Grafana >= 12,亦兼容 Grafana >= 10。
Prometheus 中
instant()与range()互斥 —— 调用.instant()会同时设置instant=true和range=false;调用.range()则相反。如需两者共存,请改用.rangeAndInstant()。Loki 的
range()/instant()已弃用 —— 请改用.queryType('range')或.queryType('instant')。同理,.resolution()已被.step()替代。首个阈值步骤必须设为
value: null—— 此为基准/默认颜色。若遗漏将导致生成非法 JSON。面板 ID 自动分配 —— 你无需手动设置面板的
id字段,Grafana 在导入时自动分配。同理,gridPos.x/y由height()和span()自动计算得出。转换(Transformations)为原始对象 —— SDK 当前未提供类型化转换构建器。请通过
.withTransformation()传入原始{ id, options }对象。CustomVariable 的特殊行为 —— 当通过 Grafana API 预配时,
CustomVariableBuilder必须设置.query()字段(以逗号分隔的 key:value 形式,例如'All : .+, Error : error'),否则选项无法持久化,即使同时调用了.values()。Go:必须使用
cog.ToPtr()—— 许多结构体字段为指针类型。对可空字段(如阈值、数据源引用等)应使用cog.ToPtr[T](value)。TypeScript 无此限制。Go:
Build()返回 error —— 必须检查其返回值。而 TypeScript 的.build()直接返回对象,并通过编译期类型检查保障安全性。插件类数据源暂无类型化查询构建器 —— 仅核心数据源(Prometheus、Loki、Tempo、Elasticsearch、CloudWatch 等)具备构建器。对于第三方插件,需自行实现
Builder接口定义自定义查询类型。仪表板 Schema v1 与 v2 —— 本技能面向 v1 仪表板(
@grafana/grafana-foundation-sdk/dashboard,Kubernetes apiVersiondashboard.grafana.app/v1beta1)。新版 v2 Schema 以dashboardv2beta1形式发布(Kubernetes apiVersiondashboard.grafana.app/v2beta1),并配备独立构建器。目前 v2beta1 仍在稳定化过程中,存在已知问题(如转换、注解定位、Go 中 SQL 表达式支持等)——除非明确需要 v2 的布局能力,否则优先选用 v1。多数查询/面板构建器在 v1/v2 间共享;部分构建器提供QueryV2Builder/VisualizationV2Builder变体以支持 v2。构建器仅在接入 tsconfig 时才受类型检查 —— SDK 仅当生成器文件实际被
tsconfig包含并执行类型检查时,才能提供编译期安全保障。若生成器位于非包目录下(例如 Helm Chart 目录),且无tsconfig引用,则该文件将静默跳过类型检查,错误仅在运行.build()时暴露。此外:SDK 输出目标为 ES2024/bundler模块解析,旧版全局tsc无法处理 —— 请始终使用项目本地编译器(npx tsc),而非陈旧的全局版本。每次修改生成器后必须重新生成 JSON —— 实际部署的仪表板是生成的 JSON 文件,而非
.ts/.go源码。编辑生成器后,需重新运行生成脚本,并将新生成的 JSON 一并提交;切勿手动编辑生成的 JSON(下次生成将静默覆盖)。建议在仓库规范中加入“禁止直接编辑仪表板 JSON”的规则。
项目特定上下文
在本项目中,仪表板通过 monitoring-deps Helm Chart 以 Kubernetes ConfigMap 方式预配:
- 仪表板 JSON 文件存放于
ops/helmfile-infra/charts/monitoring-deps/dashboards/ templates/dashboards.yaml将每个 JSON 文件包装为带grafana_dashboard: "1"标签的 ConfigMap- 数据源:Prometheus(
uid: "prometheus")和 Loki(uid: "loki") - 标准命名空间过滤器:
namespace="x402" - 常用模板变量:
$service(job 选择器)、$level(日志级别)
为本项目生成仪表板时,请将生成的 JSON 输出至 dashboards/ 目录,并确保 ConfigMap 模板正确引用该文件。
参考文件
如需完整 API 参考与示例,请查阅:
references/typescript-api.md—— 完整 TypeScript API 文档,涵盖全部面板类型、查询构建器及配置选项references/patterns.md—— 常见仪表板模式、实践配方,以及将本项目现有仪表板迁移至 SDK 的完整示例
热门AI工具
相关专题
本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。
0
2026.11.12
本专题围绕Go-Zero的安装与工具链配置展开,讲清Go版本要求、goctl安装方式、代理镜像、protoc依赖与环境变量设置,说明多版本共存、升级回退与CI流水线安装的做法,并整理安装阶段的常见报错与验证步骤。
0
2026.11.12
本专题整理Go-Zero的入门知识,从框架定位、环境准备到跑通第一个API服务,讲清目录分层、配置加载、日志与中间件的基本用法,并对比Gin、Kratos的差异,帮助Go开发者建立整体认知,判断它是否适合当前项目。
0
2026.11.12
本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。
0
2026.11.06
围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。
0
2026.11.06
详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。
0
2026.11.06
DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。
0
2026.11.05
DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。
0
2026.11.05
本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。
0
2026.11.04
热门下载
相关下载
精品课程
共6课时 | 12.1万人学习
共79课时 | 161.8万人学习
共6课时 | 54.7万人学习
最新文章