Skip to content

Commit 138ff49

Browse files
authored
Chained variables (#60)
* Tinkering with chained * Deal with missing imports * Allow for custom values (operation is not being returned) * Add support for scopedVars that override template variables * Updated signature and tests
1 parent 01bcb3c commit 138ff49

2 files changed

Lines changed: 56 additions & 22 deletions

File tree

src/components/VariableEditor/VariableEditor.tsx

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useCallback, useRef } from 'react';
2-
import { AsyncSelect, InlineField } from '@grafana/ui';
2+
import { AsyncSelect, Field, InlineField, TextArea } from '@grafana/ui';
33
import { DataQuery } from '@grafana/schema';
44
import { getBackendSrv } from '@grafana/runtime';
55
import {
@@ -10,8 +10,9 @@ import {
1010
QueryEditorProps,
1111
SelectableValue,
1212
} from '@grafana/data';
13-
import { Observable } from 'rxjs';
13+
import { Observable} from 'rxjs';
1414
import invariant from 'tiny-invariant';
15+
import { createRequestVariables } from 'datasource';
1516

1617
/**
1718
* The _Variables_ DataSource is defined separately from the UQL query
@@ -25,6 +26,7 @@ import invariant from 'tiny-invariant';
2526
type VariableDataSource = DataSourceApi<VariableQuery>;
2627
interface VariableQuery extends DataQuery {
2728
attributeKey: string;
29+
scopeFilterExpression?: string;
2830
}
2931

3032
export class VariableEditor extends CustomVariableSupport<VariableDataSource> {
@@ -38,7 +40,7 @@ export class VariableEditor extends CustomVariableSupport<VariableDataSource> {
3840
*/
3941
query = (request: DataQueryRequest<VariableQuery>): Observable<DataQueryResponse> => {
4042
const { url, projectName } = this;
41-
const { attributeKey } = request.targets[0];
43+
const { attributeKey, scopeFilterExpression } = request.targets[0];
4244
invariant(typeof attributeKey === 'string', 'Invalid attribute key');
4345

4446
return new Observable((subscriber) => {
@@ -50,6 +52,8 @@ export class VariableEditor extends CustomVariableSupport<VariableDataSource> {
5052
'scope-to-attribute-keys': [attributeKey],
5153
'oldest-time': request.range.from,
5254
'youngest-time': request.range.to,
55+
'template-variables': createRequestVariables(),
56+
'scope-to-filter-expression': scopeFilterExpression
5357
},
5458
})
5559
.then((res: AttributeRes) => {
@@ -112,23 +116,41 @@ export class VariableEditor extends CustomVariableSupport<VariableDataSource> {
112116
);
113117

114118
return (
115-
<div className="gf-form">
116-
<InlineField
117-
label="Attribute key"
118-
tooltip="Cloud Observability uses this key to populate the selectable values for the variable when viewing the dashboard. Choose from any attributes currently on your logs, metics, or traces."
119-
>
120-
<AsyncSelect
121-
defaultOptions
122-
cacheOptions
123-
defaultValue={query ? { label: query.attributeKey, value: query.attributeKey } : undefined}
124-
loadOptions={loadOptions}
125-
onChange={(v) => {
126-
if (v.value) {
127-
onChange({ refId: v.value, attributeKey: v.value });
128-
}
129-
}}
130-
/>
131-
</InlineField>
119+
<div>
120+
<div className="gf-form">
121+
<InlineField
122+
label="Attribute key"
123+
tooltip="Cloud Observability uses this key to populate the selectable values for the variable when viewing the dashboard. Choose from any attributes currently on your logs, metics, or traces."
124+
>
125+
<AsyncSelect
126+
defaultOptions
127+
cacheOptions
128+
allowCustomValue={true}
129+
defaultValue={query ? { label: query.attributeKey, value: query.attributeKey } : undefined}
130+
loadOptions={loadOptions}
131+
onChange={(v) => {
132+
if (v.value) {
133+
onChange({...query, refId: v.value, attributeKey: v.value });
134+
}
135+
}}
136+
/>
137+
</InlineField>
138+
</div>
139+
140+
<div>
141+
<Field label="UQL Filter Expression">
142+
<TextArea
143+
type="text"
144+
width="100px"
145+
rows={2}
146+
defaultValue={query.scopeFilterExpression}
147+
onChange={(ev) => {
148+
if (ev.currentTarget.value) {
149+
onChange({...query, scopeFilterExpression: ev.currentTarget.value})
150+
}
151+
}} />
152+
</Field>
153+
</div>
132154
</div>
133155
);
134156
};

src/datasource.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
DataSourceApi,
55
DataSourceInstanceSettings,
66
rangeUtil,
7+
ScopedVars
78
} from '@grafana/data';
89
import { config, getBackendSrv, getTemplateSrv } from '@grafana/runtime';
910
import { preprocessData } from './preprocessors';
@@ -61,6 +62,7 @@ export class DataSource extends DataSourceApi<LightstepQuery, LightstepDataSourc
6162
const notebookURL = createNotebookURL(request, visibleTargets, projectName);
6263

6364
const requests = visibleTargets.map(async (query) => {
65+
6466
const res = await getBackendSrv().post(`${this.url}/projects/${query.projectName}/telemetry/query_timeseries`, {
6567
data: {
6668
attributes: {
@@ -70,7 +72,7 @@ export class DataSource extends DataSourceApi<LightstepQuery, LightstepDataSourc
7072
'youngest-time': request.range.to,
7173
// query_timeseries minimum supported output-period is 1 second
7274
'output-period': Math.max(1, rangeUtil.intervalToSeconds(request.interval)),
73-
'template-variables': createRequestVariables(),
75+
'template-variables': createRequestVariables(request.scopedVars),
7476
},
7577
analytics: {
7678
anonymized_user: hashedEmail,
@@ -150,7 +152,7 @@ export class DataSource extends DataSourceApi<LightstepQuery, LightstepDataSourc
150152
* Translates Grafana dashboard variables into a set of LS API template
151153
* variables
152154
*/
153-
function createRequestVariables() {
155+
export function createRequestVariables(scopedVars?: ScopedVars) {
154156
return getTemplateSrv()
155157
.getVariables()
156158
.map((v) => {
@@ -163,6 +165,16 @@ function createRequestVariables() {
163165
values = [];
164166
}
165167

168+
// check if there are scopedVars in the request
169+
// that will override the template variable
170+
// nb: Panel options like Repeat will set scopedVars based on the selected template variable
171+
if (scopedVars && scopedVars?.[v.name]) {
172+
const scopedVar = scopedVars[v.name]?.text ?? "";
173+
if (scopedVar !== "") {
174+
values = [scopedVar]
175+
}
176+
}
177+
166178
return {
167179
name: v.name,
168180
values,

0 commit comments

Comments
 (0)