Grafana插件-开发教程

1,250 阅读17分钟

了解如何创建插件来添加对您自己的数据源的支持。

了解如何为您的数据源插件创建后端。

了解如何构建日志数据源插件。

了解如何为您的仪表板创建自定义可视化。

一、构建一个数据源插件

1 介绍

Grafana支持广泛的数据源,包括Prometheus、MySQL和Datadog。然而,在某些情况下,您已经有一个内部指标解决方案,您想将其添加到您的Grafana仪表板中。本教程教你构建一个新的数据源插件来查询数据。

在本教程中,您将:

  • 构建一个数据源来可视化周期性变化数据
  • 使用查询编辑器构建查询
  • 使用配置编辑器配置您的数据源

1.1 先决条件

  • Grafana v9.0或更高版本
  • Node.js的LTS版本

2 创建一个新的插件

Grafana创建插件工具是一个CLI应用程序,它简化了Grafana插件的开发,以便您可以专注于代码。该工具为您提供启动插件、所有所需的配置以及使用Docker Compose的开发环境。

  1. 在新目录中,使用创建插件工具从模板创建插件。当提示输入插件类型时,选择数据源:

    npx @grafana/create-plugin@latest
    
  2. 转到您新创建的插件的目录:

    cd <your-plugin>
    
  3. 安装依赖项:

    npm install
    
  4. 构建插件:

    npm run dev
    
  5. 开始Grafana:

    docker-compose up
    
  6. 打开Grafana,默认为http://localhost:3000/,然后转到管理>插件。确保您的数据源插件在那里。

您还可以通过检查日志来验证Grafana是否发现了您的插件:

INFO[01-01|12:00:00] Plugin registered       logger=plugin.loader pluginID=<your-plugin>

要了解如何创建后端数据源插件,请参阅构建数据源后端插件

3 插件的剖析

您创建的每个插件至少需要两个文件:plugin.jsonsrc/module.ts

plugin.json

当Grafana启动时,它会扫描插件目录中包含plugin.json文件的任何子目录。plugin.json文件包含有关插件的信息,并告诉Grafana您的插件需要哪些功能和依赖项。

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

  • type告诉Grafana期待哪种类型的插件。Grafana支持三种类型的插件:paneldatasourceapp
  • name是用户将在插件列表中看到的内容。如果您正在创建数据源,这通常是它连接的数据库的名称,例如Prometheus、PostgreSQL或Stackdriver。
  • id唯一标识您的插件,并应遵循以下命名约定:<$organization-name>-<$plugin-name>-<$plugin-type>。创建插件工具根据您对其提示的响应正确配置此操作。

要查看plugin.json的所有可用配置设置,请参阅plugin.json模式

module.ts

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

具体来说,src/module.ts需要导出一个扩展GrafanaPlugin的类,并且可以是以下任何一个:

4 数据源插件

Grafana中的数据源必须扩展DataSourceApi接口,这需要您定义两种方法:querytestDatasource

4.1 query方法

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

async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse>

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

4.2 测试您的数据源

testDatasource为您的数据源实施运行状况检查。例如,每当用户在更改连接设置后单击“保存和测试”按钮时,Grafana都会调用此方法。

async testDatasource()

有关前端数据源中运行状况检查的示例,请参阅我们的datasource-http插件。

5 返回数据帧

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

让我们看看如何从query方法创建和返回数据帧。在此步骤中,您将更改启动器插件中的代码以返回正弦波

  1. 在当前query方法中,删除map函数中的代码。

    query方法现在看起来像这样:

    src/datasource.ts

    async 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 };
    }
    
  2. map函数中,使用lodash/defaults包为尚未设置的查询属性设置默认值:

    src/datasource.ts

    import defaults from 'lodash/defaults';
    
    const query = defaults(target, defaultQuery);
    
  3. 在datasource.ts的顶部创建默认查询:

    src/datasource.ts

    export const defaultQuery: Partial<MyQuery> = {
      constant: 6.5,
    };
    
  4. 创建一个带有时间字段和数字字段的数据帧:

    src/datasource.ts

    const frame = new MutableDataFrame({
      refId: query.refId,
      fields: [
        { name: 'time', type: FieldType.time },
        { name: 'value', type: FieldType.number },
      ],
    });
    

    refId需要设置为告诉Grafana哪个查询生成了此日期帧。

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

  1. 创建几个辅助变量:

    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;
    
  2. 将值添加到数据帧中:

    src/datasource.ts

    for (let t = 0; t < duration; t += step) {
      frame.add({ time: from + t, value: Math.sin((2 * Math.PI * t) / duration) });
    }
    

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

  3. 返回数据帧:

    src/datasource.ts

    return frame;
    
  4. 通过创建新的数据源实例并构建仪表板来尝试。

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

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

6. 定义一个查询

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

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

查询编辑器可以像文本字段一样简单,用户在其中编辑原始查询文本,或者它可以提供一个更用户友好的表单,带有下拉菜单和开关,稍后在发送到数据库之前转换为原始查询文本。

6.1 定义查询模型

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

我们希望能够控制正弦波的频率,所以让我们添加另一个属性。

  1. 向查询模型添加一个名为frequency的新数字属性:

    src/types.ts

    export interface MyQuery extends DataQuery {
      queryText?: string;
      constant: number;
      frequency: number;
    }
    
  2. 将默认值设置为新的frequency属性:

    src/types.ts

    export const defaultQuery: Partial<MyQuery> = {
      constant: 6.5,
      frequency: 1.0,
    };
    

6.2 将模型绑定到表单上

现在您已经定义了希望支持的查询模型,下一步是将模型绑定到表单。FormFieldgrafana/ui的文本字段组件,允许您注册一个侦听器,每当表单字段值发生变化时,该侦听器将被调用。

  1. query对象定义frequency,并在查询编辑器中添加一个新的表单字段,以控制render方法中的新频率属性。

    src/components/QueryEditor.tsx

    const { queryText, constant, frequency } = query;
    
    <InlineField label="Frequency" labelWidth={16}>
      <Input onChange={onFrequencyChange} value={frequency || ''} />
    </InlineField>;
    
  2. 为新属性添加事件侦听器。

    src/components/QueryEditor.tsx

    const onFrequencyChange = (event: ChangeEvent<HTMLInputElement>) => {
      onChange({ ...query, frequency: parseFloat(event.target.value) });
      // executes the query
      onRunQuery();
    };
    

    注册的侦听器onFrequencyChange调用onChange,用表单字段中的值更新当前查询。

    onRunQuery();告诉Grafana在每次更改后运行查询。对于快速查询,建议提供更灵敏的体验。

6.3 使用该属性

新的查询模型现在可以在我们的query方法中使用。

  1. query方法中,使用frequency属性来调整我们的方程。

    src/datasource.ts

    frame.add({ time: from + t, value: Math.sin((2 * Math.PI * query.frequency * t) / duration) });
    
  2. 通过更改面板查询中的频率来尝试一下。

7. 为您的数据源启用配置

要访问特定数据源,您通常需要配置主机名、凭据或身份验证方法等内容。Aconfig编辑器允许您的用户配置您的数据源插件以满足他们的需求。

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

由于我们实际上没有在正弦波示例中连接到外部数据库,我们真的不需要很多选项。然而,为了向您展示如何添加选项,我们将添加波浪分辨率作为选项。

分辨率控制数据点彼此之间的距离有多近。更高的分辨率意味着更多的点更紧密地结合在一起,而牺牲了处理更多的数据。

7.1 定义选项模型

  1. 将一个名为resolution的新数字属性添加到选项模型中。

    src/types.ts

    export interface MyDataSourceOptions extends DataSourceJsonData {
      path?: string;
      resolution?: number;
    }
    

7.2 将模型绑定到表单上

就像查询编辑器一样,每当值发生变化时,配置编辑器中的表单字段都会调用注册的侦听器。

  1. 在查询编辑器中添加一个新的表单字段,以控制新的分辨率选项。

    src/components/ConfigEditor.tsx

    <InlineField label="Resolution" labelWidth={12}>
      <Input onChange={onResolutionChange} value={jsonData.resolution || ''} placeholder="Enter a number" width={40} />
    </InlineField>
    
  2. 为新选项添加事件侦听器。

    src/components/ConfigEditor.tsx

    const onResolutionChange = (event: ChangeEvent<HTMLInputElement>) => {
      const jsonData = {
        ...options.jsonData,
        resolution: parseFloat(event.target.value),
      };
      onOptionsChange({ ...options, jsonData });
    };
    

    onResolutionChange侦听器调用onOptionsChange,使用表单字段中的值更新当前选项。

使用选项

  1. DataSource类创建一个名为resolution的属性。

    src/datasource.ts

    export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
      resolution: number;
    
      constructor(instanceSettings: DataSourceInstanceSettings<MyDataSourceOptions>) {
        super(instanceSettings);
    
        this.resolution = instanceSettings.jsonData.resolution || 1000.0;
      }
    
      // ...
    
  2. query方法中,使用resolution属性来更改我们计算步长的方式。

    src/datasource.ts

    const step = duration / this.resolution;
    
  3. 通过配置新的数据源并更改分辨率值来尝试一下。

8. 摘要

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

9 了解更多

9.1 从外部API获取数据

Grafana中的大多数数据源将从外部API返回数据。本教程试图保持简单,不需要额外的服务。要了解如何实现这一点,请使用datasource-http示例。

此示例显示了grafana-runtimegetBackendSrv函数的使用情况。

虽然您可以使用axiosFetch API等内容来发出请求,但我们建议使用getBackendSrv,因为它通过Grafana服务器代理请求,而不是从浏览器发出请求。在向外部API发出身份验证请求时,我们强烈建议这样做。有关验证外部请求的更多信息,请参阅为数据源插件添加身份验证

9.2 提高插件的质量

要了解有关高级插件开发主题的更多信息,请参阅以下内容:

二、 构建数据源后端插件

1 介绍

Grafana支持广泛的数据源,包括Prometheus、MySQL和Datadog。然而,在某些情况下,您已经有一个内部指标解决方案,您想将其添加到您的Grafana仪表板中。本教程教你构建一个新的数据源插件来查询数据。

后端组件为您的插件提供了许多附加功能,例如自定义身份验证方法。要了解更多信息,请参阅有关后端插件的文档。

在本教程中,您将:

  • 为您的数据源构建一个后端
  • 为您的数据源实施运行状况检查
  • 为您的数据源启用Grafana警报

先决条件

  • Grafana v9.0或更高版本
  • go(版本
  • Mage
  • Node.js的LTS版本

创建一个新的插件

Grafana创建插件工具是一个CLI应用程序,它简化了Grafana插件的开发,以便您可以专注于代码。该工具为您提供启动插件、所有所需的配置以及使用Docker Compose的开发环境。

  1. 在新目录中,使用创建插件工具从模板创建插件。当提示输入插件类型时,选择并回答是“您想要插件的后端部分吗?”:

    npx @grafana/create-plugin@latest
    
  2. 转到您新创建的插件的目录:

    cd <your-plugin>
    
  3. 安装依赖项:

    npm install
    
  4. 构建插件前端:

    npm run dev
    
  5. 在新的终端窗口中,构建插件后端:

    mage -v build:linux
    
  6. 开始Grafana:

    docker-compose up
    
  7. 打开Grafana,默认为http://localhost:3000/,然后转到管理>插件。确保您的插件在那里。

您还可以通过检查日志来验证Grafana是否发现了该插件:

INFO[01-01|12:00:00] Plugin registered       logger=plugin.loader pluginID=<your-plugin>

现在,让我们验证您到目前为止构建的插件是否可以在创建新数据源时在Grafana中使用:

  1. 在侧边菜单上,转到连接>数据源
  2. 单击添加数据源
  3. 搜索您新创建的插件的名称并选择它。
  4. 输入一个名称,然后单击保存和测试。如果发生“随机错误”,您可以忽略它-这是下文进一步解释的健康检查的结果。

您现在有了插件的新数据源实例,可以在仪表板中使用。

要将数据源添加到仪表板:

  1. 创建一个新的仪表板并添加一个新的面板。
  2. 在查询选项卡上,选择您刚刚创建的数据源。线图由两个数据点组成的一个系列渲染。
  3. 保存仪表板。

故障排除

Grafana没有加载我的插件

确保Grafana已启动在开发模式下。如果您从源代码运行Grafana,则需要将以下行添加到conf/custom.ini文件中(如果您还没有,请在继续之前创建此文件):

app_mode = development

然后,您可以通过在Grafana存储库根目录中运行make run & make run-frontend,在开发模式下启动Grafana。

如果您从二进制文件或Docker容器内运行Grafana,您可以通过将环境变量GF_DEFAULT_APP_MODE设置为development来以开发模式启动它。

默认情况下,Grafana需要对后端插件进行签名。要加载未签名的后端插件,您需要配置Grafana以允许未签名的插件。有关更多信息,请参阅插件签名验证

后端插件的剖析

用于构建数据源后端的文件夹和文件是:

文件/文件夹描述
Magefile.go这不是使用mage构建文件的要求,但我们强烈建议使用它,以便您可以使用插件SDK提供的构建目标。
/go.mod Go模块依赖项
/src/plugin.json描述后端插件的JSON文件
/pkg/main.go插件二进制文件的起点。

plugin.json

所有插件都需要plugin.json文件。在构建后端插件时,这些属性很重要:

财产描述
后端对于后端插件设置为true。这告诉Grafana,在加载插件时,它应该启动二进制文件。
可执行的这是Grafana希望启动的可执行文件的名称,详情请参阅plugin.json参考
警报如果您的后端数据源支持警报,请设置为true。需要将backend设置为true

在下一步中,我们将查看查询端点!

实施数据查询

我们首先打开文件/pkg/plugin/datasource.go。在此文件中,您将看到实现backend.QueryDataHandler接口Datasource结构。此结构上的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警报

  1. 添加值为true的顶级alerting属性,以指定您的插件支持Grafana警报,例如

    src/plugin.json

    {
      ...
      "backend": true,
      "executable": "gpx_simple_datasource_backend",
      "alerting": true,
      "info": {
      ...
    }
    
  2. 重新启动您的Grafana实例。

  3. 在您的网络浏览器中打开Grafana。

  4. 通过导航到您创建的数据源来验证是否支持警报。您应该在设置视图中看到“支持警报”消息。

创建警报

笔记

以下说明基于Grafana v10.1.1,请参阅文档以获取版本适当的指导。

  1. 打开您之前在创建新插件步骤中创建的仪表板。

  2. 编辑现有面板。

  3. 单击面板下方的警报选项卡。

  4. 从此面板按钮中单击创建警报规则

  5. 表达式部分,在阈表达式C中,将IS ABOVE设置为15

  6. 单击阈表达式C上的设置为警报条件。您的警报现在应该如下所示。

    表达式部分显示B"减少"与输入:A,功能:最后,模式:严格,C阈值与输入:B,高于:15和警报条件启用指示器

    表达式部分显示B“减少”与输入:A,功能:最后,模式:严格,C阈值与输入:B,高于:15和警报条件启用指示器

  7. 设置警报评估行为部分,单击新建文件夹按钮并创建一个新文件夹以存储评估规则。

  8. 然后,单击“新建评估组”按钮并创建一个新的评估组;选择一个名称并将评估间隔设置为10s

  9. 单击保存规则并退出按钮。

  10. 保存仪表板。

  11. 一段时间后,警报规则进行评估并过渡到警报状态。

摘要

在本教程中,您为您的数据源插件创建了一个后端。

三、构建数据源后端插件

四、# 构建一个面板插件