Graphite: Have metric name type query variable use metric render endpoint (#61730)

* have metric name query var use metric render endpoint

* add documentation for new query types
This commit is contained in:
Brendan O'Handley 2023-01-23 18:13:22 -05:00 committed by GitHub
parent 3006a457f2
commit 1181d06b1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 19 deletions

View File

@ -21,6 +21,16 @@ Grafana refers to such variables as template variables.
For an introduction to templating and template variables, refer to the [Templating]({{< relref "../../../dashboards/variables" >}}) and [Add and manage variables]({{< relref "../../../dashboards/variables/add-template-variables" >}}) documentation.
## Select a query type
There are three query types for Graphite template variables
| Query Type | Description |
| ----------------- | ------------------------------------------------------------------------------- |
| Default Query | Use functions such as `tags()`, `tag_values()`, `expand(<metric>)` and metrics. |
| Value Query | Returns all the values for a query that includes a metric and function. |
| Metric Name Query | Returns all the names for a query that includes a metric and function. |
## Use tag variables
To create a variable using tag values, use the Grafana functions `tags` and `tag_values`.
@ -40,7 +50,7 @@ tag_values(server, server=~backend\*, app=~${apps:regex})
For details, refer to the [Graphite docs on the autocomplete API for tags](http://graphite.readthedocs.io/en/latest/tags.html#auto-complete-support).
### Use multi-valie variables in tag queries
### Use multi-value variables in tag queries
Multi-value variables in tag queries use the advanced formatting syntax for variables introduced in Grafana v5.0: `{var:regex}`.
Non-tag queries use the default glob formatting for multi-value variables.

View File

@ -624,24 +624,35 @@ describe('graphiteDatasource', () => {
fetchMock.mockImplementation((options: any) => {
requestOptions = options;
return of(
createFetchResponse({
results: ['apps.backend.backend_01', 'apps.backend.backend_02', 'apps.country.IE', 'apps.country.SE'],
})
createFetchResponse([
{
target: 'apps.backend.backend_01',
datapoints: [
[10, 1],
[12, 1],
],
},
{
target: 'apps.backend.backend_02',
datapoints: [
[10, 1],
[12, 1],
],
},
])
);
});
const fq: GraphiteQuery = {
queryType: GraphiteQueryType.MetricName,
target: 'query',
target: 'apps.backend.*',
refId: 'A',
datasource: ctx.ds,
};
const data = await ctx.ds.metricFindQuery(fq);
expect(requestOptions.url).toBe('/api/datasources/proxy/1/metrics/expand');
expect(requestOptions.url).toBe('/api/datasources/proxy/1/render');
expect(data[0].text).toBe('apps.backend.backend_01');
expect(data[1].text).toBe('apps.backend.backend_02');
expect(data[2].text).toBe('apps.country.IE');
expect(data[3].text).toBe('apps.country.SE');
});
});

View File

@ -486,8 +486,8 @@ export class GraphiteDatasource
const options: any = optionalOptions || {};
const queryObject = convertToGraphiteQueryObject(findQuery);
if (queryObject.queryType === GraphiteQueryType.Value) {
return this.requestMetricRender(queryObject, options);
if (queryObject.queryType === GraphiteQueryType.Value || queryObject.queryType === GraphiteQueryType.MetricName) {
return this.requestMetricRender(queryObject, options, queryObject.queryType);
}
let query = queryObject.target ?? '';
@ -531,7 +531,7 @@ export class GraphiteDatasource
};
}
if (useExpand || queryObject.queryType === GraphiteQueryType.MetricName) {
if (useExpand) {
return this.requestMetricExpand(interpolatedQuery, options.requestId, range);
} else {
return this.requestMetricFind(interpolatedQuery, options.requestId, range);
@ -540,14 +540,22 @@ export class GraphiteDatasource
/**
* Search for metrics matching giving pattern using /metrics/render endpoint.
* It will return all possible values and parse them based on queryType.
* It will return all possible values or names and parse them based on queryType.
* For example:
*
* queryType: GraphiteQueryType.Value
* query: groupByNode(movingAverage(apps.country.IE.counters.requests.count, 10), 2, 'sum')
* result: 239.4, 233.4, 230.8, 230.4, 233.9, 238, 239.8, 236.8, 235.8
*
* queryType: GraphiteQueryType.MetricName
* query: highestAverage(carbon.agents.*.*, 5)
* result: carbon.agents.aa6338c54341-a.memUsage, carbon.agents.aa6338c54341-a.committedPoints, carbon.agents.aa6338c54341-a.updateOperations, carbon.agents.aa6338c54341-a.metricsReceived, carbon.agents.aa6338c54341-a.activeConnections
*/
private async requestMetricRender(queryObject: GraphiteQuery, options: any): Promise<MetricFindValue[]> {
private async requestMetricRender(
queryObject: GraphiteQuery,
options: any,
queryType: GraphiteQueryType
): Promise<MetricFindValue[]> {
const requestId: string = options.requestId ?? `Q${this.requestCounter++}`;
const range: TimeRange = options.range ?? {
from: dateTime().subtract(6, 'hour'),
@ -568,14 +576,28 @@ export class GraphiteDatasource
requestId,
range,
};
const data = await lastValueFrom(this.query(queryReq));
const result: MetricFindValue[] = data.data[0].fields[1].values
.filter((f?: number) => !!f)
.map((v: number) => ({
text: v.toString(),
value: v,
const data: DataQueryResponse = await lastValueFrom(this.query(queryReq));
let result: MetricFindValue[];
if (queryType === GraphiteQueryType.Value) {
result = data.data[0].fields[1].values
.filter((f?: number) => !!f)
.map((v: number) => ({
text: v.toString(),
value: v,
expandable: false,
}));
} else if (queryType === GraphiteQueryType.MetricName) {
result = data.data.map((series) => ({
text: series.name,
value: series.name,
expandable: false,
}));
} else {
result = [];
}
return Promise.resolve(result);
}