从前端数据源和应用程序插件获取数据
除了 JavaScript 的 Fetch API,Grafana 数据代理还用于从 Grafana 数据源插件或应用程序插件获取数据。
数据代理特别有用
- 于克服跨站(CORS)限制,或者
- 执行受认证的请求,或者
- 从您的插件配置发送其他敏感数据到 Grafana。
本指南解释了数据代理的工作原理,并探讨了其使用中常见的常见问题。
它是如何工作的?
您不是直接从浏览器向服务器发送请求,而是通过 Grafana 后端服务器发送请求,它处理请求并将响应返回给插件。
- 无数据代理:请求直接从浏览器发送到第三方服务器。
- 使用数据代理:请求从浏览器发送到Grafana后端,然后发送到第三方服务器。在这种情况下,没有CORS限制,您可以指示Grafana使用插件配置中存储的敏感数据发送经过身份验证的请求。
您只能从数据源和应用程序插件中利用数据代理。您不能从面板插件中使用数据代理。
如何在数据源插件中使用数据代理
使用数据源插件中的数据代理最简单的方法是使用DataSourceHttpSettings
组件。
步骤 1:在您的数据源插件配置页面中使用DataSourceHttpSettings
组件
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、Cookie和超时等所有选项。
步骤 2:在您的数据源插件中使用数据代理
一旦用户在数据源配置页面中输入了端点详细信息,您就可以查询数据代理URL,该URL传递到数据源实例设置中(DataSourceInstanceSettings.url
)。
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
元数据中设置路由。
"routes": [
{
"path": "myRoutePath",
"url": "{{ .JsonData.apiUrl }}"
}
],
注意,url
值包含对jsonData.apiUrl
的插值。您的配置页面必须注意根据用户输入在jsonData
对象中设置apiUrl
。
每次您修改plugin.json
文件时,都必须构建您的插件并重新启动Grafana服务器。
步骤 2:创建您的配置页面
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 获取数据。
参考前面的示例,代码是相同的。
在应用插件中使用数据代理
您的 plugin.json
元数据中路由的设置与数据源插件中相同。但是,由于应用插件不会接收到作为 props 的 URL,因此 URL 的构造方式如下
const dataProxyUrl = `api/plugin-proxy/${PLUGIN_ID}/yourRoutePath`;
这是一个示例函数,用于在应用插件中从数据代理获取数据
在 src/plugin.json
中声明路由。您也可以像在数据源插件中那样使用认证请求和 jsonData
插值。
"routes": [
{
"path": "myRoutePath",
"url": "https://api.example.com",
// jsonData interpolation is also possible
//"url": "{{ .JsonData.apiUrl }}",
}]
然后,您可以使用数据代理通过如下构造数据代理 URL 来获取您的应用插件中的数据
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 的请求。
使用数据代理发送特殊头部
您可以使用数据代理发送特殊头部。有关向数据代理添加头部的信息,请参阅我们的文档。