diff --git a/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.test.ts b/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.test.ts index 7c7b7ac23bc..1557d36249f 100644 --- a/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.test.ts +++ b/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.test.ts @@ -334,4 +334,15 @@ describe('LokiQueryModeller', () => { expect(result.operations[1].id).toBe(LokiOperationId.Unwrap); }); }); + + describe('Disabled operations', () => { + it('Can query with line filter contains operation with empty params', () => { + expect( + modeller.renderQuery({ + labels: [{ label: 'app', op: '=', value: 'grafana' }], + operations: [{ id: LokiOperationId.LineContains, params: [''], disabled: true }], + }) + ).toBe('{app="grafana"}'); + }); + }); }); diff --git a/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.ts b/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.ts index 703d4c50f4f..ebb5aeefbb7 100644 --- a/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.ts +++ b/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.ts @@ -25,6 +25,9 @@ export class LokiQueryModeller extends QueryModellerBase { renderOperations(queryString: string, operations: QueryBuilderOperation[]): string { for (const operation of operations) { + if (operation.disabled) { + continue; + } const def = this.operationsRegistry.getIfExists(operation.id); if (!def) { console.error(`Could not find operation ${operation.id} in the registry`); diff --git a/public/app/plugins/datasource/loki/querybuilder/binaryScalarOperations.ts b/public/app/plugins/datasource/loki/querybuilder/binaryScalarOperations.ts index 3b2a56483ba..e41955641fd 100644 --- a/public/app/plugins/datasource/loki/querybuilder/binaryScalarOperations.ts +++ b/public/app/plugins/datasource/loki/querybuilder/binaryScalarOperations.ts @@ -95,6 +95,7 @@ export const binaryScalarOperations: QueryBuilderOperationDefinition[] = binaryS name: opDef.name, params, defaultParams, + toggleable: true, alternativesKey: 'binary scalar operations', category: LokiVisualQueryOperationCategory.BinaryOps, renderer: getSimpleBinaryRenderer(opDef.sign), diff --git a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilder.test.tsx b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilder.test.tsx index 2fa9d9f1801..137d733b7bf 100644 --- a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilder.test.tsx +++ b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilder.test.tsx @@ -7,7 +7,7 @@ import { config } from '@grafana/runtime'; import { createLokiDatasource } from '../../__mocks__/datasource'; import { LokiOperationId, LokiVisualQuery } from '../types'; -import { LokiQueryBuilder, TIME_SPAN_TO_TRIGGER_SAMPLES } from './LokiQueryBuilder'; +import { LokiQueryBuilder, Props, TIME_SPAN_TO_TRIGGER_SAMPLES } from './LokiQueryBuilder'; import { EXPLAIN_LABEL_FILTER_CONTENT } from './LokiQueryBuilderExplained'; const MISSING_LABEL_FILTER_ERROR_MESSAGE = 'Select at least 1 label filter (label and value)'; @@ -317,6 +317,68 @@ describe('LokiQueryBuilder', () => { expect(props.datasource.getDataSamples).toHaveBeenCalledTimes(1); }); }); + + describe('Disabling operations', () => { + let props: Omit; + beforeEach(() => { + props = createDefaultProps(); + props.datasource.getDataSamples = jest.fn().mockReturnValue(new Promise(() => {})); + props.datasource.languageProvider.fetchLabelValues = jest.fn().mockReturnValue(['a', 'b']); + }); + it('Allows to disable operations', async () => { + const onChange = jest.fn(); + + const query: LokiVisualQuery = { + labels: [{ op: '=', label: 'job', value: 'grafana' }], + operations: [ + { + id: LokiOperationId.Logfmt, + params: [], + }, + ], + }; + render(); + + expect(screen.getByText('Logfmt')).toBeInTheDocument(); + await userEvent.click(screen.getByTitle('Disable operation')); + expect(onChange).toHaveBeenCalledWith({ + ...query, + operations: [ + { + ...query.operations[0], + disabled: true, + }, + ], + }); + }); + + it('Allows to enable operations', async () => { + const onChange = jest.fn(); + const query: LokiVisualQuery = { + labels: [{ op: '=', label: 'job', value: 'grafana' }], + operations: [ + { + id: LokiOperationId.Logfmt, + params: [], + disabled: true, + }, + ], + }; + render(); + + expect(screen.getByText('Logfmt')).toBeInTheDocument(); + await userEvent.click(screen.getByTitle('Enable operation')); + expect(onChange).toHaveBeenCalledWith({ + ...query, + operations: [ + { + ...query.operations[0], + disabled: false, + }, + ], + }); + }); + }); }); const getSelectParent = (input: HTMLElement) => diff --git a/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts b/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts index 971ae7e3fc0..2ac580b9dc3 100644 --- a/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts +++ b/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts @@ -48,6 +48,7 @@ export function createRangeOperation( name: getLokiOperationDisplayName(name), params: params, defaultParams, + toggleable: true, alternativesKey: 'range function', category: LokiVisualQueryOperationCategory.RangeFunctions, orderRank: LokiOperationOrder.RangeVectorFunction, @@ -86,6 +87,7 @@ export function createRangeOperationWithGrouping(name: string): QueryBuilderOper }, ], defaultParams: [...rangeOperation.defaultParams, ''], + toggleable: true, alternativesKey: 'range function with grouping', category: LokiVisualQueryOperationCategory.RangeFunctions, renderer: getRangeAggregationWithGroupingRenderer(name, 'by'), @@ -431,6 +433,7 @@ export function createAggregationOperation( }, ], defaultParams: [], + toggleable: true, alternativesKey: 'plain aggregations', category: LokiVisualQueryOperationCategory.Aggregations, renderer: functionRendererLeft, diff --git a/public/app/plugins/datasource/loki/querybuilder/operations.ts b/public/app/plugins/datasource/loki/querybuilder/operations.ts index 1ecdec52d9e..5fb91ce0f2f 100644 --- a/public/app/plugins/datasource/loki/querybuilder/operations.ts +++ b/public/app/plugins/datasource/loki/querybuilder/operations.ts @@ -87,6 +87,7 @@ function getOperationDefinitions(): QueryBuilderOperationDefinition[] { }, ], defaultParams: [], + toggleable: true, alternativesKey: 'format', category: LokiVisualQueryOperationCategory.Formats, orderRank: LokiOperationOrder.Parsers, @@ -125,6 +126,7 @@ function getOperationDefinitions(): QueryBuilderOperationDefinition[] { }, ], defaultParams: [false, false], + toggleable: true, alternativesKey: 'format', category: LokiVisualQueryOperationCategory.Formats, orderRank: LokiOperationOrder.Parsers, @@ -147,6 +149,7 @@ function getOperationDefinitions(): QueryBuilderOperationDefinition[] { }, ], defaultParams: [''], + toggleable: true, alternativesKey: 'format', category: LokiVisualQueryOperationCategory.Formats, orderRank: LokiOperationOrder.Parsers, @@ -169,6 +172,7 @@ function getOperationDefinitions(): QueryBuilderOperationDefinition[] { }, ], defaultParams: [''], + toggleable: true, alternativesKey: 'format', category: LokiVisualQueryOperationCategory.Formats, orderRank: LokiOperationOrder.Parsers, @@ -182,6 +186,7 @@ function getOperationDefinitions(): QueryBuilderOperationDefinition[] { name: 'Unpack', params: [], defaultParams: [], + toggleable: true, alternativesKey: 'format', category: LokiVisualQueryOperationCategory.Formats, orderRank: LokiOperationOrder.Parsers, @@ -204,6 +209,7 @@ function getOperationDefinitions(): QueryBuilderOperationDefinition[] { }, ], defaultParams: [''], + toggleable: true, alternativesKey: 'format', category: LokiVisualQueryOperationCategory.Formats, orderRank: LokiOperationOrder.PipeOperations, @@ -225,6 +231,7 @@ Example: \`{{.status_code}} - {{.message}}\` { name: 'Rename to', type: 'string' }, ], defaultParams: ['', ''], + toggleable: true, alternativesKey: 'format', category: LokiVisualQueryOperationCategory.Formats, orderRank: LokiOperationOrder.PipeOperations, @@ -255,6 +262,7 @@ Example: \`\`error_level=\`level\` \`\` }, ], defaultParams: [''], + toggleable: true, alternativesKey: 'line filter', category: LokiVisualQueryOperationCategory.LineFilters, orderRank: LokiOperationOrder.LineFilters, @@ -278,6 +286,7 @@ Example: \`\`error_level=\`level\` \`\` }, ], defaultParams: [''], + toggleable: true, alternativesKey: 'line filter', category: LokiVisualQueryOperationCategory.LineFilters, orderRank: LokiOperationOrder.LineFilters, @@ -301,6 +310,7 @@ Example: \`\`error_level=\`level\` \`\` }, ], defaultParams: [''], + toggleable: true, alternativesKey: 'line filter', category: LokiVisualQueryOperationCategory.LineFilters, orderRank: LokiOperationOrder.LineFilters, @@ -324,6 +334,7 @@ Example: \`\`error_level=\`level\` \`\` }, ], defaultParams: [''], + toggleable: true, alternativesKey: 'line filter', category: LokiVisualQueryOperationCategory.LineFilters, orderRank: LokiOperationOrder.LineFilters, @@ -347,6 +358,7 @@ Example: \`\`error_level=\`level\` \`\` }, ], defaultParams: [''], + toggleable: true, alternativesKey: 'line filter', category: LokiVisualQueryOperationCategory.LineFilters, orderRank: LokiOperationOrder.LineFilters, @@ -370,6 +382,7 @@ Example: \`\`error_level=\`level\` \`\` }, ], defaultParams: [''], + toggleable: true, alternativesKey: 'line filter', category: LokiVisualQueryOperationCategory.LineFilters, orderRank: LokiOperationOrder.LineFilters, @@ -397,6 +410,7 @@ Example: \`\`error_level=\`level\` \`\` }, ], defaultParams: ['|=', ''], + toggleable: true, alternativesKey: 'line filter', category: LokiVisualQueryOperationCategory.LineFilters, orderRank: LokiOperationOrder.LineFilters, @@ -427,6 +441,7 @@ Example: \`\`error_level=\`level\` \`\` { name: 'Value', type: 'string', minWidth: 14 }, ], defaultParams: ['', '=', ''], + toggleable: true, alternativesKey: 'label filter', category: LokiVisualQueryOperationCategory.LabelFilters, orderRank: LokiOperationOrder.PipeOperations, @@ -448,6 +463,7 @@ Example: \`\`error_level=\`level\` \`\` { name: 'Value', type: 'string', minWidth: 14 }, ], defaultParams: ['', '=', ''], + toggleable: true, alternativesKey: 'label filter', category: LokiVisualQueryOperationCategory.LabelFilters, orderRank: LokiOperationOrder.PipeOperations, @@ -461,6 +477,7 @@ Example: \`\`error_level=\`level\` \`\` name: 'No pipeline errors', params: [], defaultParams: [], + toggleable: true, alternativesKey: 'label filter', category: LokiVisualQueryOperationCategory.LabelFilters, orderRank: LokiOperationOrder.NoErrors, @@ -489,6 +506,7 @@ Example: \`\`error_level=\`level\` \`\` }, ], defaultParams: ['', ''], + toggleable: true, alternativesKey: 'format', category: LokiVisualQueryOperationCategory.Formats, orderRank: LokiOperationOrder.Unwrap, @@ -509,6 +527,7 @@ Example: \`\`error_level=\`level\` \`\` name: 'Decolorize', params: [], defaultParams: [], + toggleable: true, alternativesKey: 'format', category: LokiVisualQueryOperationCategory.Formats, orderRank: LokiOperationOrder.PipeOperations, @@ -533,6 +552,7 @@ Example: \`\`error_level=\`level\` \`\` }, ], defaultParams: [''], + toggleable: true, alternativesKey: 'format', category: LokiVisualQueryOperationCategory.Formats, orderRank: LokiOperationOrder.PipeOperations, @@ -557,6 +577,7 @@ Example: \`\`error_level=\`level\` \`\` }, ], defaultParams: [''], + toggleable: true, alternativesKey: 'format', category: LokiVisualQueryOperationCategory.Formats, orderRank: LokiOperationOrder.PipeOperations, @@ -571,6 +592,7 @@ Example: \`\`error_level=\`level\` \`\` name: 'Binary operation with query', params: [], defaultParams: [], + toggleable: true, category: LokiVisualQueryOperationCategory.BinaryOps, renderer: (model, def, innerExpr) => innerExpr, addOperationHandler: addNestedQueryHandler,