grafana-foundation-sdk

Polar Sponsor
爱发电 赞助
.NET 9.0

使用 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:

  1. SDK 处于 v0.0.x 阶段(公测版) —— Grafana Labs 已在生产环境使用,但各版本间 API 可能变动。请务必显式锁定版本。推荐用于 Grafana >= 12,亦兼容 Grafana >= 10。

  2. Prometheus 中 instant() 与 range() 互斥 —— 调用 .instant() 会同时设置 instant=true 和 range=false;调用 .range() 则相反。如需两者共存,请改用 .rangeAndInstant()。

  3. Loki 的 range()/instant() 已弃用 —— 请改用 .queryType('range') 或 .queryType('instant')。同理,.resolution() 已被 .step() 替代。

  4. 首个阈值步骤必须设为 value: null —— 此为基准/默认颜色。若遗漏将导致生成非法 JSON。

  5. 面板 ID 自动分配 —— 你无需手动设置面板的 id 字段,Grafana 在导入时自动分配。同理,gridPos.x/y 由 height() 和 span() 自动计算得出。

  6. 转换(Transformations)为原始对象 —— SDK 当前未提供类型化转换构建器。请通过 .withTransformation() 传入原始 { id, options } 对象。

  7. CustomVariable 的特殊行为 —— 当通过 Grafana API 预配时,CustomVariableBuilder 必须设置 .query() 字段(以逗号分隔的 key:value 形式,例如 'All : .+, Error : error'),否则选项无法持久化,即使同时调用了 .values()。

  8. Go:必须使用 cog.ToPtr() —— 许多结构体字段为指针类型。对可空字段(如阈值、数据源引用等)应使用 cog.ToPtr[T](value)。TypeScript 无此限制。

  9. Go:Build() 返回 error —— 必须检查其返回值。而 TypeScript 的 .build() 直接返回对象,并通过编译期类型检查保障安全性。

  10. 插件类数据源暂无类型化查询构建器 —— 仅核心数据源(Prometheus、Loki、Tempo、Elasticsearch、CloudWatch 等)具备构建器。对于第三方插件,需自行实现 Builder 接口定义自定义查询类型。

  11. 仪表板 Schema v1 与 v2 —— 本技能面向 v1 仪表板(@grafana/grafana-foundation-sdk/dashboard,Kubernetes apiVersion dashboard.grafana.app/v1beta1)。新版 v2 Schema 以 dashboardv2beta1 形式发布(Kubernetes apiVersion dashboard.grafana.app/v2beta1),并配备独立构建器。目前 v2beta1 仍在稳定化过程中,存在已知问题(如转换、注解定位、Go 中 SQL 表达式支持等)——除非明确需要 v2 的布局能力,否则优先选用 v1。多数查询/面板构建器在 v1/v2 间共享;部分构建器提供 QueryV2Builder/VisualizationV2Builder 变体以支持 v2。

  12. 构建器仅在接入 tsconfig 时才受类型检查 —— SDK 仅当生成器文件实际被 tsconfig 包含并执行类型检查时,才能提供编译期安全保障。若生成器位于非包目录下(例如 Helm Chart 目录),且无 tsconfig 引用,则该文件将静默跳过类型检查,错误仅在运行 .build() 时暴露。此外:SDK 输出目标为 ES2024/bundler 模块解析,旧版全局 tsc 无法处理 —— 请始终使用项目本地编译器(npx tsc),而非陈旧的全局版本。

  13. 每次修改生成器后必须重新生成 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 的完整示例

相关专题

更多
Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

2026.11.06

0

12

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

2026.11.06

0

13

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

2026.11.06

0

10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

2026.11.05

0

12

DBeaver安全防护教程大全
DBeaver安全防护教程大全

DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。

2026.11.05

0

12

DBeaver连接创建与配置教程
DBeaver连接创建与配置教程

本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。

2026.11.04

0

16

XORM框架结构体映射与表结构同步
XORM框架结构体映射与表结构同步

本专题围绕XORM框架的结构体映射展开,说明表名与字段的命名策略、xorm标签常用属性、主键自增与时间字段自动填充,并演示Sync2自动建表、增量字段升级、索引声明与反向生成结构体的完整流程。

2026.11.04

0

15

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

2026.11.04

0

15

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

2026.11.04

0

16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.1万人学习