diff --git a/public/app/plugins/datasource/loki/components/VariableQueryEditor.test.tsx b/public/app/plugins/datasource/loki/components/VariableQueryEditor.test.tsx
index c55b0185999..0f66035ed62 100644
--- a/public/app/plugins/datasource/loki/components/VariableQueryEditor.test.tsx
+++ b/public/app/plugins/datasource/loki/components/VariableQueryEditor.test.tsx
@@ -10,43 +10,57 @@ import { LokiVariableQueryType } from '../types';
import { LokiVariableQueryEditor, Props } from './VariableQueryEditor';
-const props: Props = {
- datasource: createLokiDatasource({} as unknown as TemplateSrv),
- query: {
- refId: 'test',
- type: LokiVariableQueryType.LabelNames,
- },
- onRunQuery: () => {},
- onChange: () => {},
-};
+const refId = 'LokiVariableQueryEditor-VariableQuery';
describe('LokiVariableQueryEditor', () => {
- test('Allows to create a Label names variable', async () => {
- const onChange = jest.fn();
+ let props: Props;
- render();
+ beforeEach(() => {
+ props = {
+ datasource: createLokiDatasource({} as unknown as TemplateSrv),
+ query: {
+ refId: 'test',
+ type: LokiVariableQueryType.LabelNames,
+ },
+ onRunQuery: () => {},
+ onChange: () => {},
+ };
- expect(onChange).not.toHaveBeenCalled();
-
- await selectOptionInTest(screen.getByLabelText('Query type'), 'Label names');
-
- expect(onChange).toHaveBeenCalledWith({
- type: LokiVariableQueryType.LabelNames,
- label: '',
- stream: '',
- refId: 'LokiVariableQueryEditor-VariableQuery',
- });
+ jest.spyOn(props.datasource, 'labelNamesQuery').mockResolvedValue([]);
});
- test('Allows to create a Label values variable', async () => {
+ test('Allows to create a Label names variable', async () => {
const onChange = jest.fn();
-
render();
expect(onChange).not.toHaveBeenCalled();
await selectOptionInTest(screen.getByLabelText('Query type'), 'Label values');
- await userEvent.type(screen.getByLabelText('Label'), 'label');
+
+ expect(onChange).toHaveBeenCalledWith({
+ type: LokiVariableQueryType.LabelValues,
+ label: '',
+ stream: '',
+ refId,
+ });
+ });
+
+ test('Allows to create a Label values variable', async () => {
+ const onChange = jest.fn();
+ jest.spyOn(props.datasource, 'labelNamesQuery').mockResolvedValue([
+ {
+ text: 'moon',
+ },
+ {
+ text: 'luna',
+ },
+ ]);
+ render();
+
+ expect(onChange).not.toHaveBeenCalled();
+
+ await selectOptionInTest(screen.getByLabelText('Query type'), 'Label values');
+ await selectOptionInTest(screen.getByLabelText('Label'), 'luna');
await userEvent.type(screen.getByLabelText('Stream selector'), 'stream');
await waitFor(() => expect(screen.getByDisplayValue('stream')).toBeInTheDocument());
@@ -55,20 +69,68 @@ describe('LokiVariableQueryEditor', () => {
expect(onChange).toHaveBeenCalledWith({
type: LokiVariableQueryType.LabelValues,
- label: 'label',
+ label: 'luna',
stream: 'stream',
- refId: 'LokiVariableQueryEditor-VariableQuery',
+ refId,
+ });
+ });
+
+ test('Allows to create a Label values variable with custom label', async () => {
+ const onChange = jest.fn();
+ jest.spyOn(props.datasource, 'labelNamesQuery').mockResolvedValue([
+ {
+ text: 'moon',
+ },
+ {
+ text: 'luna',
+ },
+ ]);
+ render();
+
+ expect(onChange).not.toHaveBeenCalled();
+
+ await selectOptionInTest(screen.getByLabelText('Query type'), 'Label values');
+ await userEvent.type(screen.getByLabelText('Label'), 'sol{enter}');
+ await userEvent.type(screen.getByLabelText('Stream selector'), 'stream');
+
+ await waitFor(() => expect(screen.getByDisplayValue('stream')).toBeInTheDocument());
+
+ await userEvent.click(document.body);
+
+ expect(onChange).toHaveBeenCalledWith({
+ type: LokiVariableQueryType.LabelValues,
+ label: 'sol',
+ stream: 'stream',
+ refId,
});
});
test('Migrates legacy string queries to LokiVariableQuery instances', async () => {
- const query = 'label_values(log stream selector, label)';
-
+ const query = 'label_values(log stream selector, label_selector)';
// @ts-expect-error
render( {}} query={query} />);
await waitFor(() => expect(screen.getByText('Label values')).toBeInTheDocument());
- await waitFor(() => expect(screen.getByDisplayValue('label')).toBeInTheDocument());
+ await waitFor(() => expect(screen.getByText('label_selector')).toBeInTheDocument());
+ await waitFor(() => expect(screen.getByDisplayValue('log stream selector')).toBeInTheDocument());
+ });
+
+ test('Receives a query instance and assigns its values when editing', async () => {
+ render(
+ {}}
+ query={{
+ type: LokiVariableQueryType.LabelValues,
+ label: 'label_selector',
+ stream: 'log stream selector',
+ refId,
+ }}
+ />
+ );
+
+ await waitFor(() => expect(screen.getByText('Label values')).toBeInTheDocument());
+ await waitFor(() => expect(screen.getByText('label_selector')).toBeInTheDocument());
await waitFor(() => expect(screen.getByDisplayValue('log stream selector')).toBeInTheDocument());
});
});
diff --git a/public/app/plugins/datasource/loki/components/VariableQueryEditor.tsx b/public/app/plugins/datasource/loki/components/VariableQueryEditor.tsx
index 770d6380cac..22898babca4 100644
--- a/public/app/plugins/datasource/loki/components/VariableQueryEditor.tsx
+++ b/public/app/plugins/datasource/loki/components/VariableQueryEditor.tsx
@@ -14,22 +14,39 @@ const variableOptions = [
export type Props = QueryEditorProps;
-export const LokiVariableQueryEditor: FC = ({ onChange, query }) => {
+const refId = 'LokiVariableQueryEditor-VariableQuery';
+
+export const LokiVariableQueryEditor: FC = ({ onChange, query, datasource }) => {
const [type, setType] = useState(undefined);
const [label, setLabel] = useState('');
+ const [labelOptions, setLabelOptions] = useState>>([]);
const [stream, setStream] = useState('');
useEffect(() => {
- if (!query || typeof query !== 'string') {
+ if (!query) {
return;
}
- const variableQuery = migrateVariableQuery(query);
+ const variableQuery = typeof query === 'string' ? migrateVariableQuery(query) : query;
setType(variableQuery.type);
setLabel(variableQuery.label || '');
setStream(variableQuery.stream || '');
+
+ if (variableQuery.label) {
+ setLabelOptions([{ label: variableQuery.label, value: variableQuery.label }]);
+ }
}, [query]);
+ useEffect(() => {
+ if (type !== QueryType.LabelValues) {
+ return;
+ }
+
+ datasource.labelNamesQuery().then((labelNames: Array<{ text: string }>) => {
+ setLabelOptions(labelNames.map(({ text }) => ({ label: text, value: text })));
+ });
+ }, [datasource, type]);
+
const onQueryTypeChange = (newType: SelectableValue) => {
setType(newType.value);
if (newType.value !== undefined) {
@@ -37,13 +54,13 @@ export const LokiVariableQueryEditor: FC = ({ onChange, query }) => {
type: newType.value,
label,
stream,
- refId: 'LokiVariableQueryEditor-VariableQuery',
+ refId,
});
}
};
- const onLabelChange = (e: FormEvent) => {
- setLabel(e.currentTarget.value);
+ const onLabelChange = (newLabel: SelectableValue) => {
+ setLabel(newLabel.value || '');
};
const onStreamChange = (e: FormEvent) => {
@@ -71,15 +88,33 @@ export const LokiVariableQueryEditor: FC = ({ onChange, query }) => {
{type === QueryType.LabelValues && (
<>
-
+
-
+
+ Optional. If defined, a list of values for the label in the specified log stream selector is returned.
+
+ }
+ >
>