id | title | description | keywords | ||||||
---|---|---|---|---|---|---|---|---|---|
fetch-data-from-frontend |
Fetch data from frontend code to data source plugin using the data proxy |
Learn how to use the data proxy API to fetch data from frontend code in data source plugins in Grafana |
|
Along with the JavaScript Fetch API, the Grafana data proxy is used to fetch data from a Grafana data source plugin or app plugin.
The data proxy is especially useful
- for overcoming cross-site (CORS) limitations, or
- for performing authenticated requests, or
- for sending other sensitive data from your plugin configuration to Grafana.
This guide explains how the data proxy works and explores common issues in its usage for data source plugins. For usage in app plugins, refer to our documentation
Instead of performing a request directly from the browser to the server, you perform the request through the Grafana backend server, which handles it and returns the response to the plugin.
- Without data proxy: The requests go directly from the browser to the third-party server.
- With data proxy: The requests go from the browser to the Grafana backend and then to the third-party server. In this case, there are no restrictions in CORS, and you can instruct Grafana to send the request authenticated by using sensitive data stored in the plugin configuration.
:::note You can only make use of the data proxy from data source and app plugins. You can't use the data proxy from panel plugins. :::
The easiest way to use the data proxy from a data source plugin is using the DataSourceHttpSettings
component.
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}
/>
);
}
The DataSourceHttpSettings
will display a form with all the options for the user to configure an HTTP endpoint, including authentication, TLS, cookies, and timeout.
Once the user has entered the endpoint details in the data source configuration page, you can query the data proxy URL that is passed in the data source instance settings (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 The user must first configure the data source in the configuration page before the data source can query the endpoint via the data source. If the data source is not configured, the data proxy won't know which endpoint to send the request to. ::
If you don't want to use the DataSourceHttpSettings
component and instead create your own configuration page
you will have to do some additional setup in your plugin.
You first need to set up the routes in your plugin.json
metadata.
"routes": [
{
"path": "myRoutePath",
"url": "{{ .JsonData.apiUrl }}"
}
],
Notice that the url
value contains an interpolation of jsonData.apiUrl
. Your configuration page must take care of setting the apiUrl
in the jsonData
object based on the user input.
:::note
You must build your plugin and restart the Grafana server every time you modify your plugin.json
file.
:::
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 */}
);
}
In your data source plugin, you can now fetch data by using the proxy URL.
Refer to the previous example, as the code is the same.
You can specify the method directly in the fetch
method. Your routes in src/plugin.json
remain the same:
const response = getBackendSrv().fetch<TODO[]>({
url: `${this.baseUrl}`,
method: 'POST',
data: dataToSendViaPost,
});
To learn about adding authentication to the data proxy, refer to our documentation.
If you want to debug the requests that are going from the Grafana backend to your API, enable the data proxy logging in the configuration.
You must also enable debug logs in Grafana to be able to see the data proxy logs in your Grafana configuration file.
Example:
[log]
level = debug
[dataproxy]
logging = true
With this configuration, the Grafana server output shows the requests going out to your API from the data proxy.
You can send special headers using the data proxy. To learn about adding headers to the data proxy, refer to our documentation.