diff --git a/frontend/public/locales/en-GB/titles.json b/frontend/public/locales/en-GB/titles.json index 95a58e615f98..1e16e3ecc56d 100644 --- a/frontend/public/locales/en-GB/titles.json +++ b/frontend/public/locales/en-GB/titles.json @@ -46,5 +46,8 @@ "ALERT_HISTORY": "SigNoz | Alert Rule History", "ALERT_OVERVIEW": "SigNoz | Alert Rule Overview", "INFRASTRUCTURE_MONITORING_HOSTS": "SigNoz | Infra Monitoring", - "INFRASTRUCTURE_MONITORING_KUBERNETES": "SigNoz | Infra Monitoring" + "INFRASTRUCTURE_MONITORING_KUBERNETES": "SigNoz | Infra Monitoring", + "METER_EXPLORER": "SigNoz | Meter Explorer", + "METER_EXPLORER_VIEWS": "SigNoz | Meter Explorer", + "METER_EXPLORER_BASE": "SigNoz | Meter Explorer" } diff --git a/frontend/public/locales/en/titles.json b/frontend/public/locales/en/titles.json index 9e4039a86b74..ec43f8c026d3 100644 --- a/frontend/public/locales/en/titles.json +++ b/frontend/public/locales/en/titles.json @@ -69,5 +69,8 @@ "METRICS_EXPLORER": "SigNoz | Metrics Explorer", "METRICS_EXPLORER_EXPLORER": "SigNoz | Metrics Explorer", "METRICS_EXPLORER_VIEWS": "SigNoz | Metrics Explorer", - "API_MONITORING": "SigNoz | External APIs" + "API_MONITORING": "SigNoz | External APIs", + "METER_EXPLORER": "SigNoz | Meter Explorer", + "METER_EXPLORER_VIEWS": "SigNoz | Meter Explorer", + "METER_EXPLORER_BASE": "SigNoz | Meter Explorer" } diff --git a/frontend/src/api/queryBuilder/getAggregateAttribute.ts b/frontend/src/api/queryBuilder/getAggregateAttribute.ts index f13c3da4a891..8080d9cc6f90 100644 --- a/frontend/src/api/queryBuilder/getAggregateAttribute.ts +++ b/frontend/src/api/queryBuilder/getAggregateAttribute.ts @@ -17,6 +17,7 @@ export const getAggregateAttribute = async ({ aggregateOperator, searchText, dataSource, + source, }: IGetAggregateAttributePayload): Promise< SuccessResponse | ErrorResponse > => { @@ -27,7 +28,7 @@ export const getAggregateAttribute = async ({ `/autocomplete/aggregate_attributes?${createQueryParams({ aggregateOperator, searchText, - dataSource, + dataSource: source === 'meter' ? 'meter' : dataSource, })}`, ); diff --git a/frontend/src/api/querySuggestions/getKeySuggestions.ts b/frontend/src/api/querySuggestions/getKeySuggestions.ts index 01f737fb4011..50626dee8b88 100644 --- a/frontend/src/api/querySuggestions/getKeySuggestions.ts +++ b/frontend/src/api/querySuggestions/getKeySuggestions.ts @@ -14,6 +14,7 @@ export const getKeySuggestions = ( metricName = '', fieldContext = '', fieldDataType = '', + signalSource = '', } = props; const encodedSignal = encodeURIComponent(signal); @@ -21,8 +22,9 @@ export const getKeySuggestions = ( const encodedMetricName = encodeURIComponent(metricName); const encodedFieldContext = encodeURIComponent(fieldContext); const encodedFieldDataType = encodeURIComponent(fieldDataType); + const encodedSource = encodeURIComponent(signalSource); return axios.get( - `/fields/keys?signal=${encodedSignal}&searchText=${encodedSearchText}&metricName=${encodedMetricName}&fieldContext=${encodedFieldContext}&fieldDataType=${encodedFieldDataType}`, + `/fields/keys?signal=${encodedSignal}&searchText=${encodedSearchText}&metricName=${encodedMetricName}&fieldContext=${encodedFieldContext}&fieldDataType=${encodedFieldDataType}&source=${encodedSource}`, ); }; diff --git a/frontend/src/api/querySuggestions/getValueSuggestion.ts b/frontend/src/api/querySuggestions/getValueSuggestion.ts index cbd2ea46245a..d8852c55f276 100644 --- a/frontend/src/api/querySuggestions/getValueSuggestion.ts +++ b/frontend/src/api/querySuggestions/getValueSuggestion.ts @@ -8,13 +8,14 @@ import { export const getValueSuggestions = ( props: QueryKeyValueRequestProps, ): Promise> => { - const { signal, key, searchText } = props; + const { signal, key, searchText, signalSource } = props; const encodedSignal = encodeURIComponent(signal); const encodedKey = encodeURIComponent(key); const encodedSearchText = encodeURIComponent(searchText); + const encodedSource = encodeURIComponent(signalSource || ''); return axios.get( - `/fields/values?signal=${encodedSignal}&name=${encodedKey}&searchText=${encodedSearchText}`, + `/fields/values?signal=${encodedSignal}&name=${encodedKey}&searchText=${encodedSearchText}&source=${encodedSource}`, ); }; diff --git a/frontend/src/api/v5/queryRange/prepareQueryRangePayloadV5.ts b/frontend/src/api/v5/queryRange/prepareQueryRangePayloadV5.ts index e67e3a539b78..e77786492e40 100644 --- a/frontend/src/api/v5/queryRange/prepareQueryRangePayloadV5.ts +++ b/frontend/src/api/v5/queryRange/prepareQueryRangePayloadV5.ts @@ -60,12 +60,9 @@ export function mapPanelTypeToRequestType(panelType: PANEL_TYPES): RequestType { /** * Gets signal type from data source */ -function getSignalType( - dataSource: string, -): 'traces' | 'logs' | 'metrics' | 'meter' { +function getSignalType(dataSource: string): 'traces' | 'logs' | 'metrics' { if (dataSource === 'traces') return 'traces'; if (dataSource === 'logs') return 'logs'; - if (dataSource === 'meter') return 'meter'; return 'metrics'; } @@ -186,17 +183,13 @@ export function createAggregation( } const haveReduceTo = - (queryData.dataSource === DataSource.METRICS || - queryData.dataSource === DataSource.METER) && + queryData.dataSource === DataSource.METRICS && panelType && (panelType === PANEL_TYPES.TABLE || panelType === PANEL_TYPES.PIE || panelType === PANEL_TYPES.VALUE); - if ( - queryData.dataSource === DataSource.METRICS || - queryData.dataSource === DataSource.METER - ) { + if (queryData.dataSource === DataSource.METRICS) { return [ { metricName: @@ -262,19 +255,12 @@ export function convertBuilderQueriesToV5( aggregations: aggregations as LogAggregation[], }; break; - case 'meter': - spec = { - name: queryName, - signal: 'meter' as const, - ...baseSpec, - aggregations: aggregations as MetricAggregation[], - }; - break; case 'metrics': default: spec = { name: queryName, signal: 'metrics' as const, + source: queryData.source || '', ...baseSpec, aggregations: aggregations as MetricAggregation[], // reduceTo: queryData.reduceTo, diff --git a/frontend/src/components/QueryBuilderV2/QueryBuilderV2.tsx b/frontend/src/components/QueryBuilderV2/QueryBuilderV2.tsx index 37708eb8d269..d0621dad7a02 100644 --- a/frontend/src/components/QueryBuilderV2/QueryBuilderV2.tsx +++ b/frontend/src/components/QueryBuilderV2/QueryBuilderV2.tsx @@ -131,6 +131,7 @@ export const QueryBuilderV2 = memo(function QueryBuilderV2({ queryVariant={config?.queryVariant || 'dropdown'} showOnlyWhereClause={showOnlyWhereClause} isListViewPanel={isListViewPanel} + signalSource={config?.signalSource || ''} /> ))} diff --git a/frontend/src/components/QueryBuilderV2/QueryV2/MetricsSelect/MetricsSelect.tsx b/frontend/src/components/QueryBuilderV2/QueryV2/MetricsSelect/MetricsSelect.tsx index ce3e748509ab..b04e1d303ffc 100644 --- a/frontend/src/components/QueryBuilderV2/QueryV2/MetricsSelect/MetricsSelect.tsx +++ b/frontend/src/components/QueryBuilderV2/QueryV2/MetricsSelect/MetricsSelect.tsx @@ -9,10 +9,12 @@ export const MetricsSelect = memo(function MetricsSelect({ query, index, version, + signalSource, }: { query: IBuilderQuery; index: number; version: string; + signalSource: 'meter' | ''; }): JSX.Element { const { handleChangeAggregatorAttribute } = useQueryOperations({ index, @@ -26,6 +28,7 @@ export const MetricsSelect = memo(function MetricsSelect({ onChange={handleChangeAggregatorAttribute} query={query} index={index} + signalSource={signalSource || ''} /> ); diff --git a/frontend/src/components/QueryBuilderV2/QueryV2/QueryAddOns/QueryAddOns.tsx b/frontend/src/components/QueryBuilderV2/QueryV2/QueryAddOns/QueryAddOns.tsx index 7ac91c6c27b7..211ed3da2810 100644 --- a/frontend/src/components/QueryBuilderV2/QueryV2/QueryAddOns/QueryAddOns.tsx +++ b/frontend/src/components/QueryBuilderV2/QueryV2/QueryAddOns/QueryAddOns.tsx @@ -185,10 +185,7 @@ function QueryAddOns({ filteredAddOns = Object.values(ADD_ONS); // Filter out group_by for metrics data source - if ( - query.dataSource === DataSource.METRICS || - query.dataSource === DataSource.METER - ) { + if (query.dataSource === DataSource.METRICS) { filteredAddOns = filteredAddOns.filter( (addOn) => addOn.key !== ADD_ONS_KEYS.GROUP_BY, ); @@ -305,8 +302,7 @@ function QueryAddOns({
void; queryData: IBuilderQuery; dataSource: DataSource; + signalSource?: string; onRun?: (query: string) => void; }): JSX.Element { const isDarkMode = useIsDarkMode(); @@ -214,6 +216,7 @@ function QuerySearch({ signal: dataSource, searchText: searchText || '', metricName: debouncedMetricName ?? undefined, + signalSource: signalSource as 'meter' | '', }); if (response.data.data) { @@ -374,6 +377,7 @@ function QuerySearch({ key, searchText: sanitizedSearchText, signal: dataSource, + signalSource: signalSource as 'meter' | '', }); // Skip updates if component unmounted or key changed @@ -461,8 +465,13 @@ function QuerySearch({ setIsFetchingCompleteValuesList(false); } }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [activeKey, dataSource, isFocused], + [ + activeKey, + dataSource, + isLoadingSuggestions, + signalSource, + toggleSuggestions, + ], ); const debouncedFetchValueSuggestions = useMemo( @@ -1436,6 +1445,7 @@ function QuerySearch({ QuerySearch.defaultProps = { onRun: undefined, + signalSource: '', }; export default QuerySearch; diff --git a/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx b/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx index 3c9938e4b6e4..b4830a4ff932 100644 --- a/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx +++ b/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx @@ -28,6 +28,7 @@ export const QueryV2 = memo(function QueryV2({ isListViewPanel = false, version, showOnlyWhereClause = false, + signalSource = '', }: QueryProps & { ref: React.RefObject }): JSX.Element { const { cloneQuery, panelType } = useQueryBuilder(); @@ -63,7 +64,7 @@ export const QueryV2 = memo(function QueryV2({ const showReduceTo = useMemo( () => - (dataSource === DataSource.METRICS || dataSource === DataSource.METER) && + dataSource === DataSource.METRICS && (panelType === PANEL_TYPES.TABLE || panelType === PANEL_TYPES.PIE || panelType === PANEL_TYPES.VALUE), @@ -112,14 +113,11 @@ export const QueryV2 = memo(function QueryV2({
- {(dataSource === DataSource.METRICS || - dataSource === DataSource.METER) && ( + {dataSource === DataSource.METRICS && (
)} @@ -190,6 +188,7 @@ export const QueryV2 = memo(function QueryV2({ onChange={handleSearchChange} queryData={query} dataSource={dataSource} + signalSource={signalSource} />
@@ -204,8 +203,7 @@ export const QueryV2 = memo(function QueryV2({ {!showOnlyWhereClause && !isListViewPanel && - dataSource !== DataSource.METRICS && - dataSource !== DataSource.METER && ( + dataSource !== DataSource.METRICS && ( )} - {!showOnlyWhereClause && - (dataSource === DataSource.METRICS || - dataSource === DataSource.METER) && ( - - )} + {!showOnlyWhereClause && dataSource === DataSource.METRICS && ( + + )} {!showOnlyWhereClause && ( { if (currentQuery.queryType === EQueryType.QUERY_BUILDER) { const newQueryData = currentQuery.builder.queryData.map((query) => { const aggregations = query.aggregations?.map((aggregation) => { - if ( - query.dataSource === DataSource.METRICS || - query.dataSource === DataSource.METER - ) { + if (query.dataSource === DataSource.METRICS) { const metricAggregation = aggregation as MetricAggregation; return { ...aggregation, @@ -628,8 +625,7 @@ export const adjustQueryForV5 = (currentQuery: Query): Query => { } = query; const newAggregations = - query.dataSource === DataSource.METRICS || - query.dataSource === DataSource.METER + query.dataSource === DataSource.METRICS ? (aggregations as MetricAggregation[]) : (aggregations as (TraceAggregation | LogAggregation)[]); diff --git a/frontend/src/components/QuickFilters/FilterRenderers/Checkbox/Checkbox.tsx b/frontend/src/components/QuickFilters/FilterRenderers/Checkbox/Checkbox.tsx index eec211ff8402..35c26b0eb5e5 100644 --- a/frontend/src/components/QuickFilters/FilterRenderers/Checkbox/Checkbox.tsx +++ b/frontend/src/components/QuickFilters/FilterRenderers/Checkbox/Checkbox.tsx @@ -17,6 +17,7 @@ import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig'; import { getOperatorValue } from 'container/QueryBuilder/filters/QueryBuilderSearch/utils'; import { useGetAggregateValues } from 'hooks/queryBuilder/useGetAggregateValues'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; +import { useGetQueryKeyValueSuggestions } from 'hooks/querySuggestions/useGetQueryKeyValueSuggestions'; import useDebouncedFn from 'hooks/useDebouncedFunction'; import { cloneDeep, isArray, isEqual, isFunction } from 'lodash-es'; import { ChevronDown, ChevronRight } from 'lucide-react'; @@ -73,18 +74,59 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element { searchText: searchText ?? '', }, { - enabled: isOpen, + enabled: isOpen && source !== QuickFiltersSource.METER_EXPLORER, keepPreviousData: true, }, ); + const { + data: keyValueSuggestions, + isLoading: isLoadingKeyValueSuggestions, + } = useGetQueryKeyValueSuggestions({ + key: filter.attributeKey.key, + signal: filter.dataSource || DataSource.LOGS, + signalSource: 'meter', + options: { + enabled: isOpen && source === QuickFiltersSource.METER_EXPLORER, + keepPreviousData: true, + }, + }); + const attributeValues: string[] = useMemo(() => { const dataType = filter.attributeKey.dataType || DataTypes.String; + + if (source === QuickFiltersSource.METER_EXPLORER && keyValueSuggestions) { + // Process the response data + const responseData = keyValueSuggestions?.data as any; + const values = responseData.data?.values || {}; + const stringValues = values.stringValues || []; + const numberValues = values.numberValues || []; + + // Generate options from string values - explicitly handle empty strings + const stringOptions = stringValues + // Strict filtering for empty string - we'll handle it as a special case if needed + .filter( + (value: string | null | undefined): value is string => + value !== null && value !== undefined && value !== '', + ); + + // Generate options from number values + const numberOptions = numberValues + .filter( + (value: number | null | undefined): value is number => + value !== null && value !== undefined, + ) + .map((value: number) => value.toString()); + + // Combine all options and make sure we don't have duplicate labels + return [...stringOptions, ...numberOptions]; + } + const key = DATA_TYPE_VS_ATTRIBUTE_VALUES_KEY[dataType]; return (data?.payload?.[key] || []).filter( (val) => val !== undefined && val !== null, ); - }, [data?.payload, filter.attributeKey.dataType]); + }, [data?.payload, filter.attributeKey.dataType, keyValueSuggestions, source]); const currentAttributeKeys = attributeValues.slice(0, visibleItemsCount); @@ -478,12 +520,14 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element { )} - {isOpen && isLoading && !attributeValues.length && ( -
- -
- )} - {isOpen && !isLoading && ( + {isOpen && + (isLoading || isLoadingKeyValueSuggestions) && + !attributeValues.length && ( +
+ +
+ )} + {isOpen && !isLoading && !isLoadingKeyValueSuggestions && ( <> {!isEmptyStateWithDocsEnabled && (
diff --git a/frontend/src/components/QuickFilters/QuickFiltersSettings/constants.ts b/frontend/src/components/QuickFilters/QuickFiltersSettings/constants.ts index 3f3d6bef04ce..4f357fd2e69c 100644 --- a/frontend/src/components/QuickFilters/QuickFiltersSettings/constants.ts +++ b/frontend/src/components/QuickFilters/QuickFiltersSettings/constants.ts @@ -6,5 +6,5 @@ export const SIGNAL_DATA_SOURCE_MAP = { [SignalType.TRACES]: DataSource.TRACES, [SignalType.EXCEPTIONS]: DataSource.TRACES, [SignalType.API_MONITORING]: DataSource.TRACES, - [SignalType.METER]: DataSource.METER, + [SignalType.METER_EXPLORER]: DataSource.METRICS, }; diff --git a/frontend/src/components/QuickFilters/types.ts b/frontend/src/components/QuickFilters/types.ts index 9c2a7f08ace5..b43f30a5ed21 100644 --- a/frontend/src/components/QuickFilters/types.ts +++ b/frontend/src/components/QuickFilters/types.ts @@ -23,7 +23,7 @@ export enum SignalType { LOGS = 'logs', API_MONITORING = 'api_monitoring', EXCEPTIONS = 'exceptions', - METER = 'meter', + METER_EXPLORER = 'meter_explorer', } export interface IQuickFiltersConfig { diff --git a/frontend/src/constants/queryBuilder.ts b/frontend/src/constants/queryBuilder.ts index df6dcc48b2fc..0a94b4f074ca 100644 --- a/frontend/src/constants/queryBuilder.ts +++ b/frontend/src/constants/queryBuilder.ts @@ -114,10 +114,6 @@ export const mapOfQueryFilters: Record = { { text: 'Having', field: 'having' }, { text: 'Aggregation interval', field: 'stepInterval' }, ], - meter: [ - { text: 'Aggregation interval', field: 'stepInterval' }, - { text: 'Having', field: 'having' }, - ], }; const commonFormulaFilters: QueryAdditionalFilter[] = [ @@ -136,7 +132,6 @@ export const mapOfFormulaToFilters: Record< metrics: commonFormulaFilters, logs: commonFormulaFilters, traces: commonFormulaFilters, - meter: commonFormulaFilters, }; export const REDUCE_TO_VALUES: SelectOption[] = [ @@ -201,6 +196,7 @@ export const initialQueryBuilderFormValues: IBuilderQuery = { groupBy: [], legend: '', reduceTo: 'avg', + source: '', }; const initialQueryBuilderFormLogsValues: IBuilderQuery = { @@ -218,7 +214,7 @@ const initialQueryBuilderFormTracesValues: IBuilderQuery = { }; export const initialQueryBuilderFormMeterValues: IBuilderQuery = { - dataSource: DataSource.METER, + dataSource: DataSource.METRICS, queryName: createNewBuilderItemName({ existNames: [], sourceNames: alphabet }), aggregateOperator: MeterAggregateOperator.COUNT, aggregateAttribute: initialAutocompleteData, @@ -257,7 +253,6 @@ export const initialQueryBuilderFormValuesMap: Record< metrics: initialQueryBuilderFormValues, logs: initialQueryBuilderFormLogsValues, traces: initialQueryBuilderFormTracesValues, - meter: initialQueryBuilderFormMeterValues, }; export const initialFormulaBuilderFormValues: IBuilderFormula = { @@ -321,19 +316,23 @@ const initialQueryTracesWithType: Query = { }, }; -const initialQueryMeterWithType: Query = { - ...initialQueryWithType, - builder: { - ...initialQueryWithType.builder, - queryData: [initialQueryBuilderFormValuesMap.meter], - }, -}; - export const initialQueriesMap: Record = { metrics: initialQueryWithType, logs: initialQueryLogsWithType, traces: initialQueryTracesWithType, - meter: initialQueryMeterWithType, +}; + +export const initialQueryMeterWithType: Query = { + ...initialQueryWithType, + builder: { + ...initialQueryWithType.builder, + queryData: [ + { + ...initialQueryBuilderFormValuesMap.metrics, + source: 'meter', + }, + ], + }, }; export const operatorsByTypes: Record = { diff --git a/frontend/src/container/CreateAlertRule/config.ts b/frontend/src/container/CreateAlertRule/config.ts index c4887f6975e1..fe52bb12bf25 100644 --- a/frontend/src/container/CreateAlertRule/config.ts +++ b/frontend/src/container/CreateAlertRule/config.ts @@ -5,5 +5,4 @@ export const ALERT_TYPE_VS_SOURCE_MAPPING = { [DataSource.LOGS]: AlertTypes.LOGS_BASED_ALERT, [DataSource.METRICS]: AlertTypes.METRICS_BASED_ALERT, [DataSource.TRACES]: AlertTypes.TRACES_BASED_ALERT, - [DataSource.METER]: AlertTypes.METRICS_BASED_ALERT, }; diff --git a/frontend/src/container/ExplorerOptions/utils.ts b/frontend/src/container/ExplorerOptions/utils.ts index 2866191b14fe..d3a2d768d54e 100644 --- a/frontend/src/container/ExplorerOptions/utils.ts +++ b/frontend/src/container/ExplorerOptions/utils.ts @@ -18,7 +18,6 @@ export const DATASOURCE_VS_ROUTES: Record = { [DataSource.METRICS]: ROUTES.METRICS_EXPLORER, [DataSource.TRACES]: ROUTES.TRACES_EXPLORER, [DataSource.LOGS]: ROUTES.LOGS_EXPLORER, - [DataSource.METER]: ROUTES.METER_EXPLORER, }; export const saveNewViewHandler = ({ diff --git a/frontend/src/container/MeterExplorer/Explorer/Explorer.styles.scss b/frontend/src/container/MeterExplorer/Explorer/Explorer.styles.scss index fc6f1faecee4..74cf54423841 100644 --- a/frontend/src/container/MeterExplorer/Explorer/Explorer.styles.scss +++ b/frontend/src/container/MeterExplorer/Explorer/Explorer.styles.scss @@ -17,7 +17,7 @@ .explore-header { display: flex; align-items: center; - justify-content: flex-end; + justify-content: space-between; margin: 4px 0; padding: 0 8px; diff --git a/frontend/src/container/MeterExplorer/Explorer/Explorer.tsx b/frontend/src/container/MeterExplorer/Explorer/Explorer.tsx index ae40b85378ad..5d1e619a0f54 100644 --- a/frontend/src/container/MeterExplorer/Explorer/Explorer.tsx +++ b/frontend/src/container/MeterExplorer/Explorer/Explorer.tsx @@ -1,13 +1,13 @@ import './Explorer.styles.scss'; import * as Sentry from '@sentry/react'; -// import { Button, Tooltip } from 'antd'; +import { Button, Tooltip } from 'antd'; import logEvent from 'api/common/logEvent'; import cx from 'classnames'; import { QueryBuilderV2 } from 'components/QueryBuilderV2/QueryBuilderV2'; -// import QuickFilters from 'components/QuickFilters/QuickFilters'; -// import { QuickFiltersSource, SignalType } from 'components/QuickFilters/types'; -import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder'; +import QuickFilters from 'components/QuickFilters/QuickFilters'; +import { QuickFiltersSource, SignalType } from 'components/QuickFilters/types'; +import { initialQueryMeterWithType, PANEL_TYPES } from 'constants/queryBuilder'; import ExplorerOptionWrapper from 'container/ExplorerOptions/ExplorerOptionWrapper'; import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions'; import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interfaces'; @@ -15,9 +15,9 @@ import DateTimeSelector from 'container/TopNav/DateTimeSelectionV2'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl'; import { useSafeNavigate } from 'hooks/useSafeNavigate'; -// import { Filter } from 'lucide-react'; +import { Filter } from 'lucide-react'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; -import { useCallback, useEffect, useMemo } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { Dashboard } from 'types/api/dashboard/getAll'; import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { DataSource } from 'types/common/queryBuilder'; @@ -25,7 +25,6 @@ import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToD import { v4 as uuid } from 'uuid'; import { MeterExplorerEventKeys, MeterExplorerEvents } from '../events'; -// import QuerySection from './QuerySection'; import TimeSeries from './TimeSeries'; import { splitQueryIntoOneChartPerQuery } from './utils'; @@ -38,14 +37,15 @@ function Explorer(): JSX.Element { } = useQueryBuilder(); const { safeNavigate } = useSafeNavigate(); - // const [showQuickFilters, setShowQuickFilters] = useState(false); + const [showQuickFilters, setShowQuickFilters] = useState(true); const defaultQuery = useMemo( () => updateAllQueriesOperators( - initialQueriesMap[DataSource.METER], + initialQueryMeterWithType, PANEL_TYPES.TIME_SERIES, - DataSource.METER, + DataSource.METRICS, + 'meter' as 'meter' | '', ), [updateAllQueriesOperators], ); @@ -53,9 +53,10 @@ function Explorer(): JSX.Element { const exportDefaultQuery = useMemo( () => updateAllQueriesOperators( - currentQuery || initialQueriesMap[DataSource.METER], + currentQuery || initialQueryMeterWithType, PANEL_TYPES.TIME_SERIES, - DataSource.METER, + DataSource.METRICS, + 'meter' as 'meter' | '', ), [currentQuery, updateAllQueriesOperators], ); @@ -86,9 +87,7 @@ function Explorer(): JSX.Element { const splitedQueries = useMemo( () => - splitQueryIntoOneChartPerQuery( - stagedQuery || initialQueriesMap[DataSource.METER], - ), + splitQueryIntoOneChartPerQuery(stagedQuery || initialQueryMeterWithType), [stagedQuery], ); @@ -107,10 +106,10 @@ function Explorer(): JSX.Element { }>
- {/*
{ setShowQuickFilters(!showQuickFilters); }} /> -
*/} +
- {/*
+
{!showQuickFilters && (
*/} +
@@ -151,8 +150,9 @@ function Explorer(): JSX.Element {
[stagedQuery || initialQueriesMap[DataSource.METER]], + () => [stagedQuery || initialQueryMeterWithType], [stagedQuery], ); @@ -70,7 +70,7 @@ function TimeSeries(): JSX.Element { selectedTime: 'GLOBAL_TIME', globalSelectedInterval: globalSelectedTime, params: { - dataSource: DataSource.METER, + dataSource: DataSource.METRICS, }, }, ENTITY_VERSION_V5, @@ -120,7 +120,7 @@ function TimeSeries(): JSX.Element { isError={queries[index].isError} isLoading={queries[index].isLoading} data={datapoint} - dataSource={DataSource.METER} + dataSource={DataSource.METRICS} />
))} diff --git a/frontend/src/container/MetricsExplorer/Explorer/Explorer.tsx b/frontend/src/container/MetricsExplorer/Explorer/Explorer.tsx index a2dbf0183627..51e0c61e85f5 100644 --- a/frontend/src/container/MetricsExplorer/Explorer/Explorer.tsx +++ b/frontend/src/container/MetricsExplorer/Explorer/Explorer.tsx @@ -188,7 +188,7 @@ function Explorer(): JSX.Element { query={exportDefaultQuery} sourcepage={DataSource.METRICS} onExport={handleExport} - isOneChartPerQuery={showOneChartPerQuery} + isOneChartPerQuery={false} splitedQueries={splitedQueries} /> diff --git a/frontend/src/container/NewWidget/utils.ts b/frontend/src/container/NewWidget/utils.ts index 00cfb0d1bca2..8903150ed593 100644 --- a/frontend/src/container/NewWidget/utils.ts +++ b/frontend/src/container/NewWidget/utils.ts @@ -97,29 +97,6 @@ export const panelTypeDataSourceFormValuesMap: Record< ], }, }, - [DataSource.METER]: { - builder: { - queryData: [ - 'aggregateAttribute', - 'aggregateOperator', - 'timeAggregation', - 'filters', - 'filter', - 'spaceAggregation', - 'groupBy', - 'limit', - 'having', - 'orderBy', - 'stepInterval', - 'legend', - 'queryName', - 'disabled', - 'functions', - 'expression', - 'aggregations', - ], - }, - }, [DataSource.TRACES]: { builder: { queryData: [ @@ -187,29 +164,6 @@ export const panelTypeDataSourceFormValuesMap: Record< ], }, }, - [DataSource.METER]: { - builder: { - queryData: [ - 'aggregateAttribute', - 'aggregateOperator', - 'timeAggregation', - 'filters', - 'filter', - 'spaceAggregation', - 'groupBy', - 'limit', - 'having', - 'orderBy', - 'stepInterval', - 'legend', - 'queryName', - 'disabled', - 'functions', - 'expression', - 'aggregations', - ], - }, - }, [DataSource.TRACES]: { builder: { queryData: [ @@ -277,29 +231,6 @@ export const panelTypeDataSourceFormValuesMap: Record< ], }, }, - [DataSource.METER]: { - builder: { - queryData: [ - 'aggregateAttribute', - 'aggregateOperator', - 'timeAggregation', - 'filters', - 'filter', - 'spaceAggregation', - 'groupBy', - 'limit', - 'having', - 'orderBy', - 'stepInterval', - 'legend', - 'queryName', - 'disabled', - 'functions', - 'expression', - 'aggregations', - ], - }, - }, [DataSource.TRACES]: { builder: { queryData: [ @@ -368,30 +299,6 @@ export const panelTypeDataSourceFormValuesMap: Record< ], }, }, - [DataSource.METER]: { - builder: { - queryData: [ - 'aggregateAttribute', - 'aggregateOperator', - 'timeAggregation', - 'filters', - 'filter', - 'spaceAggregation', - 'groupBy', - 'reduceTo', - 'limit', - 'having', - 'orderBy', - 'stepInterval', - 'legend', - 'queryName', - 'expression', - 'disabled', - 'functions', - 'aggregations', - ], - }, - }, [DataSource.TRACES]: { builder: { queryData: [ @@ -460,30 +367,6 @@ export const panelTypeDataSourceFormValuesMap: Record< ], }, }, - [DataSource.METER]: { - builder: { - queryData: [ - 'aggregateAttribute', - 'aggregateOperator', - 'timeAggregation', - 'filters', - 'filter', - 'spaceAggregation', - 'groupBy', - 'reduceTo', - 'limit', - 'having', - 'orderBy', - 'stepInterval', - 'legend', - 'queryName', - 'expression', - 'disabled', - 'functions', - 'aggregations', - ], - }, - }, [DataSource.TRACES]: { builder: { queryData: [ @@ -524,11 +407,6 @@ export const panelTypeDataSourceFormValuesMap: Record< queryData: ['filters', 'filter', 'aggregations'], }, }, - [DataSource.METER]: { - builder: { - queryData: ['filters', 'filter', 'aggregations'], - }, - }, [DataSource.TRACES]: { builder: { queryData: [ @@ -583,27 +461,6 @@ export const panelTypeDataSourceFormValuesMap: Record< ], }, }, - [DataSource.METER]: { - builder: { - queryData: [ - 'aggregateAttribute', - 'aggregateOperator', - 'timeAggregation', - 'filters', - 'filter', - 'spaceAggregation', - 'having', - 'reduceTo', - 'stepInterval', - 'legend', - 'queryName', - 'expression', - 'disabled', - 'functions', - 'aggregations', - ], - }, - }, [DataSource.TRACES]: { builder: { queryData: [ diff --git a/frontend/src/container/QueryBuilder/QueryBuilder.interfaces.ts b/frontend/src/container/QueryBuilder/QueryBuilder.interfaces.ts index 7b891e91f92d..a80639e5ef02 100644 --- a/frontend/src/container/QueryBuilder/QueryBuilder.interfaces.ts +++ b/frontend/src/container/QueryBuilder/QueryBuilder.interfaces.ts @@ -17,8 +17,9 @@ export type QueryBuilderConfig = | { queryVariant: 'static'; initialDataSource: DataSource; + signalSource?: string; } - | { queryVariant: 'dropdown' }; + | { queryVariant: 'dropdown'; signalSource?: string }; export type QueryBuilderProps = { config?: QueryBuilderConfig; diff --git a/frontend/src/container/QueryBuilder/components/Query/Query.interfaces.ts b/frontend/src/container/QueryBuilder/components/Query/Query.interfaces.ts index 7f2f6ccde7a5..b5dd84a5732c 100644 --- a/frontend/src/container/QueryBuilder/components/Query/Query.interfaces.ts +++ b/frontend/src/container/QueryBuilder/components/Query/Query.interfaces.ts @@ -11,4 +11,5 @@ export type QueryProps = { version: string; showSpanScopeSelector?: boolean; showOnlyWhereClause?: boolean; + signalSource?: string; } & Pick; diff --git a/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.intefaces.ts b/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.intefaces.ts index 47035662309b..49ce65cd4d15 100644 --- a/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.intefaces.ts +++ b/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.intefaces.ts @@ -8,4 +8,5 @@ export type AgregatorFilterProps = Pick & { defaultValue?: string; onSelect?: (value: BaseAutocompleteData) => void; index?: number; + signalSource?: 'meter' | ''; }; diff --git a/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx b/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx index e0ebc87be369..a70ff65e64d4 100644 --- a/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx +++ b/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx @@ -38,6 +38,7 @@ export const AggregatorFilter = memo(function AggregatorFilter({ defaultValue, onSelect, index, + signalSource, }: AgregatorFilterProps): JSX.Element { const queryClient = useQueryClient(); const [optionsData, setOptionsData] = useState([]); @@ -73,11 +74,11 @@ export const AggregatorFilter = memo(function AggregatorFilter({ searchText: debouncedValue, aggregateOperator: queryAggregation.timeAggregation, dataSource: query.dataSource, + source: signalSource || '', }), { enabled: query.dataSource === DataSource.METRICS || - query.dataSource === DataSource.METER || (!!queryAggregation.timeAggregation && !!query.dataSource), onSuccess: (data) => { const options: ExtendedSelectOption[] = @@ -153,10 +154,17 @@ export const AggregatorFilter = memo(function AggregatorFilter({ setSearchText(text); }, []); - const placeholder: string = - query.dataSource === DataSource.METRICS - ? `Search metric name` - : 'Aggregate attribute'; + const getPlaceholder = useCallback(() => { + if (signalSource === 'meter') { + return 'Meter name'; + } + + if (query.dataSource === DataSource.METRICS) { + return 'Metric name'; + } + + return 'Aggregate attribute'; + }, [signalSource, query.dataSource]); const getAttributesData = useCallback( (): BaseAutocompleteData[] => @@ -285,7 +293,7 @@ export const AggregatorFilter = memo(function AggregatorFilter({ return ( {isError && error && } +
} {isLoading && dataSource === DataSource.TRACES && } {isLoading && dataSource === DataSource.METRICS && } - {isLoading && dataSource === DataSource.METER && } {chartData && chartData[0] && @@ -237,8 +231,7 @@ function TimeSeriesView({ !isLoading && !isError && !isFilterApplied && - dataSource !== DataSource.METRICS && - dataSource !== DataSource.METER && } + dataSource !== DataSource.METRICS && } {chartData && chartData[0] && @@ -247,13 +240,6 @@ function TimeSeriesView({ !isError && dataSource === DataSource.METRICS && } - {chartData && - chartData[0] && - chartData[0]?.length === 0 && - !isLoading && - !isError && - dataSource === DataSource.METER && } - {!isLoading && !isError && chartData && diff --git a/frontend/src/hooks/querySuggestions/useGetQueryKeyValueSuggestions.ts b/frontend/src/hooks/querySuggestions/useGetQueryKeyValueSuggestions.ts index 587cb6d90963..b7d7a8ca1ae3 100644 --- a/frontend/src/hooks/querySuggestions/useGetQueryKeyValueSuggestions.ts +++ b/frontend/src/hooks/querySuggestions/useGetQueryKeyValueSuggestions.ts @@ -1,22 +1,34 @@ import { getValueSuggestions } from 'api/querySuggestions/getValueSuggestion'; import { AxiosError, AxiosResponse } from 'axios'; -import { useQuery, UseQueryResult } from 'react-query'; +import { useQuery, UseQueryOptions, UseQueryResult } from 'react-query'; +import { ErrorResponse } from 'react-router-dom-v5-compat'; +import { SuccessResponse } from 'types/api'; import { QueryKeyValueSuggestionsResponseProps } from 'types/api/querySuggestions/types'; export const useGetQueryKeyValueSuggestions = ({ key, signal, searchText, + signalSource, }: { key: string; signal: 'traces' | 'logs' | 'metrics'; searchText?: string; + signalSource?: 'meter' | ''; + options?: UseQueryOptions< + SuccessResponse | ErrorResponse + >; }): UseQueryResult< AxiosResponse, AxiosError > => useQuery, AxiosError>({ - queryKey: ['queryKeyValueSuggestions', key, signal, searchText], + queryKey: ['queryKeyValueSuggestions', key, signal, searchText, signalSource], queryFn: () => - getValueSuggestions({ signal, key, searchText: searchText || '' }), + getValueSuggestions({ + signal, + key, + searchText: searchText || '', + signalSource: signalSource as 'meter' | '', + }), }); diff --git a/frontend/src/pages/MeterExplorer/MeterExplorerPage.tsx b/frontend/src/pages/MeterExplorer/MeterExplorerPage.tsx index d8b2d2d47f70..fd0433418b6a 100644 --- a/frontend/src/pages/MeterExplorer/MeterExplorerPage.tsx +++ b/frontend/src/pages/MeterExplorer/MeterExplorerPage.tsx @@ -2,13 +2,8 @@ import './MeterExplorer.styles.scss'; import RouteTab from 'components/RouteTab'; import { TabRoutes } from 'components/RouteTab/types'; -import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder'; -import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; -import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl'; import history from 'lib/history'; -import { useMemo } from 'react'; import { useLocation } from 'react-use'; -import { DataSource } from 'types/common/queryBuilder'; import { Explorer, Views } from './constants'; @@ -17,20 +12,6 @@ function MeterExplorerPage(): JSX.Element { const routes: TabRoutes[] = [Explorer, Views]; - const { updateAllQueriesOperators } = useQueryBuilder(); - - const defaultQuery = useMemo( - () => - updateAllQueriesOperators( - initialQueriesMap[DataSource.METER], - PANEL_TYPES.LIST, - DataSource.METER, - ), - [updateAllQueriesOperators], - ); - - useShareBuilderUrl({ defaultValue: defaultQuery }); - return (
diff --git a/frontend/src/pages/SaveView/index.tsx b/frontend/src/pages/SaveView/index.tsx index 84e1b38b4306..f9c2f6fb1a0e 100644 --- a/frontend/src/pages/SaveView/index.tsx +++ b/frontend/src/pages/SaveView/index.tsx @@ -167,7 +167,7 @@ function SaveView(): JSX.Element { logEvent(MetricsExplorerEvents.TabChanged, { [MetricsExplorerEventKeys.Tab]: 'views', }); - } else if (sourcepage === DataSource.METER) { + } else if (sourcepage === 'meter') { logEvent(MeterExplorerEvents.TabChanged, { [MeterExplorerEventKeys.Tab]: 'views', }); diff --git a/frontend/src/providers/QueryBuilder.tsx b/frontend/src/providers/QueryBuilder.tsx index a25f40b4e66b..9bde92a49a90 100644 --- a/frontend/src/providers/QueryBuilder.tsx +++ b/frontend/src/providers/QueryBuilder.tsx @@ -241,12 +241,26 @@ export function QueryBuilderProvider({ ); const updateAllQueriesOperators = useCallback( - (query: Query, panelType: PANEL_TYPES, dataSource: DataSource): Query => { + ( + query: Query, + panelType: PANEL_TYPES, + dataSource: DataSource, + signalSource?: 'meter' | '', + ): Query => { const queryData = query.builder.queryData?.map((item) => getElementWithActualOperator(item, dataSource, panelType), ); - return { ...query, builder: { ...query.builder, queryData } }; + return { + ...query, + builder: { + ...query.builder, + queryData: queryData.map((item) => ({ + ...item, + source: signalSource, + })), + }, + }; }, [getElementWithActualOperator], diff --git a/frontend/src/providers/preferences/updater/usePreferenceUpdater.ts b/frontend/src/providers/preferences/updater/usePreferenceUpdater.ts index e42f903b6646..2489b7e571ce 100644 --- a/frontend/src/providers/preferences/updater/usePreferenceUpdater.ts +++ b/frontend/src/providers/preferences/updater/usePreferenceUpdater.ts @@ -38,7 +38,6 @@ const getUpdaterConfig = ( setSavedViewPreferences, ), [DataSource.METRICS]: metricsUpdater, - [DataSource.METER]: metricsUpdater, }); export function usePreferenceUpdater({ diff --git a/frontend/src/types/api/queryBuilder/getAggregatorAttribute.ts b/frontend/src/types/api/queryBuilder/getAggregatorAttribute.ts index d308e013a3f5..5fea93b62bca 100644 --- a/frontend/src/types/api/queryBuilder/getAggregatorAttribute.ts +++ b/frontend/src/types/api/queryBuilder/getAggregatorAttribute.ts @@ -4,4 +4,5 @@ export interface IGetAggregateAttributePayload { aggregateOperator: string; dataSource: DataSource; searchText: string; + source?: 'meter' | ''; } diff --git a/frontend/src/types/api/queryBuilder/queryBuilderData.ts b/frontend/src/types/api/queryBuilder/queryBuilderData.ts index 66c834e3ee88..82a5aa820743 100644 --- a/frontend/src/types/api/queryBuilder/queryBuilderData.ts +++ b/frontend/src/types/api/queryBuilder/queryBuilderData.ts @@ -87,6 +87,7 @@ export type IBuilderQuery = { pageSize?: number; offset?: number; selectColumns?: BaseAutocompleteData[] | TelemetryFieldKey[]; + source?: 'meter' | ''; }; export interface IClickHouseQuery { diff --git a/frontend/src/types/api/querySuggestions/types.ts b/frontend/src/types/api/querySuggestions/types.ts index e239a65c7a7d..688ec20128f2 100644 --- a/frontend/src/types/api/querySuggestions/types.ts +++ b/frontend/src/types/api/querySuggestions/types.ts @@ -9,7 +9,7 @@ export interface QueryKeyDataSuggestionsProps { fieldContext?: 'resource' | 'scope' | 'attribute' | 'span'; fieldDataType?: QUERY_BUILDER_KEY_TYPES; name: string; - signal: 'traces' | 'logs' | 'metrics' | 'meter'; + signal: 'traces' | 'logs' | 'metrics'; } export interface QueryKeySuggestionsResponseProps { @@ -23,11 +23,12 @@ export interface QueryKeySuggestionsResponseProps { } export interface QueryKeyRequestProps { - signal: 'traces' | 'logs' | 'metrics' | 'meter'; + signal: 'traces' | 'logs' | 'metrics'; searchText: string; fieldContext?: 'resource' | 'scope' | 'attribute' | 'span'; fieldDataType?: QUERY_BUILDER_KEY_TYPES; metricName?: string; + signalSource?: 'meter' | ''; } export interface QueryKeyValueSuggestionsProps { @@ -41,9 +42,10 @@ export interface QueryKeyValueSuggestionsResponseProps { } export interface QueryKeyValueRequestProps { - signal: 'traces' | 'logs' | 'metrics' | 'meter'; + signal: 'traces' | 'logs' | 'metrics'; key: string; searchText: string; + signalSource?: 'meter' | ''; } -export type SignalType = 'traces' | 'logs' | 'metrics' | 'meter'; +export type SignalType = 'traces' | 'logs' | 'metrics'; diff --git a/frontend/src/types/api/v5/queryRange.ts b/frontend/src/types/api/v5/queryRange.ts index 89866d3cbcd1..1032c1bb51bb 100644 --- a/frontend/src/types/api/v5/queryRange.ts +++ b/frontend/src/types/api/v5/queryRange.ts @@ -24,7 +24,7 @@ export type OrderDirection = 'asc' | 'desc'; export type JoinType = 'inner' | 'left' | 'right' | 'full' | 'cross'; -export type SignalType = 'traces' | 'logs' | 'metrics' | 'meter'; +export type SignalType = 'traces' | 'logs' | 'metrics'; export type DataType = 'string' | 'number' | 'boolean' | 'array'; @@ -240,7 +240,8 @@ export interface MetricBuilderQuery extends BaseBuilderQuery { } export interface MeterBuilderQuery extends BaseBuilderQuery { - signal: 'meter'; + signal: 'metrics'; + source: 'meter'; aggregations?: MetricAggregation[]; } diff --git a/frontend/src/types/common/queryBuilder.ts b/frontend/src/types/common/queryBuilder.ts index 08f4c9e72cd8..3a5c73502fec 100644 --- a/frontend/src/types/common/queryBuilder.ts +++ b/frontend/src/types/common/queryBuilder.ts @@ -19,7 +19,6 @@ export enum DataSource { METRICS = 'metrics', TRACES = 'traces', LOGS = 'logs', - METER = 'meter', } export enum StringOperators { @@ -274,6 +273,7 @@ export type QueryBuilderContextType = { queryData: Query, panelType: PANEL_TYPES, dataSource: DataSource, + signalSource?: 'meter' | '', ) => Query; updateQueriesData: ( query: Query, diff --git a/frontend/src/utils/aggregationConverter.ts b/frontend/src/utils/aggregationConverter.ts index ae98a408d0d7..a07c09828cf9 100644 --- a/frontend/src/utils/aggregationConverter.ts +++ b/frontend/src/utils/aggregationConverter.ts @@ -29,7 +29,6 @@ export function convertAggregationsToBaseAutocompleteData( if (!aggregations || aggregations.length === 0) { switch (dataSource) { case DataSource.METRICS: - case DataSource.METER: return [ { id: uuid(), diff --git a/frontend/src/utils/convertNewToOldQueryBuilder.ts b/frontend/src/utils/convertNewToOldQueryBuilder.ts index 9f35c2ebcdb2..e181b8e04037 100644 --- a/frontend/src/utils/convertNewToOldQueryBuilder.ts +++ b/frontend/src/utils/convertNewToOldQueryBuilder.ts @@ -15,8 +15,6 @@ const getDataSourceFromSignal = (signal: string): DataSource => { return DataSource.LOGS; case 'traces': return DataSource.TRACES; - case 'meter': - return DataSource.METER; default: return DataSource.METRICS; }