However I ran into an issue where the datasource query is only triggered when the dashboard loads or the refresh button is used.
This is the intended way Grafana works. Datasources don’t decide when to send data or to update variables. That’s something the user decides.
If you are talking about the query editor, there’s a prop passed to the QueryEditor called onRunQuery
that you can call (without passing anything to it) and it’ll trigger the query run.
e.g. of a Query Editor using this
export function QueryEditor({ query, onChange, onRunQuery }: Props) {
const fixedUrl = 'https://dummyjson.com/';
const inputValue = query.queryText?.startsWith(fixedUrl)
? query.queryText.slice(fixedUrl.length)
: query.queryText || '';
const onQueryTextChange = (event: ChangeEvent<HTMLInputElement>) => {
onChange({ ...query, queryText: fixedUrl + event.target.value });
onRunQuery(); //runs on text change
};
return (
<Stack gap={0}>
<InlineField label="API Endpoint" labelWidth={16} tooltip="Enter the path after https://dummyjson.com/">
<Input
id="query-editor-query-text"
onChange={onQueryTextChange}
value={inputValue}
required
placeholder="Enter endpoint path (e.g. 'products/1')"
addonBefore={fixedUrl}
/>
</InlineField>
</Stack>
);
}
in your datasource.ts file, you must make sure your query method is using getTemplateSrv().replace(query, options.scopedVars);
example for the previous query editor:
async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse> {
// Return a constant for each query.
const data = await Promise.all(options.targets.map(async (target) => {
const query = target.queryText;
const finalQuery = getTemplateSrv().replace(query, options.scopedVars); // variable replacing
console.log("Fetching data from: " + finalQuery);
const req = await fetch(finalQuery);
const todos = await req.json();
return createDataFrame({
refId: target.refId,
fields: [
{ name: "id", values: todos.todos.map((todo: any) => todo.id), type: FieldType.number },
{ name: 'Title', values: todos.todos.map((todo: any) => todo.todo), type: FieldType.string },
{ name: "Completed", values: todos.todos.map((todo: any) => todo.completed), type: FieldType.boolean },
],
});
}));
return { data };
}
what is very important to mention is that the query MUST contain a variable that is defined in the dashboard for grafana to prompt the datasource to query.
For example if in your dashboard there’s a variable called $limit and the user writes a query like
"SELECT* FROM TABLE WHERE id = 1 LIMIT $limit"
Grafana will now know whenever the variable $limit changes it should re-trigger this datasource. It will not trigger datasources that have queries without variables in the dashboard.
Bottom line:
- make sure you are using
getTemplateSrv().replace
to interpolate variables in your datasource
- make sure the query the user is writing in your query editor is using variables
- if you are 100% sure about the previous point, make sure you are using the correct variable name (the name in the variable editor, not the label)
- just to be sure, variables in queries look like this:
$variable
(like in Perl or PHP
)
I tested all this locally with a fresh bootstrapped plugin with create-plugin and it is all working as expected