在(二)中实现query方法 的末尾,我们遇到了跨域问题。如果你没有后端的修改权,这个问题在纯前端的情况下相对比较棘手。好在grafana为我们提供了代理路由,我们只需要让对数据库的请求经过grafana后端中转就可以解决跨域问题了。此外,这也防止了请求直接由浏览器发出而导致的不安全问题。
此外,本节中也将介绍如何自定义Grafana插件的配置项,例如在添加数据源时自定义数据库URL
你可能需要一点关于React的基础。即便没接触过React也不用担心。React自己的api函数非常少,基本上就是Js加类似Html的<jsx>,非常好理解。
为数据源自定义配置项
修改ConfigEditor组件
如果你之前接触过React,那么你应该一看就都懂了。。
模板中具有两个示例,Path和ApiKey,对应了jsonData普通配置项和安全性较高的secureJsonData配置项。
想要新增我们自己的配置字段,创建一个文本框,然后绑定对应的配置修改方法即可。
下面将以创建一个数据库地址的配置字段为例:
因为是TypeScript,所以我们先来修改接口类型。模板中的配置对象接口类型叫MyDataSourceOptions。
export interface MyDataSourceOptions extends DataSourceJsonData {
path?: string;
URL: string; //我们新加的
}
在组件内部添加一个方法
(这方法看着感觉挺啰嗦的。。你可以自己优化一下)
onURLChange = (event: ChangeEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
const jsonData = {
...options.jsonData,
URL: event.target.value,
};
onOptionsChange({ ...options, jsonData });
};
然后在render方法的返回值内,找个地方插入我们的FormField组件。如果是私密数据的话可以选择SecretFormField组件。
因为都是普通字段,所以我把它和模板里自带的Path放到了一起
......
<div className="gf-form">
<FormField
label="URL"
labelWidth={6}
inputWidth={20}
onChange={this.onURLChange}
value={jsonData.URL || ''}
placeholder="http://greptime.example.com"
/>
{/* 下面这个是自带的 */}
<FormField
label="Path"
labelWidth={6}
inputWidth={20}
onChange={this.onPathChange}
value={jsonData.path || ''}
placeholder="json field returned to frontend"
/>
</div>
......
Build一下,然后让Grafana重新加载插件,看看效果
可以看到我们新增的配置项已经显示出来了!
使用配置文件中的数据
在query中使用
在(二)中,我们对数据库地址进行了硬编码。现在我们可以将其修改为从数据源配置中获取了!
回到我们的datasource.ts ,你可以在constructor中看到,其中传入了一个参数instanceSettings,其中便包括了我们插件的各项设置
通过instanceSettings.jsonData我们可以把上面添加的URL拿出来。
export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
URL: string;
constructor(instanceSettings: DataSourceInstanceSettings<MyDataSourceOptions>) {
super(instanceSettings);
this.URL = instanceSettings.jsonData.URL;
}
…………
然后修改我们的doRequest方法。如果你是在类内部定义的,可以直接使用this.URL。
因为我是在文件外定义的,这里我使用了一个闭包,在构造函数中使用setUrl将url传递过来。
let BaseUrl = '';
export const setUrl = (url: string) => {
BaseUrl = url;
};
export async function doRequst(sql: String): Promise<GreptimeDBResponse> {
const SQL_URL = `${BaseUrl}/v1/sql`;
const response: GreptimeDBResponse = await getBackendSrv().post(`${SQL_URL}?sql=${sql}`);
return response;
}
打包测试一下结果
可以看到确实向我们在设置中填写的地址发出了请求。
如此,你便可以自由的编写你的数据库配置项了。
为数据源设置代理
我们首先需要在plugin.json中进行填写route相关属性。我们最少需要其中的url
url
- For data source plugins. Route URL is where the request is proxied to.
在我们的plugin.json内添加如下内容。通过{{ .JsonData.foobar}}可以读取数据源配置文件中的配置项。
"routes": [
{
"url": "{{ .JsonData.URL }}"
}
],
然后回到我们的datasource.ts,更改URL的来源
export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
URL: string;
constructor(instanceSettings: DataSourceInstanceSettings<MyDataSourceOptions>) {
super(instanceSettings);
this.URL = instanceSettings.url!;
}
更新插件进行测试
可以看到这次我们的请求的目标链接变成了grafana的proxy而不是之前填写的数据库地址了,并且查询仍然有效!
Grafana非常人性化的帮我们生成了一个代理服务 instanceSettings.url => JsonData.URL
,这样就解决了跨域和请求直接暴露的问题。
Comments | 1 条评论
博主 Mesak
謝謝分享