跳到主内容

从前端数据源和应用插件获取数据

除了 JavaScript Fetch API,Grafana 数据代理用于从 Grafana 数据源插件或应用插件获取数据。

数据代理特别有用

  • 用于克服跨站(CORS)限制,或
  • 用于执行认证请求,或
  • 用于将您的插件配置中的其他敏感数据发送到 Grafana。

本指南解释了数据代理的工作原理并探讨了其使用中的常见问题。

工作原理

您可以不必直接从浏览器向服务器发送请求,而是通过 Grafana 后端服务器发送请求,由 Grafana 后端处理并返回响应给插件。

  • 不使用数据代理:请求直接从浏览器发送到第三方服务器。
  • 使用数据代理:请求从浏览器发送到 Grafana 后端,然后发送到第三方服务器。在这种情况下,不存在 CORS 限制,并且您可以指示 Grafana 使用存储在插件配置中的敏感数据进行认证发送请求。
注意

您只能从数据源和应用插件中使用数据代理。您不能从面板插件中使用数据代理。

如何在数据源插件中使用数据代理

从数据源插件中使用数据代理最简单的方法是使用 DataSourceHttpSettings 组件。

步骤 1:在数据源插件配置页面中使用 DataSourceHttpSettings 组件

src/ConfigEditor.tsx
import React from 'react';
import { DataSourceHttpSettings } from '@grafana/ui';
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';

export function ConfigEditor(props: DataSourcePluginOptionsEditorProps) {
const { onOptionsChange, options } = props;

return (
<DataSourceHttpSettings
defaultUrl="https://jsonplaceholder.typicode.com/"
dataSourceConfig={options}
onChange={onOptionsChange}
/>
);
}

DataSourceHttpSettings 将显示一个表单,其中包含用户配置 HTTP 端点的所有选项,包括身份验证、TLS、cookies 和超时。

步骤 2:在数据源插件中使用数据代理

用户在数据源配置页面输入端点详细信息后,您就可以查询在数据源实例设置(DataSourceInstanceSettings.url)中传递的数据代理 URL。

src/dataSource.ts
import {
DataQueryRequest,
DataQueryResponse,
DataSourceApi,
DataSourceInstanceSettings,
FieldType,
PartialDataFrame,
} from '@grafana/data';
import { getBackendSrv } from '@grafana/runtime';
import { lastValueFrom } from 'rxjs';

type TODO = {
title: string;
id: number;
};

export class DataSource extends DataSourceApi {
baseUrl: string;
constructor(instanceSettings: DataSourceInstanceSettings) {
super(instanceSettings);
// notice we are storing the URL from the instanceSettings
this.baseUrl = instanceSettings.url!;
}

async query(options: DataQueryRequest): Promise<DataQueryResponse> {
const response = getBackendSrv().fetch<TODO[]>({
// You can see above that `this.baseUrl` is set in the constructor
// in this example we assume the configured url is
// https://jsonplaceholder.typicode.com
/// if you inspect `this.baseUrl` you'll see the Grafana data proxy url
url: `${this.baseUrl}/todos`,
});
// backendSrv fetch returns an observable object
// we should unwrap with rxjs
const responseData = await lastValueFrom(response);
const todos = responseData.data;

// we'll return the same todos for all queries in this example
// in a real data source each target should fetch the data
// as necessary.
const data: PartialDataFrame[] = options.targets.map((target) => {
return {
refId: target.refId,
fields: [
{ name: 'Id', type: FieldType.number, values: todos.map((todo) => todo.id) },
{ name: 'Title', type: FieldType.string, values: todos.map((todo) => todo.title) },
],
};
});

return { data };
}

async testDatasource() {
return {
status: 'success',
message: 'Success',
};
}
}

:: note 用户必须首先在配置页面配置数据源,然后该数据源才能通过数据源查询端点。如果数据源未配置,数据代理将不知道将请求发送到哪个端点。 :

如何在具有自定义配置页面的数据源插件中使用数据代理

如果您不想使用 DataSourceHttpSettings 组件,而是想创建自己的配置页面,则需要在插件中进行一些额外的设置。

步骤 1:在插件元数据中声明路由

首先需要在 plugin.json 元数据中设置路由。

src/plugin.json
"routes": [
{
"path": "myRoutePath",
"url": "{{ .JsonData.apiUrl }}"
}
],

请注意,url 值包含 jsonData.apiUrl 的插值。您的配置页面必须负责根据用户输入在 jsonData 对象中设置 apiUrl

注意

每次修改 plugin.json 文件后,都必须构建插件并重启 Grafana 服务器。

步骤 2:创建配置页面

src/ConfigEditor.tsx
import React, { ChangeEvent } from 'react';
import { InlineField, Input } from '@grafana/ui';

export function ConfigEditor(props: Props) {
const { onOptionsChange, options } = props;
const { jsonData } = options;

const onApiUrlChange = (event: ChangeEvent<HTMLInputElement>) => {
onOptionsChange({
...options,
jsonData: {
...jsonData,
// notice we set the apiUrl value inside jsonData
apiUrl: event.target.value,
},
});
};

return (
<InlineField label="apiUrl" labelWidth={12}>
<Input
onChange={onApiUrlChange}
value={jsonData.apiUrl || ''}
placeholder="json field returned to frontend"
width={40}
/>
</InlineField>
{/* The rest of your configuration page form */}
);
}

步骤 3:从前端代码获取数据

在您的数据源插件中,您现在可以使用代理 URL 获取数据。

请参考上一个示例,但在 query 函数中更改 url,以便之前声明的 path 包含在 url

src/dataSource.ts
async query(options: DataQueryRequest): Promise<DataQueryResponse> {
const response = getBackendSrv().fetch<TODO[]>({
// You can see above that `this.baseUrl` is set in the constructor
// in this example we assume the configured url is
// https://jsonplaceholder.typicode.com
// if you inspect `this.baseUrl` you'll see the Grafana data proxy url
// and you need to add the myRoutePath path (previously configured in plugin.json) to the url
url: `${this.baseUrl}/myRoutePath/todos`,
});
// backendSrv fetch returns an observable object
// we should unwrap with rxjs
const responseData = await lastValueFrom(response);
const todos = responseData.data;

// we'll return the same todos for all queries in this example
// in a real data source each target should fetch the data
// as necessary.
const data: PartialDataFrame[] = options.targets.map((target) => {
return {
refId: target.refId,
fields: [
{ name: 'Id', type: FieldType.number, values: todos.map((todo) => todo.id) },
{ name: 'Title', type: FieldType.string, values: todos.map((todo) => todo.title) },
],
};
});

return { data };
}

在应用插件中使用数据代理

plugin.json 元数据中设置路由的方式与数据源插件相同。但是,由于应用插件不接收 URL 作为属性的一部分,URL 构建如下

const dataProxyUrl = `api/plugin-proxy/${PLUGIN_ID}/yourRoutePath`;

以下是一个从应用插件的数据代理获取数据的函数的示例

src/plugin.json 中声明路由。您也可以像在数据源插件中一样使用认证请求和 jsonData 插值。

src/plugin.json
"routes": [
{
"path": "myRoutePath",
"url": "https://api.example.com",
// jsonData interpolation is also possible
//"url": "{{ .JsonData.apiUrl }}",
}]

在您的应用插件代码中,您可以通过如下方式构建数据代理 URL 来使用数据代理获取数据

src/dataproxy-api-example.ts
import { getBackendSrv } from '@grafana/runtime';
import { lastValueFrom } from 'rxjs';

async function getDataFromApi() {
const dataProxyUrl = `api/plugin-proxy/${PLUGIN_ID}/myRoutePath`;
const response = getBackendSrv().fetch<TODO[]>({
url: dataProxyUrl,
});
return await lastValueFrom(response);
}

将其他 HTTP 方法(例如 POST、PUT、DELETE)与数据代理一起使用

您可以直接在 fetch 方法中指定方法。您在 src/plugin.json 中的路由保持不变

const response = getBackendSrv().fetch<TODO[]>({
url: `${this.baseUrl}`,
method: 'POST',
data: dataToSendViaPost,
});

使用数据代理为请求添加身份验证

要了解如何为数据代理添加身份验证,请参阅我们的文档

调试来自数据代理的请求

如果您想调试从 Grafana 后端发送到您的 API 的请求,请在配置中启用数据代理日志记录。

您还必须在 Grafana 中启用调试日志,以便能够在 Grafana 配置文件中看到数据代理日志。

示例

[log]
level = debug

[dataproxy]
logging = true

通过此配置,Grafana 服务器输出将显示从数据代理发送到您的 API 的请求。

使用数据代理发送特殊标头

您可以使用数据代理发送特殊标头。要了解如何为数据代理添加标头,请参阅我们的文档