From 4c344322466f9850b66e66c46d50731c4c891677 Mon Sep 17 00:00:00 2001 From: Daniele Rossetti <drossetti@gitlab.com> Date: Wed, 31 Jan 2024 11:52:33 +0000 Subject: [PATCH] Configure metrics FilteredSearch with search metadata --- .../javascripts/observability/client.js | 43 +++++---- .../details/filter_bar/groupby_filter.vue | 28 +++--- .../filter_bar/metrics_filtered_search.vue | 28 +++--- .../metrics/details/metrics_details.vue | 35 +++---- .../details/filter_bar/groupby_filter_spec.js | 65 +++++++------ .../metrics_filtered_search_spec.js | 91 +++++++++++-------- .../metrics/details/metrics_details_spec.js | 41 ++++----- locale/gitlab.pot | 2 +- spec/frontend/observability/client_spec.js | 24 ++--- 9 files changed, 182 insertions(+), 175 deletions(-) diff --git a/app/assets/javascripts/observability/client.js b/app/assets/javascripts/observability/client.js index 3785f42a769f0..5f146fce4817d 100644 --- a/app/assets/javascripts/observability/client.js +++ b/app/assets/javascripts/observability/client.js @@ -337,7 +337,7 @@ async function fetchMetrics(metricsUrl, { filters = {}, limit } = {}) { const SUPPORTED_METRICS_DIMENSION_FILTER_OPERATORS = ['=', '!=', '=~', '!~']; -function addMetricsDimensionFilterToQueryParams(dimensionFilter, params) { +function addMetricsAttributeFilterToQueryParams(dimensionFilter, params) { if (!dimensionFilter || !params) return; Object.entries(dimensionFilter).forEach(([filterName, values]) => { @@ -371,12 +371,12 @@ function addMetricsDateRangeFilterToQueryParams(dateRangeFilter, params) { function addGroupByFilterToQueryParams(groupByFilter, params) { if (!groupByFilter || !params) return; - const { func, dimensions } = groupByFilter; + const { func, attributes } = groupByFilter; if (func) { params.append('groupby_fn', func); } - if (Array.isArray(dimensions) && dimensions.length > 0) { - params.append('groupby_attrs', dimensions.join(',')); + if (Array.isArray(attributes) && attributes.length > 0) { + params.append('groupby_attrs', attributes.join(',')); } } @@ -394,10 +394,10 @@ async function fetchMetric(searchUrl, name, type, options = {}) { mtype: type, }); - const { dimensions, dateRange, groupBy } = options.filters ?? {}; + const { attributes, dateRange, groupBy } = options.filters ?? {}; - if (dimensions) { - addMetricsDimensionFilterToQueryParams(dimensions, params); + if (attributes) { + addMetricsAttributeFilterToQueryParams(attributes, params); } if (dateRange) { @@ -442,17 +442,24 @@ async function fetchMetricSearchMetadata(searchMetadataUrl, name, type) { // }); // return data; - return { - name: 'cpu_seconds_total', - type: 'sum', - description: 'some_description', - last_ingested_at: 1705374438711900000, - attribute_keys: ['host.name', 'host.dc', 'host.type'], - supported_aggregations: ['1m', '1h'], - supported_functions: ['min', 'max', 'avg', 'sum', 'count'], - default_group_by_attributes: ['host.name'], - default_group_by_function: ['avg'], - }; + return new Promise((resolve) => { + setTimeout(() => + resolve( + { + name: 'cpu_seconds_total', + type: 'sum', + description: 'some_description', + last_ingested_at: 1705374438711900000, + attribute_keys: ['host.name', 'host.dc', 'host.type'], + supported_aggregations: ['1m', '1h'], + supported_functions: ['min', 'max', 'avg', 'sum', 'count'], + default_group_by_attributes: ['host.name'], + default_group_by_function: 'avg', + }, + 1000, + ), + ); + }); } catch (e) { return reportErrorAndThrow(e); } diff --git a/ee/app/assets/javascripts/metrics/details/filter_bar/groupby_filter.vue b/ee/app/assets/javascripts/metrics/details/filter_bar/groupby_filter.vue index acfbb5c9b83d6..d6791c1c864e1 100644 --- a/ee/app/assets/javascripts/metrics/details/filter_bar/groupby_filter.vue +++ b/ee/app/assets/javascripts/metrics/details/filter_bar/groupby_filter.vue @@ -10,11 +10,11 @@ export default { groupByPlaceholderMultipleSelect: s__('ObservabilityMetrics|multiple'), }, props: { - searchConfig: { + searchMetadata: { type: Object, required: true, }, - selectedDimensions: { + selectedAttributes: { type: Array, required: true, }, @@ -25,24 +25,24 @@ export default { }, data() { return { - groupByDimensions: this.selectedDimensions, + groupByAttributes: this.selectedAttributes, groupByFunction: this.selectedFunction, }; }, computed: { availableGroupByFunctions() { - return this.searchConfig.groupByFunctions.map((func) => ({ value: func, text: func })); + return this.searchMetadata.supported_functions.map((func) => ({ value: func, text: func })); }, - availableGroupByDimensions() { - return this.searchConfig.dimensions.map((d) => ({ value: d, text: d })); + availableGroupByAttributes() { + return this.searchMetadata.attribute_keys.map((d) => ({ value: d, text: d })); }, groupByLabel() { - return this.groupByDimensions.length > 1 ? this.groupByDimensions.join(', ') : ''; + return this.groupByAttributes.length > 1 ? this.groupByAttributes.join(', ') : ''; }, groupByToggleText() { - if (this.groupByDimensions.length > 0) { - if (this.groupByDimensions.length === 1) { - return this.groupByDimensions[0]; + if (this.groupByAttributes.length > 0) { + if (this.groupByAttributes.length === 1) { + return this.groupByAttributes[0]; } return this.$options.i18n.groupByPlaceholderMultipleSelect; } @@ -52,7 +52,7 @@ export default { methods: { onSelect() { this.$emit('groupBy', { - dimensions: this.groupByDimensions, + attributes: this.groupByAttributes, func: this.groupByFunction, }); }, @@ -70,11 +70,11 @@ export default { /> <span>{{ __('by') }}</span> <gl-collapsible-listbox - v-model="groupByDimensions" - data-testid="group-by-dimensions-dropdown" + v-model="groupByAttributes" + data-testid="group-by-attributes-dropdown" :toggle-text="groupByToggleText" multiple - :items="availableGroupByDimensions" + :items="availableGroupByAttributes" @select="onSelect" /> <span data-testid="group-by-label">{{ groupByLabel }}</span> diff --git a/ee/app/assets/javascripts/metrics/details/filter_bar/metrics_filtered_search.vue b/ee/app/assets/javascripts/metrics/details/filter_bar/metrics_filtered_search.vue index bec6eb6bffe1e..522e5fe64736d 100644 --- a/ee/app/assets/javascripts/metrics/details/filter_bar/metrics_filtered_search.vue +++ b/ee/app/assets/javascripts/metrics/details/filter_bar/metrics_filtered_search.vue @@ -14,14 +14,14 @@ export default { GroupByFilter, }, i18n: { - searchInputPlaceholder: s__('ObservabilityMetrics|Filter dimensions...'), + searchInputPlaceholder: s__('ObservabilityMetrics|Filter attributes...'), }, props: { - searchConfig: { + searchMetadata: { type: Object, required: true, }, - dimensionFilters: { + attributeFilters: { type: Array, required: false, default: () => [], @@ -42,16 +42,16 @@ export default { shouldShowDateRangePicker: false, dateRange: this.dateRangeFilter, groupBy: this.groupByFilter ?? { - dimensions: this.searchConfig.defaultGroupByDimensions ?? [], - func: this.searchConfig.defaultGroupByFunction ?? '', + attributes: this.searchMetadata.default_group_by_attributes ?? [], + func: this.searchMetadata.default_group_by_function ?? '', }, }; }, computed: { availableTokens() { - return this.searchConfig.dimensions.map((dimension) => ({ - title: dimension, - type: dimension, + return this.searchMetadata.attribute_keys.map((attribute) => ({ + title: attribute, + type: attribute, token: GlFilteredSearchToken, operators: [...OPERATORS_IS_NOT, ...OPERATORS_LIKE_NOT], })); @@ -60,7 +60,7 @@ export default { methods: { onFilter(filters) { this.$emit('filter', { - dimensions: filters, + attributes: filters, dateRange: this.dateRange, groupBy: this.groupBy, }); @@ -68,8 +68,8 @@ export default { onDateRangeSelected({ value, startDate, endDate }) { this.dateRange = { value, startDate, endDate }; }, - onGroupBy({ dimensions, func }) { - this.groupBy = { dimensions, func }; + onGroupBy({ attributes, func }) { + this.groupBy = { attributes, func }; }, }, }; @@ -85,7 +85,7 @@ export default { namespace="metrics-details-filtered-search" :search-input-placeholder="$options.i18n.searchInputPlaceholder" :tokens="availableTokens" - :initial-filter-value="dimensionFilters" + :initial-filter-value="attributeFilters" terms-as-tokens @onFilter="onFilter" /> @@ -97,8 +97,8 @@ export default { <hr class="gl-my-3" /> <group-by-filter - :search-config="searchConfig" - :selected-dimensions="groupBy.dimensions" + :search-metadata="searchMetadata" + :selected-attributes="groupBy.attributes" :selected-function="groupBy.func" @groupBy="onGroupBy" /> diff --git a/ee/app/assets/javascripts/metrics/details/metrics_details.vue b/ee/app/assets/javascripts/metrics/details/metrics_details.vue index 19506899c9e79..2925e8845fa13 100644 --- a/ee/app/assets/javascripts/metrics/details/metrics_details.vue +++ b/ee/app/assets/javascripts/metrics/details/metrics_details.vue @@ -53,10 +53,10 @@ export default { const defaultRange = periodToDate(DEFAULT_TIME_RANGE); return { metricData: [], - searchConfig: null, + searchMetadata: null, // TODO get filters from query params https://gitlab.com/gitlab-org/opstrace/opstrace/-/work_items/2605 filters: { - dimensions: [], + attributes: [], dateRange: { value: DEFAULT_TIME_RANGE, startDarte: defaultRange.min, @@ -64,7 +64,6 @@ export default { }, }, loading: false, - searchMetadata: null, }; }, computed: { @@ -76,9 +75,9 @@ export default { description: this.searchMetadata?.description, }; }, - dimensionFiltersValue() { - // only dimensions are used by the filtered_search component, so only those needs processing - return prepareTokens(this.filters.dimensions); + attributeFiltersValue() { + // only attributes are used by the filtered_search component, so only those needs processing + return prepareTokens(this.filters.attributes); }, }, created() { @@ -96,10 +95,7 @@ export default { try { const enabled = await this.observabilityClient.isObservabilityEnabled(); if (enabled) { - await this.fetchMetricSearchMetadata(); - if (this.searchMetadata) { - await this.fetchMetricData(); - } + await Promise.all([this.fetchMetricSearchMetadata(), await this.fetchMetricData()]); } else { this.goToMetricsIndex(); } @@ -131,13 +127,6 @@ export default { this.metricType, { filters: this.filters }, ); - // TODO fetch config from API https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2488 - this.searchConfig = { - dimensions: ['dimension_one', 'dimension_two'], - groupByFunctions: ['avg', 'sum', 'p50'], - defaultGroupByFunction: 'avg', - defaultGroupByDimensions: ['dimension_one', 'dimension_two'], - }; } catch (e) { createAlert({ message: this.$options.i18n.error, @@ -149,10 +138,10 @@ export default { goToMetricsIndex() { visitUrl(this.metricsIndexUrl); }, - onFilter({ dimensions, dateRange, groupBy }) { + onFilter({ attributes, dateRange, groupBy }) { this.filters = { - // only dimensions are used by the filtered_search component, so only those needs processing - dimensions: processFilteredSearchFilters(dimensions), + // only attributes are used by the filtered_search component, so only those needs processing + attributes: processFilteredSearchFilters(attributes), dateRange, groupBy, }; @@ -182,9 +171,9 @@ export default { <div class="gl-my-6"> <filtered-search - v-if="searchConfig" - :search-config="searchConfig" - :dimension-filters="dimensionFiltersValue" + v-if="searchMetadata" + :search-metadata="searchMetadata" + :attribute-filters="attributeFiltersValue" :date-range-filter="filters.dateRange" :group-by-filter="filters.groupBy" @filter="onFilter" diff --git a/ee/spec/frontend/metrics/details/filter_bar/groupby_filter_spec.js b/ee/spec/frontend/metrics/details/filter_bar/groupby_filter_spec.js index e3a19da9d45df..1f6d3d5a164a7 100644 --- a/ee/spec/frontend/metrics/details/filter_bar/groupby_filter_spec.js +++ b/ee/spec/frontend/metrics/details/filter_bar/groupby_filter_spec.js @@ -5,11 +5,18 @@ describe('GroupByFilter', () => { let wrapper; const props = { - searchConfig: { - groupByFunctions: ['sum', 'avg'], - dimensions: ['dimension_one', 'dimensions_two'], + searchMetadata: { + name: 'cpu_seconds_total', + type: 'sum', + description: 'some_description', + last_ingested_at: 1705374438711900000, + attribute_keys: ['attribute_one', 'attributes_two'], + supported_aggregations: ['1m', '1h'], + supported_functions: ['sum', 'avg'], + default_group_by_attributes: ['attribute_one', 'attributes_two'], + default_group_by_function: 'avg', }, - selectedDimensions: ['dimension_one'], + selectedAttributes: ['attribute_one'], selectedFunction: 'sum', }; @@ -35,13 +42,13 @@ describe('GroupByFilter', () => { ); }); - it('renders the group by dimensions dropdown', () => { - expect(wrapper.findByTestId('group-by-dimensions-dropdown').props('items')).toEqual([ - { value: 'dimension_one', text: 'dimension_one' }, - { value: 'dimensions_two', text: 'dimensions_two' }, + it('renders the group by attributes dropdown', () => { + expect(wrapper.findByTestId('group-by-attributes-dropdown').props('items')).toEqual([ + { value: 'attribute_one', text: 'attribute_one' }, + { value: 'attributes_two', text: 'attributes_two' }, ]); - expect(wrapper.findByTestId('group-by-dimensions-dropdown').props('selected')).toEqual( - props.selectedDimensions, + expect(wrapper.findByTestId('group-by-attributes-dropdown').props('selected')).toEqual( + props.selectedAttributes, ); }); @@ -51,22 +58,22 @@ describe('GroupByFilter', () => { expect(wrapper.emitted('groupBy')).toEqual([ [ { - dimensions: props.selectedDimensions, + attributes: props.selectedAttributes, func: 'avg', }, ], ]); }); - it('emits groupBy on dimension change', async () => { + it('emits groupBy on attribute change', async () => { await wrapper - .findByTestId('group-by-dimensions-dropdown') - .vm.$emit('select', ['dimension_two']); + .findByTestId('group-by-attributes-dropdown') + .vm.$emit('select', ['attribute_two']); expect(wrapper.emitted('groupBy')).toEqual([ [ { - dimensions: ['dimension_two'], + attributes: ['attribute_two'], func: props.selectedFunction, }, ], @@ -74,23 +81,23 @@ describe('GroupByFilter', () => { }); it('updates the group-by toggle text depending on value', async () => { - expect(wrapper.findByTestId('group-by-dimensions-dropdown').props('toggleText')).toBe( - 'dimension_one', + expect(wrapper.findByTestId('group-by-attributes-dropdown').props('toggleText')).toBe( + 'attribute_one', ); await wrapper - .findByTestId('group-by-dimensions-dropdown') - .vm.$emit('select', ['dimension_two']); + .findByTestId('group-by-attributes-dropdown') + .vm.$emit('select', ['attribute_two']); - expect(wrapper.findByTestId('group-by-dimensions-dropdown').props('toggleText')).toBe( - 'dimension_two', + expect(wrapper.findByTestId('group-by-attributes-dropdown').props('toggleText')).toBe( + 'attribute_two', ); await wrapper - .findByTestId('group-by-dimensions-dropdown') - .vm.$emit('select', ['dimension_two', 'dimensions_one']); + .findByTestId('group-by-attributes-dropdown') + .vm.$emit('select', ['attribute_two', 'attributes_one']); - expect(wrapper.findByTestId('group-by-dimensions-dropdown').props('toggleText')).toBe( + expect(wrapper.findByTestId('group-by-attributes-dropdown').props('toggleText')).toBe( 'multiple', ); }); @@ -99,15 +106,15 @@ describe('GroupByFilter', () => { expect(wrapper.findByTestId('group-by-label').text()).toBe(''); await wrapper - .findByTestId('group-by-dimensions-dropdown') - .vm.$emit('select', ['dimension_two']); + .findByTestId('group-by-attributes-dropdown') + .vm.$emit('select', ['attribute_two']); expect(wrapper.findByTestId('group-by-label').text()).toBe(''); await wrapper - .findByTestId('group-by-dimensions-dropdown') - .vm.$emit('select', ['dimension_two', 'dimensions_one']); + .findByTestId('group-by-attributes-dropdown') + .vm.$emit('select', ['attribute_two', 'attributes_one']); - expect(wrapper.findByTestId('group-by-label').text()).toBe('dimension_two, dimensions_one'); + expect(wrapper.findByTestId('group-by-label').text()).toBe('attribute_two, attributes_one'); }); }); diff --git a/ee/spec/frontend/metrics/details/filter_bar/metrics_filtered_search_spec.js b/ee/spec/frontend/metrics/details/filter_bar/metrics_filtered_search_spec.js index d6514e580c2ab..e5fb1a9127e9e 100644 --- a/ee/spec/frontend/metrics/details/filter_bar/metrics_filtered_search_spec.js +++ b/ee/spec/frontend/metrics/details/filter_bar/metrics_filtered_search_spec.js @@ -10,15 +10,22 @@ import { OPERATORS_LIKE_NOT } from '~/observability/constants'; describe('MetricsFilteredSearch', () => { let wrapper; - const defaultSearchConfig = { - dimensions: ['dimension_one', 'dimension_two'], - groupByFunctions: ['avg', 'sum', 'p50'], + const defaultSearchMetadata = { + name: 'cpu_seconds_total', + type: 'sum', + description: 'some_description', + last_ingested_at: 1705374438711900000, + attribute_keys: ['attribute_one', 'attribute_two'], + supported_aggregations: ['1m', '1h'], + supported_functions: ['avg', 'sum', 'p50'], + default_group_by_attributes: ['host.name'], + default_group_by_function: 'avg', }; - const mount = (props = {}, searchConfig = {}) => { + const mount = (props = {}, searchMetadata = {}) => { wrapper = shallowMountExtended(MetricsFilteredSearch, { propsData: { - searchConfig: { ...defaultSearchConfig, ...searchConfig }, + searchMetadata: { ...defaultSearchMetadata, ...searchMetadata }, ...props, }, }); @@ -32,14 +39,14 @@ describe('MetricsFilteredSearch', () => { const findDateRangeFilter = () => wrapper.findComponent(DateRangeFilter); const findGroupByFilter = () => wrapper.findComponent(GroupByFilter); - it('renders the filtered search component with tokens based on dimensions', () => { + it('renders the filtered search component with tokens based on attributes', () => { const filteredSeach = findFilteredSearch(); expect(filteredSeach.exists()).toBe(true); const tokens = filteredSeach.props('tokens'); - expect(tokens.length).toBe(defaultSearchConfig.dimensions.length); + expect(tokens.length).toBe(defaultSearchMetadata.attribute_keys.length); tokens.forEach((token, index) => { - expect(token.type).toBe(defaultSearchConfig.dimensions[index]); - expect(token.title).toBe(defaultSearchConfig.dimensions[index]); + expect(token.type).toBe(defaultSearchMetadata.attribute_keys[index]); + expect(token.title).toBe(defaultSearchMetadata.attribute_keys[index]); expect(token.token).toBe(GlFilteredSearchToken); expect(token.operators).toEqual([...OPERATORS_IS_NOT, ...OPERATORS_LIKE_NOT]); }); @@ -47,7 +54,7 @@ describe('MetricsFilteredSearch', () => { it('renders the filtered search component with with initial tokens', () => { const filters = [{ type: 'key.name', value: 'foo' }]; - mount({ dimensionFilters: filters }); + mount({ attributeFilters: filters }); expect(findFilteredSearch().props('initialFilterValue')).toEqual(filters); }); @@ -65,32 +72,36 @@ describe('MetricsFilteredSearch', () => { }); describe('group-by filter', () => { - it('renders the group-by filter with search config', () => { + it('renders the group-by filter with search metadata', () => { const groupBy = findGroupByFilter(); expect(groupBy.exists()).toBe(true); - expect(groupBy.props('searchConfig')).toEqual(defaultSearchConfig); - expect(groupBy.props('selectedFunction')).toBe(''); - expect(groupBy.props('selectedDimensions')).toEqual([]); + expect(groupBy.props('searchMetadata')).toEqual(defaultSearchMetadata); + expect(groupBy.props('selectedFunction')).toBe( + defaultSearchMetadata.default_group_by_function, + ); + expect(groupBy.props('selectedAttributes')).toEqual( + defaultSearchMetadata.default_group_by_attributes, + ); }); it('renders the group-by filter with defaults', () => { mount( {}, { - defaultGroupByFunction: 'avg', - defaultGroupByDimensions: ['dimension_one', 'dimension_two'], + default_group_by_function: 'avg', + default_group_by_attributes: ['attribute_one', 'attribute_two'], }, ); const groupBy = findGroupByFilter(); - expect(groupBy.props('searchConfig')).toEqual({ - ...defaultSearchConfig, - defaultGroupByFunction: 'avg', - defaultGroupByDimensions: ['dimension_one', 'dimension_two'], + expect(groupBy.props('searchMetadata')).toEqual({ + ...defaultSearchMetadata, + default_group_by_function: 'avg', + default_group_by_attributes: ['attribute_one', 'attribute_two'], }); expect(groupBy.props('selectedFunction')).toBe('avg'); - expect(groupBy.props('selectedDimensions')).toEqual(['dimension_one', 'dimension_two']); + expect(groupBy.props('selectedAttributes')).toEqual(['attribute_one', 'attribute_two']); }); it('renders the group-by filter with specified prop', () => { @@ -98,32 +109,32 @@ describe('MetricsFilteredSearch', () => { { groupByFilter: { func: 'sum', - dimensions: ['attr_1'], + attributes: ['attr_1'], }, }, { - defaultGroupByFunction: 'avg', - defaultGroupByDimensions: ['dimension_one', 'dimension_two'], + default_group_by_function: 'avg', + default_group_by_attributes: ['attribute_one', 'attribute_two'], }, ); const groupBy = findGroupByFilter(); expect(groupBy.props('selectedFunction')).toBe('sum'); - expect(groupBy.props('selectedDimensions')).toEqual(['attr_1']); + expect(groupBy.props('selectedAttributes')).toEqual(['attr_1']); }); }); - it('emits the filter event when the dimensions filter is changed', async () => { - const filters = [{ dimension: 'namespace', operator: 'is not', value: 'test' }]; + it('emits the filter event when the attributes filter is changed', async () => { + const filters = [{ attribute: 'namespace', operator: 'is not', value: 'test' }]; await findFilteredSearch().vm.$emit('onFilter', filters); expect(wrapper.emitted('filter')).toEqual([ [ { - dimensions: [{ dimension: 'namespace', operator: 'is not', value: 'test' }], + attributes: [{ attribute: 'namespace', operator: 'is not', value: 'test' }], groupBy: { - dimensions: [], - func: '', + attributes: defaultSearchMetadata.default_group_by_attributes, + func: defaultSearchMetadata.default_group_by_function, }, }, ], @@ -145,11 +156,11 @@ describe('MetricsFilteredSearch', () => { expect(wrapper.emitted('filter')).toEqual([ [ { - dimensions: [], + attributes: [], dateRange, groupBy: { - dimensions: [], - func: '', + attributes: defaultSearchMetadata.default_group_by_attributes, + func: defaultSearchMetadata.default_group_by_function, }, }, ], @@ -161,8 +172,8 @@ describe('MetricsFilteredSearch', () => { mount( {}, { - defaultGroupByFunction: 'avg', - defaultGroupByDimensions: ['dimension_one', 'dimension_two'], + default_group_by_function: 'avg', + default_group_by_attributes: ['attribute_one', 'attribute_two'], }, ); @@ -171,9 +182,9 @@ describe('MetricsFilteredSearch', () => { expect(wrapper.emitted('filter')).toEqual([ [ { - dimensions: [], + attributes: [], groupBy: { - dimensions: ['dimension_one', 'dimension_two'], + attributes: ['attribute_one', 'attribute_two'], func: 'avg', }, }, @@ -183,7 +194,7 @@ describe('MetricsFilteredSearch', () => { it('emits the filter event when the group-by is changed and the filtered-search onFilter is emitted', async () => { const groupBy = { - dimensions: ['dimension_one'], + attributes: ['attribute_one'], func: 'sum', }; @@ -195,12 +206,12 @@ describe('MetricsFilteredSearch', () => { expect(wrapper.emitted('filter')).toEqual([ [ { - dimensions: [], + attributes: [], groupBy, }, ], ]); expect(findGroupByFilter().props('selectedFunction')).toBe(groupBy.func); - expect(findGroupByFilter().props('selectedDimensions')).toEqual(groupBy.dimensions); + expect(findGroupByFilter().props('selectedAttributes')).toEqual(groupBy.attributes); }); }); diff --git a/ee/spec/frontend/metrics/details/metrics_details_spec.js b/ee/spec/frontend/metrics/details/metrics_details_spec.js index 84e7ec6288274..d686d4e7e7c96 100644 --- a/ee/spec/frontend/metrics/details/metrics_details_spec.js +++ b/ee/spec/frontend/metrics/details/metrics_details_spec.js @@ -133,16 +133,15 @@ describe('MetricsDetails', () => { describe('filtered search', () => { const findFilteredSearch = () => findMetricDetails().findComponent(FilteredSearch); it('renders the FilteredSearch component', () => { - expect(findFilteredSearch().exists()).toBe(true); - // TODO get searchConfig from API https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2488 - expect(Object.keys(findFilteredSearch().props('searchConfig'))).toEqual( - expect.arrayContaining([ - 'dimensions', - 'groupByFunctions', - 'defaultGroupByFunction', - 'defaultGroupByDimensions', - ]), - ); + const filteredSearch = findFilteredSearch(); + expect(filteredSearch.exists()).toBe(true); + expect(filteredSearch.props('searchMetadata')).toBe(mockSearchMetadata); + }); + + it('does not render the filtered search component if fetching metadata fails', async () => { + observabilityClientMock.fetchMetricSearchMetadata.mockRejectedValueOnce('error'); + await mountComponent(); + expect(findFilteredSearch().exists()).toBe(false); }); it('sets the default date range', () => { @@ -156,7 +155,7 @@ describe('MetricsDetails', () => { it('fetches metrics with filters', () => { expect(observabilityClientMock.fetchMetric).toHaveBeenCalledWith(METRIC_ID, METRIC_TYPE, { filters: { - dimensions: [], + attributes: [], dateRange: { endDate: new Date('2020-07-06T00:00:00.000Z'), startDarte: new Date('2020-07-05T23:00:00.000Z'), @@ -167,9 +166,9 @@ describe('MetricsDetails', () => { }); describe('on search submit', () => { - const setFilters = async (dimensions, dateRange, groupBy) => { + const setFilters = async (attributes, dateRange, groupBy) => { findFilteredSearch().vm.$emit('filter', { - dimensions: prepareTokens(dimensions), + attributes: prepareTokens(attributes), dateRange, groupBy, }); @@ -188,7 +187,7 @@ describe('MetricsDetails', () => { }, { func: 'avg', - dimensions: ['attr_1', 'attr_2'], + attributes: ['attr_1', 'attr_2'], }, ); }); @@ -199,7 +198,7 @@ describe('MetricsDetails', () => { METRIC_TYPE, { filters: { - dimensions: { + attributes: { 'key.one': [{ operator: '=', value: '12h' }], }, dateRange: { @@ -209,7 +208,7 @@ describe('MetricsDetails', () => { }, groupBy: { func: 'avg', - dimensions: ['attr_1', 'attr_2'], + attributes: ['attr_1', 'attr_2'], }, }, }, @@ -222,14 +221,14 @@ describe('MetricsDetails', () => { startDarte: new Date('2020-07-05T23:00:00.000Z'), value: '30d', }); - expect(findFilteredSearch().props('dimensionFilters')).toEqual( + expect(findFilteredSearch().props('attributeFilters')).toEqual( prepareTokens({ 'key.one': [{ operator: '=', value: '12h' }], }), ); expect(findFilteredSearch().props('groupByFilter')).toEqual({ func: 'avg', - dimensions: ['attr_1', 'attr_2'], + attributes: ['attr_1', 'attr_2'], }); }); }); @@ -318,12 +317,6 @@ describe('MetricsDetails', () => { }); }); - it('does not fetch metric data if fetching search metadata fails', async () => { - observabilityClientMock.fetchMetricSearchMetadata.mockRejectedValueOnce('error'); - await mountComponent(); - expect(observabilityClientMock.fetchMetric).not.toHaveBeenCalled(); - }); - it('renders an alert if metricId is missing', async () => { await mountComponent({ metricId: undefined }); diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 389a22113288e..f997e489e5c91 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -33588,7 +33588,7 @@ msgstr "" msgid "ObservabilityMetrics|Failed to load metrics." msgstr "" -msgid "ObservabilityMetrics|Filter dimensions..." +msgid "ObservabilityMetrics|Filter attributes..." msgstr "" msgid "ObservabilityMetrics|Last ingested" diff --git a/spec/frontend/observability/client_spec.js b/spec/frontend/observability/client_spec.js index 3d98e1a2166bc..367278a7b7e70 100644 --- a/spec/frontend/observability/client_spec.js +++ b/spec/frontend/observability/client_spec.js @@ -785,11 +785,11 @@ describe('buildClient', () => { axiosMock.onGet(metricsSearchUrl).reply(200, { results: [] }); }); - describe('dimension filter', () => { + describe('attribute filter', () => { it('converts filter to proper query params', async () => { await client.fetchMetric('name', 'type', { filters: { - dimensions: { + attributes: { attr_1: [ { operator: '=', value: 'foo' }, { operator: '!=', value: 'bar' }, @@ -811,7 +811,7 @@ describe('buildClient', () => { it('handles repeated params', async () => { await client.fetchMetric('name', 'type', { filters: { - dimensions: { + attributes: { attr_1: [ { operator: '=', value: 'v1' }, { operator: '=', value: 'v2' }, @@ -824,7 +824,7 @@ describe('buildClient', () => { it('ignores empty filters', async () => { await client.fetchMetric('name', 'type', { - filters: { dimensions: [] }, + filters: { attributes: [] }, }); expect(getQueryParam()).toBe('mname=name&mtype=type'); @@ -832,7 +832,7 @@ describe('buildClient', () => { it('ignores undefined dimension filters', async () => { await client.fetchMetric('name', 'type', { - filters: { dimensions: undefined }, + filters: { attributes: undefined }, }); expect(getQueryParam()).toBe('mname=name&mtype=type'); @@ -841,7 +841,7 @@ describe('buildClient', () => { it('ignores non-array filters', async () => { await client.fetchMetric('name', 'type', { filters: { - dimensions: { + attributes: { attr_1: { operator: '=', value: 'foo' }, }, }, @@ -853,7 +853,7 @@ describe('buildClient', () => { it('ignores unsupported operators', async () => { await client.fetchMetric('name', 'type', { filters: { - dimensions: { + attributes: { attr_1: [ { operator: '*', value: 'foo' }, { operator: '>', value: 'foo' }, @@ -929,16 +929,16 @@ describe('buildClient', () => { expect(getQueryParam()).toContain(`groupby_fn=sum`); }); - it('handle group by dimension', async () => { + it('handle group by attribute', async () => { await client.fetchMetric('name', 'type', { - filters: { groupBy: { dimensions: ['attr_1'] } }, + filters: { groupBy: { attributes: ['attr_1'] } }, }); expect(getQueryParam()).toContain(`groupby_attrs=attr_1`); }); - it('handle group by multiple dimensions', async () => { + it('handle group by multiple attributes', async () => { await client.fetchMetric('name', 'type', { - filters: { groupBy: { dimensions: ['attr_1', 'attr_2'] } }, + filters: { groupBy: { attributes: ['attr_1', 'attr_2'] } }, }); expect(getQueryParam()).toContain(`groupby_attrs=attr_1,attr_2`); }); @@ -951,7 +951,7 @@ describe('buildClient', () => { it('ignores empty list', async () => { await client.fetchMetric('name', 'type', { - filters: { groupBy: { dimensions: [] } }, + filters: { groupBy: { attributes: [] } }, }); expect(getQueryParam()).toBe('mname=name&mtype=type'); }); -- GitLab