diff --git a/packages/grafana-schema/src/raw/composable/azuremonitor/dataquery/x/AzureMonitorDataQuery_types.gen.ts b/packages/grafana-schema/src/raw/composable/azuremonitor/dataquery/x/AzureMonitorDataQuery_types.gen.ts index 55ad5313063..d889801bfb4 100644 --- a/packages/grafana-schema/src/raw/composable/azuremonitor/dataquery/x/AzureMonitorDataQuery_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/azuremonitor/dataquery/x/AzureMonitorDataQuery_types.gen.ts @@ -329,8 +329,17 @@ export enum BuilderQueryEditorOrderByOptions { Desc = 'desc', } +export enum BuilderQueryEditorReduceParameterTypes { + Generic = 'generic', + Numeric = 'numeric', +} + export interface BuilderQueryEditorProperty { name: string; + /** + * Optional parameter type for function properties + */ + parameterType?: BuilderQueryEditorReduceParameterTypes; type: BuilderQueryEditorPropertyType; } diff --git a/pkg/tsdb/azuremonitor/kinds/dataquery/types_dataquery_gen.go b/pkg/tsdb/azuremonitor/kinds/dataquery/types_dataquery_gen.go index e1deb1f008b..47594fbd55c 100644 --- a/pkg/tsdb/azuremonitor/kinds/dataquery/types_dataquery_gen.go +++ b/pkg/tsdb/azuremonitor/kinds/dataquery/types_dataquery_gen.go @@ -223,6 +223,8 @@ func NewBuilderQueryEditorPropertyExpression() *BuilderQueryEditorPropertyExpres type BuilderQueryEditorProperty struct { Type BuilderQueryEditorPropertyType `json:"type"` Name string `json:"name"` + // Optional parameter type for function properties + ParameterType *BuilderQueryEditorReduceParameterTypes `json:"parameterType,omitempty"` } // NewBuilderQueryEditorProperty creates a new BuilderQueryEditorProperty object. @@ -242,6 +244,13 @@ const ( BuilderQueryEditorPropertyTypeInterval BuilderQueryEditorPropertyType = "interval" ) +type BuilderQueryEditorReduceParameterTypes string + +const ( + BuilderQueryEditorReduceParameterTypesGeneric BuilderQueryEditorReduceParameterTypes = "generic" + BuilderQueryEditorReduceParameterTypesNumeric BuilderQueryEditorReduceParameterTypes = "numeric" +) + type BuilderQueryEditorExpressionType string const ( diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.test.tsx b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.test.tsx new file mode 100644 index 00000000000..3c472fcb69e --- /dev/null +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.test.tsx @@ -0,0 +1,191 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { + BuilderQueryEditorExpressionType, + BuilderQueryEditorPropertyType, + BuilderQueryEditorReduceExpression, + BuilderQueryEditorReduceParameterTypes, +} from '../../dataquery.gen'; + +import AggregateItem from './AggregateItem'; + +describe('AggregateItem', () => { + const mockColumns = [ + { label: 'TimeGenerated', value: 'TimeGenerated' }, + { label: 'Level', value: 'Level' }, + { label: 'Message', value: 'Message' }, + ]; + + const mockTemplateVariables = { label: '$variable', value: '$variable' }; + + const defaultAggregate: BuilderQueryEditorReduceExpression = { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'TimeGenerated', + type: BuilderQueryEditorPropertyType.String, + }, + }; + + const defaultProps = { + aggregate: defaultAggregate, + columns: mockColumns, + onChange: jest.fn(), + onDelete: jest.fn(), + templateVariableOptions: mockTemplateVariables, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders aggregate function select (with column field)', () => { + render(); + expect(screen.getByLabelText('Aggregate function')).toBeInTheDocument(); + expect(screen.getByLabelText('Column')).toBeInTheDocument(); + }); + + it('does not render column select for count aggregates', () => { + const countAggregate = { + ...defaultAggregate, + reduce: { + name: 'count', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Generic, + }, + }; + render(); + expect(screen.queryByLabelText('Column')).not.toBeInTheDocument(); + }); + + it('renders percentile input and OF label for percentile aggregate', () => { + const percentileAggregate: BuilderQueryEditorReduceExpression = { + reduce: { + name: 'percentile', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + parameters: [ + { + type: BuilderQueryEditorExpressionType.Function_parameter, + fieldType: BuilderQueryEditorPropertyType.Number, + value: '95', + }, + { + type: BuilderQueryEditorExpressionType.Function_parameter, + fieldType: BuilderQueryEditorPropertyType.String, + value: 'TimeGenerated', + }, + ], + property: { + name: 'TimeGenerated', + type: BuilderQueryEditorPropertyType.String, + }, + }; + render(); + expect(screen.getByDisplayValue('95')).toBeInTheDocument(); + expect(screen.getByText('OF')).toBeInTheDocument(); + }); + + it('calls onChange when aggregate function changes', async () => { + render(); + + const select = screen.getByLabelText('Aggregate function'); + await userEvent.click(select); + + const avgOption = await screen.findByText('avg'); + await userEvent.click(avgOption); + + expect(defaultProps.onChange).toHaveBeenCalledWith( + expect.objectContaining({ + reduce: expect.objectContaining({ + name: 'avg', + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }), + }) + ); + }); + + it('calls onChange when column changes', async () => { + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + const levelOption = await screen.findByText('Level'); + await userEvent.click(levelOption); + + expect(defaultProps.onChange).toHaveBeenCalledWith( + expect.objectContaining({ + property: expect.objectContaining({ + name: 'Level', + }), + }) + ); + }); + + it('calls onChange when percentile value changes', async () => { + const percentileAggregate: BuilderQueryEditorReduceExpression = { + reduce: { + name: 'percentile', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + parameters: [ + { + type: BuilderQueryEditorExpressionType.Function_parameter, + fieldType: BuilderQueryEditorPropertyType.Number, + value: '95', + }, + { + type: BuilderQueryEditorExpressionType.Function_parameter, + fieldType: BuilderQueryEditorPropertyType.String, + value: 'TimeGenerated', + }, + ], + }; + render(); + + const percentileInput = screen.getByDisplayValue('95'); + await userEvent.clear(percentileInput); + await userEvent.type(percentileInput, '99'); + + expect(defaultProps.onChange).toHaveBeenCalledWith( + expect.objectContaining({ + parameters: expect.arrayContaining([expect.objectContaining({ value: '99' })]), + }) + ); + }); + + it('calls onDelete when delete button clicked', async () => { + render(); + + const deleteButton = screen.getByLabelText('Remove'); + await userEvent.click(deleteButton); + expect(defaultProps.onDelete).toHaveBeenCalledTimes(1); + }); + + it('includes template variables in column options', async () => { + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + expect(await screen.findByText('$variable')).toBeInTheDocument(); + }); + + it('handles array of template variables', async () => { + const arrayTemplateVars = [ + { label: '$var1', value: '$var1' }, + { label: '$var2', value: '$var2' }, + ]; + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + + expect(await screen.findByText('$var1')).toBeInTheDocument(); + }); +}); diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.tsx b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.tsx index 867098f7574..2eacf01b8bd 100644 --- a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.tsx @@ -9,6 +9,7 @@ import { BuilderQueryEditorExpressionType, BuilderQueryEditorPropertyType, BuilderQueryEditorReduceExpression, + BuilderQueryEditorReduceParameterTypes, } from '../../dataquery.gen'; import { aggregateOptions, inputFieldSize } from './utils'; @@ -65,8 +66,16 @@ const AggregateItem: React.FC = ({ }; const handleAggregateChange = (funcName?: string) => { + const functionParameterType = + aggregateOptions.find((option) => option.value === (funcName || ''))?.parameterType || + BuilderQueryEditorReduceParameterTypes.Generic; + updateAggregate({ - reduce: { name: funcName || '', type: BuilderQueryEditorPropertyType.Function }, + reduce: { + name: funcName || '', + type: BuilderQueryEditorPropertyType.Function, + parameterType: functionParameterType, + }, }); }; diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.test.tsx b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.test.tsx new file mode 100644 index 00000000000..ea073e1e8e5 --- /dev/null +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.test.tsx @@ -0,0 +1,293 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { + AzureQueryType, + BuilderQueryEditorExpressionType, + BuilderQueryEditorPropertyType, + BuilderQueryEditorReduceExpression, + BuilderQueryEditorReduceParameterTypes, +} from '../../dataquery.gen'; +import { AzureMonitorQuery } from '../../types/query'; + +import { AggregateSection } from './AggregationSection'; + +describe('AggregationSection', () => { + const mockAllColumns = [ + { name: 'TimeGenerated', type: 'datetime' }, + { name: 'Level', type: 'string' }, + { name: 'Count', type: 'int' }, + { name: 'Duration', type: 'real' }, + ]; + + const mockTemplateVariables = { label: '$variable', value: '$variable' }; + + const createMockQuery = (reduce?: BuilderQueryEditorReduceExpression[]): AzureMonitorQuery => ({ + refId: 'A', + queryType: AzureQueryType.LogAnalytics, + azureLogAnalytics: { + builderQuery: { + from: { + type: BuilderQueryEditorExpressionType.Property, + property: { type: BuilderQueryEditorPropertyType.String, name: 'AppRequests' }, + }, + columns: { + type: BuilderQueryEditorExpressionType.Property, + columns: [], + }, + reduce: { + type: BuilderQueryEditorExpressionType.Reduce, + expressions: reduce || [], + }, + where: { + type: BuilderQueryEditorExpressionType.And, + expressions: [], + }, + groupBy: { + type: BuilderQueryEditorExpressionType.Group_by, + expressions: [], + }, + }, + }, + }); + + const defaultProps = { + query: createMockQuery(), + allColumns: mockAllColumns, + templateVariableOptions: mockTemplateVariables, + buildAndUpdateQuery: jest.fn(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders the aggregate section', () => { + render(); + expect(screen.getByTestId('aggregate-section')).toBeInTheDocument(); + }); + + it('renders empty list when no aggregates exist', () => { + render(); + const addButton = screen.getByRole('button', { name: /add/i }); + expect(addButton).toBeInTheDocument(); + }); + + it('renders existing aggregates', () => { + const existingAggregates: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'Count', + type: BuilderQueryEditorPropertyType.String, + }, + }, + { + reduce: { + name: 'avg', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'Duration', + type: BuilderQueryEditorPropertyType.String, + }, + }, + ]; + + const queryWithAggregates = createMockQuery(existingAggregates); + render(); + + expect(screen.getAllByLabelText('Aggregate function')).toHaveLength(2); + }); + + it('calls buildAndUpdateQuery when aggregate is added', async () => { + render(); + + const addButton = screen.getByRole('button', { name: /add/i }); + await userEvent.click(addButton); + + expect(defaultProps.buildAndUpdateQuery).toHaveBeenCalledWith({ + reduce: expect.arrayContaining([expect.objectContaining({})]), + }); + }); + + it('calls buildAndUpdateQuery when aggregate is deleted', async () => { + const existingAggregates: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'Count', + type: BuilderQueryEditorPropertyType.String, + }, + }, + ]; + const avgAggregate = { + reduce: { + name: 'avg', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'Duration', + type: BuilderQueryEditorPropertyType.String, + }, + }; + existingAggregates.push(avgAggregate); + + const queryWithAggregates = createMockQuery(existingAggregates); + render(); + + const deleteButton = (await screen.findAllByLabelText('Remove'))[0]; + await userEvent.click(deleteButton); + + expect(defaultProps.buildAndUpdateQuery).toHaveBeenCalledWith({ + reduce: [avgAggregate], + }); + expect(screen.getAllByLabelText('Aggregate function')).toHaveLength(1); + }); + + it('provides numeric columns for numeric aggregate functions', async () => { + const numericAggregate: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + }, + ]; + + const queryWithAggregate = createMockQuery(numericAggregate); + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('Count')).toBeInTheDocument(); + expect(await screen.getByText('Duration')).toBeInTheDocument(); + + expect(screen.queryByText('Level')).not.toBeInTheDocument(); + }); + + it('provides all columns for generic aggregate functions', async () => { + const genericAggregate: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'min', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Generic, + }, + }, + ]; + + const queryWithAggregate = createMockQuery(genericAggregate); + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('TimeGenerated')).toBeInTheDocument(); + expect(await screen.getByText('Level')).toBeInTheDocument(); + expect(await screen.getByText('Count')).toBeInTheDocument(); + expect(await screen.getByText('Duration')).toBeInTheDocument(); + }); + + it('resets aggregates when table changes', () => { + const existingAggregates: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'Count', + type: BuilderQueryEditorPropertyType.String, + }, + }, + ]; + + const queryWithAggregates = createMockQuery(existingAggregates); + const { rerender } = render(); + + const newQuery = createMockQuery(existingAggregates); + newQuery.azureLogAnalytics!.builderQuery!.from!.property.name = 'AppEvents'; + + rerender(); + + const addButton = screen.getByRole('button', { name: /add/i }); + expect(addButton).toBeInTheDocument(); + }); + + it('uses selected columns when available', async () => { + const aggregate: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Generic, + }, + }, + ]; + + const query = createMockQuery(aggregate); + query.azureLogAnalytics!.builderQuery = { + ...query.azureLogAnalytics!.builderQuery, + columns: { + columns: ['TimeGenerated', 'Level'], + type: BuilderQueryEditorExpressionType.Property, + }, + }; + + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('TimeGenerated')).toBeInTheDocument(); + expect(await screen.getByText('Level')).toBeInTheDocument(); + + expect(screen.queryByText('Count')).not.toBeInTheDocument(); + expect(screen.queryByText('Duration')).not.toBeInTheDocument(); + }); + + it('falls back to all columns when no columns selected', async () => { + const aggregate: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Generic, + }, + }, + ]; + + const query = createMockQuery(aggregate); + query.azureLogAnalytics!.builderQuery = { + ...query.azureLogAnalytics!.builderQuery, + columns: { + columns: [], + type: BuilderQueryEditorExpressionType.Property, + }, + }; + + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('TimeGenerated')).toBeInTheDocument(); + expect(await screen.getByText('Level')).toBeInTheDocument(); + expect(await screen.getByText('Count')).toBeInTheDocument(); + expect(await screen.getByText('Duration')).toBeInTheDocument(); + }); +}); diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.tsx b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.tsx index 4f3a1050a14..6910792685d 100644 --- a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.tsx @@ -4,12 +4,12 @@ import { SelectableValue } from '@grafana/data'; import { t } from '@grafana/i18n'; import { EditorField, EditorFieldGroup, EditorList, EditorRow } from '@grafana/plugin-ui'; -import { BuilderQueryEditorReduceExpression } from '../../dataquery.gen'; +import { BuilderQueryEditorReduceExpression, BuilderQueryEditorReduceParameterTypes } from '../../dataquery.gen'; import { AzureLogAnalyticsMetadataColumn } from '../../types/logAnalyticsMetadata'; import { AzureMonitorQuery } from '../../types/query'; import AggregateItem from './AggregateItem'; -import { BuildAndUpdateOptions } from './utils'; +import { BuildAndUpdateOptions, isNumericColumn } from './utils'; interface AggregateSectionProps { query: AzureMonitorQuery; @@ -43,6 +43,10 @@ export const AggregateSection: React.FC = ({ const availableColumns: Array> = builderQuery?.columns?.columns?.length ? builderQuery.columns.columns.map((col) => ({ label: col, value: col })) : allColumns.map((col) => ({ label: col.name, value: col.name })); + const numericColumns: Array> = allColumns.filter(isNumericColumn).map((col) => ({ + label: col.name, + value: col.name, + })); const onChange = (newItems: Array>) => { setAggregates(newItems); @@ -82,7 +86,12 @@ export const AggregateSection: React.FC = ({ @@ -93,6 +102,7 @@ export const AggregateSection: React.FC = ({ function makeRenderAggregate( availableColumns: Array>, + numericColumns: Array>, onDeleteAggregate: (aggregate: BuilderQueryEditorReduceExpression) => void, templateVariableOptions: SelectableValue ) { @@ -105,7 +115,11 @@ function makeRenderAggregate( aggregate={item} onChange={onChange} onDelete={() => onDeleteAggregate(item)} - columns={availableColumns} + columns={ + item.reduce?.name && item.reduce.parameterType === BuilderQueryEditorReduceParameterTypes.Numeric + ? numericColumns + : availableColumns + } templateVariableOptions={templateVariableOptions} /> ); diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/utils.ts b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/utils.ts index 062dac286f9..cb660fb98e9 100644 --- a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/utils.ts +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/utils.ts @@ -9,6 +9,7 @@ import { BuilderQueryEditorPropertyExpression, BuilderQueryEditorPropertyType, BuilderQueryEditorReduceExpression, + BuilderQueryEditorReduceParameterTypes, BuilderQueryEditorWhereExpression, BuilderQueryExpression, } from '../../dataquery.gen'; @@ -93,12 +94,17 @@ export interface BuildAndUpdateOptions { } export const aggregateOptions = [ - { label: 'sum', value: 'sum' }, - { label: 'avg', value: 'avg' }, - { label: 'percentile', value: 'percentile' }, - { label: 'count', value: 'count' }, - { label: 'min', value: 'min' }, - { label: 'max', value: 'max' }, - { label: 'dcount', value: 'dcount' }, - { label: 'stdev', value: 'stdev' }, + { label: 'sum', value: 'sum', parameterType: BuilderQueryEditorReduceParameterTypes.Numeric }, + { label: 'avg', value: 'avg', parameterType: BuilderQueryEditorReduceParameterTypes.Numeric }, + { label: 'percentile', value: 'percentile', parameterType: BuilderQueryEditorReduceParameterTypes.Numeric }, + { label: 'stdev', value: 'stdev', parameterType: BuilderQueryEditorReduceParameterTypes.Numeric }, + { label: 'min', value: 'min', parameterType: BuilderQueryEditorReduceParameterTypes.Generic }, + { label: 'max', value: 'max', parameterType: BuilderQueryEditorReduceParameterTypes.Generic }, + { label: 'count', value: 'count', parameterType: BuilderQueryEditorReduceParameterTypes.Generic }, + { label: 'dcount', value: 'dcount', parameterType: BuilderQueryEditorReduceParameterTypes.Generic }, ]; + +export const isNumericColumn = (column: AzureLogAnalyticsMetadataColumn): boolean => { + const numericTypes = ['decimal', 'int', 'long', 'real']; + return numericTypes.includes(column.type); +}; diff --git a/public/app/plugins/datasource/azuremonitor/dataquery.cue b/public/app/plugins/datasource/azuremonitor/dataquery.cue index 4fd52d5f297..403fd1ea72e 100644 --- a/public/app/plugins/datasource/azuremonitor/dataquery.cue +++ b/public/app/plugins/datasource/azuremonitor/dataquery.cue @@ -175,10 +175,13 @@ composableKinds: DataQuery: { #BuilderQueryEditorExpressionType: "property" | "operator" | "reduce" | "function_parameter" | "group_by" | "or" | "and" | "order_by" @cuetsy(kind="enum", memberNames:"Property|Operator|Reduce|FunctionParameter|GroupBy|Or|And|OrderBy") #BuilderQueryEditorPropertyType: "number" | "string" | "boolean" | "datetime" | "time_span" | "function" | "interval" @cuetsy(kind="enum", memberNames:"Number|String|Boolean|Datetime|TimeSpan|Function|Interval") #BuilderQueryEditorOrderByOptions: "asc" | "desc" @cuetsy(kind="enum", memberNames:"Asc|Desc") + #BuilderQueryEditorReduceParameterTypes: "generic" | "numeric" @cuetsy(kind="enum", memberNames:"Asc|Desc") #BuilderQueryEditorProperty: { type: #BuilderQueryEditorPropertyType name: string + // Optional parameter type for function properties + parameterType?: #BuilderQueryEditorReduceParameterTypes } @cuetsy(kind="interface") #BuilderQueryEditorPropertyExpression: { diff --git a/public/app/plugins/datasource/azuremonitor/dataquery.gen.ts b/public/app/plugins/datasource/azuremonitor/dataquery.gen.ts index c4b986970ca..2ed7b87a5ce 100644 --- a/public/app/plugins/datasource/azuremonitor/dataquery.gen.ts +++ b/public/app/plugins/datasource/azuremonitor/dataquery.gen.ts @@ -327,8 +327,17 @@ export enum BuilderQueryEditorOrderByOptions { Desc = 'desc', } +export enum BuilderQueryEditorReduceParameterTypes { + Generic = 'generic', + Numeric = 'numeric', +} + export interface BuilderQueryEditorProperty { name: string; + /** + * Optional parameter type for function properties + */ + parameterType?: BuilderQueryEditorReduceParameterTypes; type: BuilderQueryEditorPropertyType; }