构建数据源插件
简介
Grafana 支持各种各样的 数据源,包括 Prometheus、MySQL 和 Datadog。但在某些情况下,您可能已经拥有一个内部指标解决方案,并希望将其添加到 Grafana 仪表板中。本教程将指导您构建一个新的数据源插件来查询数据。
在本教程中,您将
- 构建一个用于可视化正弦波的数据源
- 使用查询编辑器构建查询
- 使用配置编辑器配置数据源
先决条件
- Grafana v9.0 或更高版本
- LTS 版本的 Node.js
创建新的插件
Grafana 的 create-plugin 工具 是一个 CLI 应用程序,它简化了 Grafana 插件的开发,以便您专注于代码。该工具会为您构建一个启动插件、所有必需的配置以及使用 Docker Compose 的开发环境。
-
在新的目录中,使用 create-plugin 工具从模板创建插件。当提示您选择插件类型时,选择datasource:
npx @grafana/create-plugin@latest
-
转到新创建的插件的目录
cd <your-plugin>
-
安装依赖项
npm install
-
构建插件
npm run dev
-
启动 Grafana
docker compose up
- 打开 Grafana,默认情况下为 https://127.0.0.1:3000/,然后转到管理 > 插件。确保您的datasource插件存在。
您还可以通过检查日志来验证 Grafana 是否已发现您的插件
INFO[01-01|12:00:00] Plugin registered logger=plugin.loader pluginID=<your-plugin>
要了解如何创建后端数据源插件,请参阅 构建数据源后端插件
插件结构
您创建的每个插件至少需要两个文件:plugin.json
和 src/module.ts
。
plugin.json
Grafana 启动时,会扫描 插件目录 中任何包含 plugin.json
文件的子目录。plugin.json
文件包含有关插件的信息,并告诉 Grafana 插件需要哪些功能和依赖项。
虽然某些插件类型可以具有特定的配置选项,但让我们看一下必填项
type
告诉 Grafana 预期哪种类型的插件。Grafana 支持三种类型的插件:panel
、datasource
和app
。name
是用户在插件列表中看到的内容。如果您正在创建数据源,则通常是其连接到的数据库的名称,例如 Prometheus、PostgreSQL 或 Stackdriver。id
唯一标识您的插件,应遵循以下命名约定:<$organization-name>-<$plugin-name>-<$plugin-type>
。create-plugin 工具会根据您对提示的回复正确配置此项。
要查看 plugin.json
的所有可用配置设置,请参阅 plugin.json 模式。
module.ts
发现您的插件后,Grafana 会加载 module.js
文件,这是插件的入口点。module.js
公开插件的实现,这取决于您正在构建的插件类型。
具体来说,src/module.ts
需要导出一个扩展 GrafanaPlugin 的类,并且可以是以下任何一种
数据源插件
Grafana 中的数据源必须扩展 DataSourceApi
接口,这要求您定义两种方法:query
和 testDatasource
。
query
方法
query
方法是任何数据源插件的核心。它接受用户的查询,从外部数据库检索数据,并以 Grafana 识别的格式返回数据。
async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse>
options
对象包含用户发出的查询(或目标),以及上下文信息,例如当前时间间隔。使用此信息查询外部数据库。
测试您的数据源
testDatasource
为数据源实现了一个运行状况检查。例如,每当用户在更改连接设置后单击保存并测试按钮时,Grafana 都会调用此方法。
async testDatasource()
有关前端数据源中运行状况检查的示例,请参阅我们的 datasource-http 插件。
返回数据帧
有无数个不同的数据库,每个数据库都有自己的数据查询方式。为了能够支持所有不同的数据格式,Grafana 将数据整合到一个统一的数据结构中,称为 数据帧。
让我们看看如何从 query
方法创建和返回数据帧。在此步骤中,您将更改启动插件中的代码以返回 正弦波。
-
在当前的
query
方法中,删除map
函数内的代码。query
方法现在如下所示src/datasource.tsasync query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse> {
const { range } = options;
const from = range!.from.valueOf();
const to = range!.to.valueOf();
const data = options.targets.map(target => {
// Your code goes here.
});
return { data };
} -
在
map
函数中,使用lodash/defaults
包为未设置的查询属性设置默认值src/datasource.tsimport defaults from 'lodash/defaults';
const query = defaults(target, defaultQuery); -
在 datasource.ts 的顶部创建一个默认查询
src/datasource.tsexport const defaultQuery: Partial<MyQuery> = {
constant: 6.5,
}; -
创建一个具有时间字段和数字字段的数据帧
src/datasource.tsconst frame = new MutableDataFrame({
refId: query.refId,
fields: [
{ name: 'time', type: FieldType.time },
{ name: 'value', type: FieldType.number },
],
});需要将
refId
设置为告诉 Grafana 生成此日期帧的查询。
接下来,我们将向数据帧添加实际值。不用担心用于计算值的数学运算。
-
创建几个辅助变量
src/datasource.ts// duration of the time range, in milliseconds.
const duration = to - from;
// step determines how close in time (ms) the points will be to each other.
const step = duration / 1000; -
将值添加到数据帧
src/datasource.tsfor (let t = 0; t < duration; t += step) {
frame.add({ time: from + t, value: Math.sin((2 * Math.PI * t) / duration) });
}frame.add()
接受一个对象,其中键对应于数据帧中每个字段的名称。 -
返回数据帧
src/datasource.tsreturn frame;
-
通过创建新的数据源实例并构建仪表板来试用它。
您的数据源现在正在发送 Grafana 可以可视化的数据帧。接下来,我们将了解如何通过定义查询来控制正弦波的频率。
在此示例中,我们正在从当前时间范围生成时间戳。这意味着无论您使用什么时间范围,您都将获得相同的图形。在实践中,您将改为使用数据库返回的时间戳。
定义查询
大多数数据源都提供了一种查询特定数据的方法。MySQL 和 PostgreSQL 使用 SQL,而 Prometheus 拥有自己的查询语言,称为PromQL。无论您的数据库使用什么查询语言,Grafana 都允许您构建对它的支持。
通过实现您自己的查询编辑器(一个 React 组件,允许用户通过用户友好的图形界面构建自己的查询)来为数据源添加对自定义查询的支持。
查询编辑器可以像一个用户编辑原始查询文本的文本字段一样简单,也可以提供一个更用户友好的表单,其中包含下拉菜单和开关,然后在将其发送到数据库之前将其转换为原始查询文本。
定义查询模型
设计查询编辑器的第一步是定义其查询模型。查询模型定义了对数据源的用户输入。
我们希望能够控制正弦波的频率,因此让我们添加另一个属性。
-
向查询模型添加一个名为
frequency
的新数字属性src/types.tsexport interface MyQuery extends DataQuery {
queryText?: string;
constant: number;
frequency: number;
} -
为新的
frequency
属性设置默认值src/types.tsexport const defaultQuery: Partial<MyQuery> = {
constant: 6.5,
frequency: 1.0,
};
将模型绑定到表单
现在您已经定义了要支持的查询模型,下一步是将模型绑定到表单。FormField
是来自 grafana/ui
的文本字段组件,它允许您注册一个侦听器,该侦听器将在表单字段值更改时调用。
-
定义
query
对象中的frequency
,并在render
方法中向查询编辑器添加一个新的表单字段以控制新的frequency
属性。src/components/QueryEditor.tsxconst { queryText, constant, frequency } = query;
<InlineField label="Frequency" labelWidth={16}>
<Input onChange={onFrequencyChange} value={frequency || ''} />
</InlineField>; -
为新属性添加事件监听器。
src/components/QueryEditor.tsxconst onFrequencyChange = (event: ChangeEvent<HTMLInputElement>) => {
onChange({ ...query, frequency: parseFloat(event.target.value) });
// executes the query
onRunQuery();
};注册的监听器
onFrequencyChange
调用onChange
以使用表单字段中的值更新当前查询。onRunQuery();
告诉 Grafana 在每次更改后运行查询。对于快速查询,建议使用此方法以提供更灵敏的体验。
使用该属性
新的查询模型现在已准备好在我们 query
方法中使用。
-
在
query
方法中,使用frequency
属性调整我们的等式。src/datasource.tsframe.add({ time: from + t, value: Math.sin((2 * Math.PI * query.frequency * t) / duration) });
-
尝试更改面板查询中的频率来测试它。
为数据源启用配置
要访问特定数据源,您通常需要配置主机名、凭据或身份验证方法等内容。配置编辑器 允许您的用户配置您的数据源插件以满足他们的需求。
配置编辑器与查询编辑器类似,它定义一个模型并将其绑定到表单。
由于我们实际上并未在正弦波示例中连接到外部数据库,因此我们实际上不需要很多选项。但是,为了向您展示如何添加选项,我们将添加波形分辨率作为选项。
分辨率控制数据点彼此之间的时间间隔。更高的分辨率意味着更多点更靠近,但代价是需要处理更多数据。
定义选项模型
-
在选项模型中添加一个名为
resolution
的新数字属性。src/types.tsexport interface MyDataSourceOptions extends DataSourceJsonData {
path?: string;
resolution?: number;
}
将模型绑定到表单
就像查询编辑器一样,配置编辑器中的表单字段在值更改时调用注册的监听器。
-
在查询编辑器中添加一个新的表单字段以控制新的分辨率选项。
src/components/ConfigEditor.tsx<InlineField label="Resolution" labelWidth={12}>
<Input onChange={onResolutionChange} value={jsonData.resolution || ''} placeholder="Enter a number" width={40} />
</InlineField> -
为新选项添加事件监听器。
src/components/ConfigEditor.tsxconst onResolutionChange = (event: ChangeEvent<HTMLInputElement>) => {
const jsonData = {
...options.jsonData,
resolution: parseFloat(event.target.value),
};
onOptionsChange({ ...options, jsonData });
};onResolutionChange
监听器调用onOptionsChange
以使用表单字段中的值更新当前选项。
使用该选项
-
为
DataSource
类创建一个名为resolution
的属性。src/datasource.tsexport class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
resolution: number;
constructor(instanceSettings: DataSourceInstanceSettings<MyDataSourceOptions>) {
super(instanceSettings);
this.resolution = instanceSettings.jsonData.resolution || 1000.0;
}
// ... -
在
query
方法中,使用resolution
属性更改我们计算步长的方式。src/datasource.tsconst step = duration / this.resolution;
-
尝试配置一个新的数据源并更改分辨率的值来测试它。
总结
在本教程中,您构建了一个完整的 Grafana 数据源插件,该插件使用查询编辑器来控制要可视化的数据。您添加了一个数据源选项,通常用于设置连接选项等。
了解更多
从外部 API 获取数据
Grafana 中的大多数数据源都将从外部 API 返回数据。本教程试图使事情保持简单,并且不需要额外的服务。要了解如何实现这一点,请使用 datasource-http 示例。
此示例展示了如何使用来自 grafana-runtime
包 的 getBackendSrv
函数。
虽然您可以使用诸如 axios 或 Fetch API 之类的东西来发出请求,但我们建议使用 getBackendSrv
,因为它通过 Grafana 服务器代理请求,而不是从浏览器发出请求。在向外部 API 发出经过身份验证的请求时,我们强烈建议这样做。有关外部请求身份验证的更多信息,请参阅 为数据源插件添加身份验证。
提高插件的质量
要了解有关高级插件开发主题的更多信息,请参阅以下内容