构建数据源后端插件
简介
Grafana 支持各种 数据源,包括 Prometheus、MySQL 和 Datadog。但在某些情况下,您可能已经拥有一个内部指标解决方案,并希望将其添加到 Grafana 仪表板中。本教程将教您构建一个新的数据源插件来查询数据。
后端组件为您的插件提供了许多额外的功能,例如自定义身份验证方法。要了解更多信息,请参阅关于 后端插件 的文档。
在本教程中,您将
- 为您的数据源构建 后端
- 为您的数据源实现健康检查
- 为您的数据源启用 Grafana 告警
先决条件
创建一个新插件
Grafana create-plugin 工具是一个 CLI 应用程序,可简化 Grafana 插件开发,让您可以专注于代码。该工具为您搭建了一个入门插件、所有必需的配置以及使用 Docker Compose 的开发环境。
-
在一个新目录中,使用 create-plugin 工具从模板创建一个插件。当提示插件类型时,选择并对“您是否想要插件的后端部分?”回答是。
npx @grafana/create-plugin@latest
-
转到您新创建的插件的目录
cd <your-plugin>
-
安装依赖项
npm install
-
构建插件前端
npm run dev
-
在一个新的终端窗口中,构建插件后端
mage -v build:linux
-
启动 Grafana
docker compose up
-
打开 Grafana,默认地址为 https://127.0.0.1:3000,然后转到 管理 > 插件。确保您的插件在那里。
您还可以通过检查日志来验证 Grafana 是否已发现该插件
INFO[01-01|12:00:00] Plugin registered logger=plugin.loader pluginID=<your-plugin>
现在,让我们验证一下,当创建新的数据源时,您到目前为止构建的插件是否可以在 Grafana 中使用
- 在侧边菜单中,转到 连接 > 数据源。
- 单击 添加数据源。
- 搜索您新创建的插件的名称并选择它。
- 输入名称,然后单击 保存 & 测试。如果出现“随机错误”,您可以忽略它 - 这是 健康检查 的结果,将在下面进一步解释。
您现在拥有一个新的数据源实例,您的插件已准备好在仪表板中使用。
要将数据源添加到仪表板
- 创建一个新的仪表板并添加一个新的面板。
- 在查询选项卡上,选择您刚刚创建的数据源。将渲染一个折线图,其中包含由两个数据点组成的一个系列。
- 保存仪表板。
故障排除
Grafana 没有加载我的插件
确保 Grafana 已在开发模式下启动。如果您从源代码运行 Grafana,请将以下行添加到您的 conf/custom.ini
文件中
app_mode = development
如果您还没有 conf/custom.ini
文件,请在继续之前创建它。
然后,您可以通过在 Grafana 仓库根目录中运行 make run & make run-frontend
以开发模式启动 Grafana。
如果您从二进制文件或 Docker 容器内部运行 Grafana,您可以通过将环境变量 GF_DEFAULT_APP_MODE
设置为 development
以开发模式启动它。
后端插件的结构
用于构建数据源的后端的文件夹和文件是
文件/文件夹 | 描述 |
---|---|
Magefile.go | 使用 mage 构建文件不是必需的,但我们强烈建议您使用它们,以便您可以使用插件 SDK 提供的构建目标。 |
/go.mod | Go 模块依赖项。 |
/src/plugin.json | 描述插件的 JSON 文件。 |
/pkg/main.go | 插件二进制文件的起点。 |
plugin.json 文件
plugin.json
文件是所有插件都必需的。构建后端插件时,请特别注意以下属性
属性 | 描述 |
---|---|
backend | 对于后端插件,设置为 true 。这告诉 Grafana 在加载插件时应启动二进制文件。 |
executable | 这是 Grafana 期望启动的可执行文件的名称。有关详细信息,请参阅 plugin.json 参考。 |
alerting | 如果您的后端数据源支持告警,则设置为 true 。需要将 backend 设置为 true 。 |
在下一步中,我们将查看查询端点!
实现数据查询
我们首先打开文件 /pkg/plugin/datasource.go
。在此文件中,您将看到 Datasource
结构体,它实现了 backend.QueryDataHandler 接口。此结构体上的 QueryData
方法是数据源插件进行数据获取的地方。
每个请求都包含多个查询,以减少 Grafana 和插件之间的流量。因此,您需要循环遍历查询切片,处理每个查询,然后返回所有查询的结果。
在本教程中,我们提取了一个名为 query
的方法来处理每个查询模型。由于每个插件都有自己唯一的查询模型,因此 Grafana 以 JSON 格式将其发送到后端插件。因此,插件需要将查询模型 Unmarshal
为更易于处理的形式。
正如您所见,示例仅返回静态数字。尝试扩展插件以返回其他类型的数据。
例如,要生成三个在时间上均匀分布的浮点数,您可以使用以下代码替换生成的两个静态数字
duration := query.TimeRange.To.Sub(query.TimeRange.From)
mid := query.TimeRange.From.Add(duration / 2)
s := rand.NewSource(time.Now().UnixNano())
r := rand.New(s)
lowVal := 10.0
highVal := 20.0
midVal := lowVal + (r.Float64() * (highVal - lowVal))
// add fields.
frame.Fields = append(frame.Fields,
data.NewField("time", nil, []time.Time{query.TimeRange.From, mid, query.TimeRange.To}),
data.NewField("values", nil, []float64{lowVal, midVal, highVal}),
)
您可以阅读更多关于如何在我们的文档中 构建数据帧 的信息。
添加对健康检查的支持
实现健康检查处理程序允许 Grafana 验证数据源是否已正确配置。
在 Grafana 的 UI 中编辑数据源时,您可以单击 保存 & 测试 以验证它是否按预期工作。
在这个示例数据源中,健康检查有 50% 的几率成功。确保返回适当的错误消息给用户,告知他们数据源中配置错误的内容。
打开 /pkg/plugin/datasource.go
。在此文件中,您将看到 Datasource
结构体也实现了 backend.CheckHealthHandler 接口。转到 CheckHealth
方法以查看此示例插件的健康检查是如何实现的。
要了解更多信息,请参阅我们的 示例仓库 中的其他健康检查实现。
添加身份验证
实现身份验证允许您的插件访问受保护的资源,如数据库或 API。要了解有关如何使用后端插件进行身份验证的更多信息,请参阅 我们的文档。
启用 Grafana 告警
-
添加顶层
alerting
属性,其值为true
,以指定您的插件支持 Grafana 告警,例如src/plugin.json{
...
"backend": true,
"executable": "gpx_simple_datasource_backend",
"alerting": true,
"info": {
...
} -
重启您的 Grafana 实例。
-
在您的 Web 浏览器中打开 Grafana。
-
验证告警现在是否受支持,方法是导航到您创建的数据源。您应该在“设置”视图中看到“支持告警”消息。
创建告警
以下说明基于 Grafana v10.1.1,有关适用于您版本的告警指南,请查阅 文档。
- 打开您在创建一个新插件步骤中创建的仪表板。
- 编辑现有面板。
- 单击面板下方的告警选项卡。
- 单击从此面板创建告警规则按钮。
- 在表达式部分中,在阈值表达式
C
中,将高于设置为15
。 - 在阈值表达式
C
上单击设置为告警条件。您的告警现在应如下所示。表达式部分显示 B“reduce”,输入:A,函数:Last,模式:Strict,C 阈值,输入:B,高于:15,并启用告警条件指示器 - 在设置告警评估行为部分中,单击新建文件夹按钮并创建一个新文件夹来存储评估规则。
- 然后,单击新建评估组按钮并创建一个新的评估组;选择一个名称并将评估间隔设置为
10s
。 - 单击保存规则并退出按钮。
- 保存仪表板。一段时间后,告警规则评估并转换为告警中状态。
并发运行多个查询
此功能仅适用于 Grafana 后端插件 SDK 版本 0.232.0 及更高版本。
默认情况下,单个请求(即,在一个面板内)中的多个查询是按顺序执行的。要并发运行多个查询,您可以使用 SDK 公开的 concurrent.QueryData
函数。
要使用 concurrent.QueryData
,请指定如何执行单个查询以及要运行的并发查询数量的限制。请注意,最大并发查询数为 10 个。
import (
...
"github.com/grafana/grafana-plugin-sdk-go/experimental/concurrent"
...
)
func (d *Datasource) handleSingleQueryData(ctx context.Context, q concurrent.Query) (res backend.DataResponse) {
// Implement the query logic here
}
func (d *Datasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
return concurrent.QueryData(ctx, req, d.handleSingleQueryData, 10)
}
总结
在本教程中,您为您的数据源插件创建了一个后端。