构建一个数据源插件

bob电竞频道Grafana实验室团队
Grabob电竞频道fana实验室团队

最后更新于2022年11月15日

初学者

简介

Grafana支持广泛的数据源,包括Prometheus、MySQL,甚至datdogg。你很有可能已经从你所设置的系统中可视化了指标。不过,在某些情况下,您已经有了想要添加到Grafana仪表板中的内部度量解决方案。本教程将教会您如何构建对数据源的支持。

在本教程中,您将:

  • 构建一个数据源来可视化正弦波
  • 使用查询编辑器构造查询
  • 使用配置编辑器配置数据源

先决条件

  • Grafana > = 7.0
  • NodeJS > = 14

设置您的环境

在开始构建插件之前,需要为插件开发设置环境。

为了发现插件,Grafana扫描a插件目录,它的位置取决于你的操作系统。

  1. 创建一个名为grafana-plugins在您首选的工作空间中。

  2. 找到插件属性,并设置插件财产的路径你grafana-plugins目录中。请参阅Grafana配置文档更多信息。

    [paths] plugins = "/path/to/grafana-plugins"
  3. 如果Grafana已经在运行,则重新启动它,以加载新的配置。

可选方法:Docker

如果不想在本地机器上安装Grafana,可以使用码头工人

使用Docker建立Grafana插件开发,运行以下命令:

运行-d -p 3000:3000 -v "$(pwd)"/ var/lib/grafana/plugins——name=grafana grafana/grafana:7.0.0 .

由于Grafana只在启动时加载插件,所以在添加或删除插件时需要重新启动容器。

Docker重启grafana

创建一个新插件

现代web开发的工具很难让你理解。虽然您当然可以编写自己的webpack配置,但在本指南中,您将使用grafana create-plugin工具

Grafanacreate-plugin工具是一个CLI应用程序,它简化了Grafana插件的开发,因此您可以专注于代码。该工具为您提供了启动器插件和所有所需的配置。

  1. 在插件目录中,使用create-plugin从模板创建一个插件:

    npx @grafana / create-plugin
  2. 更改目录到你新创建的插件:

    cd my-plugin
  3. 安装依赖项:

    线安装
  4. 编译插件:

    纱线开发
  5. 重新启动Grafana服务器以发现您的插件。

  6. 打开Grafana然后去配置->插件.确保你的插件在那里。

默认情况下,Grafana在发现插件时记录日志:

INFO[01-01|12:00:00] registered plugin logger=plugins name=my-plugin . INFO[01-01|12:00:00

插件的剖析

插件有不同的形状和大小。在我们深入讨论之前,让我们看看它们共有的一些属性。

你创建的每个插件都至少需要两个文件:plugin.json而且module.ts

plugin.json

当Grafana启动时,它会扫描插件目录中包含plugin.json文件。的plugin.json文件包含关于你的插件的信息,并告诉Grafana你的插件需要什么功能和依赖。

虽然某些插件类型可以有特定的配置选项,但让我们看看强制性的配置选项:

  • 类型告诉Grafana应该期待什么类型的插件。Grafana支持三种类型的插件:面板数据源,应用程序
  • 的名字是用户将在插件列表中看到的内容。如果您正在创建一个数据源,这通常是它所连接的数据库的名称,例如Prometheus、PostgreSQL或Stackdriver。
  • id唯一标识您的插件,并应以您的Grafana用户名开始,以避免与其他插件冲突。注册一个Grafana账户来声明您的用户名。

控件的所有可用配置设置plugin.json,请参阅plugin.jsonSchema

module.ts

发现插件后,Grafana加载module.ts文件,你的插件的入口点。module.ts公开插件的实现,这取决于您正在构建的插件的类型。

具体地说,module.ts需要公开扩展的对象GrafanaPlugin,可以是以下任何一个:

数据源插件

Grafana中的数据源必须扩展DataSourceApi接口,它要求您定义两个方法:查询而且testDatasource

查询方法

查询方法是任何数据源插件的核心。它接受来自用户的查询,从外部数据库检索数据,并以Grafana可识别的格式返回数据。

async查询(选项:DataQueryRequest): Promise

选项对象包含查询,或者目标,以及上下文信息,如当前时间间隔。使用此信息查询外部数据库。

这个词目标起源于Graphite,早期的Grafana是唯一受支持的数据源。随着Grafana获得对更多数据源的支持,术语“目标”成为任何类型查询的同义词。

测试数据源

testDatasource为数据源实现运行状况检查。例如,每当用户单击保存和测试按钮,更改连接设置后。

异步testDatasource ()

数据帧

现在有无数不同的数据库,每一个都有自己的查询数据的方法。为了能够支持所有不同的数据格式,Grafana将数据合并为一个统一的数据结构,称为数据帧

方法创建和返回数据帧查询方法。在这一步中,您将更改starter插件中的代码以返回一个正弦波

  1. 在水流中查询方法中删除代码地图函数。

    查询方法现在看起来像这样:

    async query(options: DataQueryRequest): Promise {const {range} = options;const from = range!.to.valueOf();Const data = options.targets。地图(target => { // Your code goes here. }); return { data }; }
  2. 地图函数,使用lodash /违约包用于为未设置的查询属性设置默认值:

    const query = defaults(target, defaultQuery);
  3. 创建一个包含时间字段和数字字段的数据帧:

    const frame = new MutableDataFrame({refId: query.)refId,字段:[{name: 'time',类型:FieldType。time}, {name: 'value',类型:FieldType。Number},],});

    refId需要设置来告诉Grafana是哪个查询生成了这个日期帧。

接下来,我们将向数据帧添加实际值。不要担心用于计算值的数学。

  1. 创建两个辅助变量:

    //时间范围的持续时间,单位为毫秒。Const duration = to - from;// step决定点之间的时间距离(ms)。Const step = duration / 1000;
  2. 将值添加到数据帧中:

    For (let t = 0;T < duration;T += step){帧。add({时间:从+ t,值:数学。sin(2 *数学。)PI * t) /持续时间)});}

    frame.add ()接受一个对象,其中键对应数据帧中每个字段的名称。

  3. 返回数据帧:

    返回帧;
  4. 重新构建插件并尝试它。

您的数据源现在正在发送Grafana可以可视化的数据帧。接下来,我们将看看如何通过定义a来控制正弦波的频率查询

在本例中,我们从当前时间范围生成时间戳。这意味着无论您使用什么时间范围,都将得到相同的图表。实际上,您应该使用数据库返回的时间戳。

定义查询

大多数数据源都提供了查询特定数据的方法。MySQL和PostgreSQL使用SQL,而Prometheus有自己的查询语言,称为PromQL.无论数据库使用什么查询语言,Grafana都允许您构建对它的支持。

通过实现自己的数据源,为数据源添加对自定义查询的支持查询编辑器这是一个React组件,它允许用户通过用户友好的图形界面构建自己的查询。

查询编辑器可以像文本字段一样简单,用户可以在其中编辑原始查询文本,也可以提供更用户友好的表单,其中包含下拉菜单和开关,稍后将其转换为原始查询文本,然后再将其发送到数据库。

定义查询模型

设计查询编辑器的第一步是定义它查询模型.查询模型定义数据源的用户输入。

我们想要能够控制正弦波的频率,所以让我们添加另一个性质。

  1. 添加一个名为频率对于查询模型:

    src / types.ts

    导出MyQuery扩展DataQuery {queryText?:字符串;常数:数量;频率:数量;}
  2. 将默认值设置为new频率属性:

    export const defaultQuery: Partial ={常量:6.5,频率:1.0,};

将模型绑定到表单

既然已经定义了希望支持的查询模型,下一步就是将模型绑定到表单。的FormField文本字段组件是否来自grafana / ui这使您可以注册一个侦听器,该侦听器将在表单字段值更改时被调用。

  1. 向查询编辑器添加一个新的表单字段,以控制新的频率属性。

    QueryEditor.tsx

    const {queryText, constant, frequency} =查询;
     .
  2. 为新属性添加一个事件监听器。

    onFrequencyChange = (event: ChangeEvent) => {const {onChange, query, onRunQuery} = this.props;onChange({…查询,频率:parseFloat(event.target.value) }); // executes the query onRunQuery(); };

    注册听众,onFrequencyChangeonChange使用来自表单字段的值更新当前查询。

    onRunQuery ();告诉Grafana在每次更改后运行查询。对于快速查询,建议这样做,以提供响应更快的体验。

使用属性

新的查询模型现在可以在我们的查询方法。

  1. 查询方法,使用频率属性来调整我们的方程。

    框架。add({时间:从+ t,值:数学。sin(2 *数学。)PI * query.frequency * t) / duration)});

配置数据源

要访问特定的数据源,通常需要配置主机名、凭证或身份验证方法等。一个配置编辑器让你的用户配置你的数据源插件来满足他们的需求。

配置编辑器看起来类似于查询编辑器,因为它定义了一个模型并将其绑定到一个表单。

因为在正弦波示例中,我们实际上没有连接到外部数据库,所以实际上不需要太多选项。为了向您展示如何添加选项,我们将添加波决议作为一个选项。

分辨率控制数据点之间的时间距离。更高的分辨率意味着更多的点靠得更近,代价是要处理更多的数据。

定义选项模型

  1. 添加一个名为决议到期权模型。

    types.ts

    导出接口MyDataSourceOptions扩展DataSourceJsonData{路径?:字符串;决议?:数量;}

将模型绑定到表单

就像查询编辑器一样,配置编辑器中的表单字段在值更改时调用注册的侦听器。

  1. 向查询编辑器添加一个新的表单字段,以控制新的解析选项。

    ConfigEditor.tsx

  2. 为新选项添加一个事件监听器。

    onResolutionChange = (event: ChangeEvent) => {const {onOptionsChange, options} = this.props;const jsonData ={…jsonData,解析:parseFloat(event.target.value),};onOptionsChange({…选项,jsonData }); };

    onResolutionChange监听器调用onOptionsChange使用来自表单字段的值更新当前选项。

使用选项

  1. 创建一个名为决议数据源类。

    导出类DataSource extends DataSourceApi{分辨率:number;构造函数(instanceSettings: DataSourceInstanceSettings) {super(instanceSettings);这一点。resolution = instancessets . jsondata .resolution || 1000.0;} //…
  2. 查询方法,使用决议属性计算步长。

    src / DataSource.ts

    Const step = duration / this.resolution;

从外部API获取数据

到目前为止,您已经生成了数据源返回的数据。更现实的用例是从外部API获取数据。

你可以用axios或者是获取API要发出请求,我们建议使用getBackendSrv函数来自grafana /运行时包中。

的主要优点getBackendSrv它通过Grafana服务器代理请求,而不是从浏览器发出请求。当向外部API发出经过身份验证的请求时,强烈建议这样做。有关验证外部请求的更多信息,请参见为数据源插件添加身份验证

  1. 进口getBackendSrv

    src / DataSource.ts

    import {getBackendSrv} from "@grafana/runtime"
  2. 创建一个helper方法doRequest然后使用datasourceRequest方法向API发出请求。取代https://api.example.com/metrics来指向您自己的API端点。

    async doRequest(query: MyQuery) {const result = await getBackendSrv()。datasourceRequest({ method: "GET", url: "https://api.example.com/metrics", params: query, }) return result; }
  3. 为每个查询发出请求。Promises.all等待所有请求完成后再返回数据。

    async query(options: DataQueryRequest): Promise {const promises = options.targets.map((query) => this.doRequest(query).then((response) => {const frame = new MutableDataFrame({refId: query。refId, fields: [{name: "Time", type: FieldType.]time},{名称:“值”,类型:FieldType。Number},],});response.data。forEach((point: any) => {frame.appendRow([point: any])时间,point.value]);});返回帧;}));return Promise.all(promises).then((data) => ({data}));}

总结

在本教程中,您为Grafana构建了一个完整的数据源插件,该插件使用查询编辑器来控制要可视化的数据。您已经添加了一个数据源选项,通常用于设置连接选项等。

了解更多

了解如何进一步改进插件,请阅读我们的高级指南: