feat: integrate meter api changes

This commit is contained in:
Yunus M 2025-08-05 14:30:58 +05:30
parent 0595c526a7
commit 07659f91c3
40 changed files with 218 additions and 317 deletions

View File

@ -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"
}

View File

@ -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"
}

View File

@ -17,6 +17,7 @@ export const getAggregateAttribute = async ({
aggregateOperator,
searchText,
dataSource,
source,
}: IGetAggregateAttributePayload): Promise<
SuccessResponse<IQueryAutocompleteResponse> | ErrorResponse
> => {
@ -27,7 +28,7 @@ export const getAggregateAttribute = async ({
`/autocomplete/aggregate_attributes?${createQueryParams({
aggregateOperator,
searchText,
dataSource,
dataSource: source === 'meter' ? 'meter' : dataSource,
})}`,
);

View File

@ -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}`,
);
};

View File

@ -8,13 +8,14 @@ import {
export const getValueSuggestions = (
props: QueryKeyValueRequestProps,
): Promise<AxiosResponse<QueryKeyValueSuggestionsResponseProps>> => {
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}`,
);
};

View File

@ -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,

View File

@ -131,6 +131,7 @@ export const QueryBuilderV2 = memo(function QueryBuilderV2({
queryVariant={config?.queryVariant || 'dropdown'}
showOnlyWhereClause={showOnlyWhereClause}
isListViewPanel={isListViewPanel}
signalSource={config?.signalSource || ''}
/>
))}

View File

@ -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 || ''}
/>
</div>
);

View File

@ -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({
<div className="input">
<GroupByFilter
disabled={
(query.dataSource === DataSource.METRICS ||
query.dataSource === DataSource.METER) &&
query.dataSource === DataSource.METRICS &&
!(query.aggregations?.[0] as MetricAggregation)?.metricName
}
query={query}

View File

@ -81,10 +81,12 @@ function QuerySearch({
queryData,
dataSource,
onRun,
signalSource,
}: {
onChange: (value: string) => 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;

View File

@ -28,6 +28,7 @@ export const QueryV2 = memo(function QueryV2({
isListViewPanel = false,
version,
showOnlyWhereClause = false,
signalSource = '',
}: QueryProps & { ref: React.RefObject<HTMLDivElement> }): 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({
<div className="query-actions-container">
<div className="query-actions-left-container">
<QBEntityOptions
isMetricsDataSource={
dataSource === DataSource.METRICS || dataSource === DataSource.METER
}
isMetricsDataSource={dataSource === DataSource.METRICS}
showFunctions={
(version && version === ENTITY_VERSION_V4) ||
query.dataSource === DataSource.LOGS ||
query.dataSource === DataSource.METRICS ||
query.dataSource === DataSource.METER ||
showFunctions ||
false
}
@ -172,13 +170,13 @@ export const QueryV2 = memo(function QueryV2({
{!isCollapsed && (
<div className="qb-elements-container">
<div className="qb-search-container">
{(dataSource === DataSource.METRICS ||
dataSource === DataSource.METER) && (
{dataSource === DataSource.METRICS && (
<div className="metrics-select-container">
<MetricsSelect
query={query}
index={index}
version={ENTITY_VERSION_V5}
signalSource={signalSource as 'meter' | ''}
/>
</div>
)}
@ -190,6 +188,7 @@ export const QueryV2 = memo(function QueryV2({
onChange={handleSearchChange}
queryData={query}
dataSource={dataSource}
signalSource={signalSource}
/>
</div>
@ -204,8 +203,7 @@ export const QueryV2 = memo(function QueryV2({
{!showOnlyWhereClause &&
!isListViewPanel &&
dataSource !== DataSource.METRICS &&
dataSource !== DataSource.METER && (
dataSource !== DataSource.METRICS && (
<QueryAggregation
dataSource={dataSource}
key={`query-search-${query.queryName}-${query.dataSource}`}
@ -216,17 +214,15 @@ export const QueryV2 = memo(function QueryV2({
/>
)}
{!showOnlyWhereClause &&
(dataSource === DataSource.METRICS ||
dataSource === DataSource.METER) && (
<MetricsAggregateSection
panelType={panelType}
query={query}
index={index}
key={`metrics-aggregate-section-${query.queryName}-${query.dataSource}`}
version="v4"
/>
)}
{!showOnlyWhereClause && dataSource === DataSource.METRICS && (
<MetricsAggregateSection
panelType={panelType}
query={query}
index={index}
key={`metrics-aggregate-section-${query.queryName}-${query.dataSource}`}
version="v4"
/>
)}
{!showOnlyWhereClause && (
<QueryAddOns

View File

@ -513,7 +513,7 @@ export const convertAggregationToExpression = (
spaceAggregation === 'noop' ? 'count' : spaceAggregation;
// For metrics, use the MetricAggregation format
if (dataSource === DataSource.METRICS || dataSource === DataSource.METER) {
if (dataSource === DataSource.METRICS) {
return [
{
metricName: aggregateAttribute.key,
@ -598,10 +598,7 @@ export const adjustQueryForV5 = (currentQuery: Query): Query => {
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)[]);

View File

@ -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 {
)}
</section>
</section>
{isOpen && isLoading && !attributeValues.length && (
<section className="loading">
<Skeleton paragraph={{ rows: 4 }} />
</section>
)}
{isOpen && !isLoading && (
{isOpen &&
(isLoading || isLoadingKeyValueSuggestions) &&
!attributeValues.length && (
<section className="loading">
<Skeleton paragraph={{ rows: 4 }} />
</section>
)}
{isOpen && !isLoading && !isLoadingKeyValueSuggestions && (
<>
{!isEmptyStateWithDocsEnabled && (
<section className="search">

View File

@ -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,
};

View File

@ -23,7 +23,7 @@ export enum SignalType {
LOGS = 'logs',
API_MONITORING = 'api_monitoring',
EXCEPTIONS = 'exceptions',
METER = 'meter',
METER_EXPLORER = 'meter_explorer',
}
export interface IQuickFiltersConfig {

View File

@ -114,10 +114,6 @@ export const mapOfQueryFilters: Record<DataSource, QueryAdditionalFilter[]> = {
{ 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<ReduceOperators, string>[] = [
@ -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<DataSource, Query> = {
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<LocalDataType, string[]> = {

View File

@ -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,
};

View File

@ -18,7 +18,6 @@ export const DATASOURCE_VS_ROUTES: Record<DataSource, string> = {
[DataSource.METRICS]: ROUTES.METRICS_EXPLORER,
[DataSource.TRACES]: ROUTES.TRACES_EXPLORER,
[DataSource.LOGS]: ROUTES.LOGS_EXPLORER,
[DataSource.METER]: ROUTES.METER_EXPLORER,
};
export const saveNewViewHandler = ({

View File

@ -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;

View File

@ -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 {
<Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}>
<div
className={cx('meter-explorer-container', {
// 'quick-filters-open': showQuickFilters,
'quick-filters-open': showQuickFilters,
})}
>
{/* <div
<div
className={cx('meter-explorer-quick-filters-section', {
hidden: !showQuickFilters,
})}
@ -118,19 +117,19 @@ function Explorer(): JSX.Element {
<QuickFilters
className="qf-meter-explorer"
source={QuickFiltersSource.METER_EXPLORER}
signal={SignalType.METER}
signal={SignalType.METER_EXPLORER}
showFilterCollapse
showQueryName={false}
handleFilterVisibilityChange={(): void => {
setShowQuickFilters(!showQuickFilters);
}}
/>
</div> */}
</div>
<div className="meter-explorer-content-section">
<div className="meter-explorer-explore-content">
<div className="explore-header">
{/* <div className="explore-header-left-actions">
<div className="explore-header-left-actions">
{!showQuickFilters && (
<Tooltip title="Show Quick Filters" placement="right" arrow={false}>
<Button
@ -140,7 +139,7 @@ function Explorer(): JSX.Element {
/>
</Tooltip>
)}
</div> */}
</div>
<div className="explore-header-right-actions">
<DateTimeSelector showAutoRefresh />
@ -151,8 +150,9 @@ function Explorer(): JSX.Element {
</div>
<QueryBuilderV2
config={{
initialDataSource: DataSource.METER,
initialDataSource: DataSource.METRICS,
queryVariant: 'static',
signalSource: 'meter',
}}
panelType={PANEL_TYPES.TIME_SERIES}
queryComponents={queryComponents}

View File

@ -1,6 +1,6 @@
import { isAxiosError } from 'axios';
import { ENTITY_VERSION_V5 } from 'constants/app';
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import { initialQueryMeterWithType, PANEL_TYPES } from 'constants/queryBuilder';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
import TimeSeriesView from 'container/TimeSeriesView/TimeSeriesView';
import { convertDataValueToMs } from 'container/TimeSeriesView/utils';
@ -45,7 +45,7 @@ function TimeSeries(): JSX.Element {
}, [currentQuery]);
const queryPayloads = useMemo(
() => [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}
/>
</div>
))}

View File

@ -188,7 +188,7 @@ function Explorer(): JSX.Element {
query={exportDefaultQuery}
sourcepage={DataSource.METRICS}
onExport={handleExport}
isOneChartPerQuery={showOneChartPerQuery}
isOneChartPerQuery={false}
splitedQueries={splitedQueries}
/>
</Sentry.ErrorBoundary>

View File

@ -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: [

View File

@ -17,8 +17,9 @@ export type QueryBuilderConfig =
| {
queryVariant: 'static';
initialDataSource: DataSource;
signalSource?: string;
}
| { queryVariant: 'dropdown' };
| { queryVariant: 'dropdown'; signalSource?: string };
export type QueryBuilderProps = {
config?: QueryBuilderConfig;

View File

@ -11,4 +11,5 @@ export type QueryProps = {
version: string;
showSpanScopeSelector?: boolean;
showOnlyWhereClause?: boolean;
signalSource?: string;
} & Pick<QueryBuilderProps, 'filterConfigs' | 'queryComponents'>;

View File

@ -8,4 +8,5 @@ export type AgregatorFilterProps = Pick<AutoCompleteProps, 'disabled'> & {
defaultValue?: string;
onSelect?: (value: BaseAutocompleteData) => void;
index?: number;
signalSource?: 'meter' | '';
};

View File

@ -38,6 +38,7 @@ export const AggregatorFilter = memo(function AggregatorFilter({
defaultValue,
onSelect,
index,
signalSource,
}: AgregatorFilterProps): JSX.Element {
const queryClient = useQueryClient();
const [optionsData, setOptionsData] = useState<ExtendedSelectOption[]>([]);
@ -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 (
<AutoComplete
getPopupContainer={popupContainer}
placeholder={placeholder}
placeholder={getPlaceholder()}
style={selectStyle}
filterOption={false}
onSearch={handleSearchText}

View File

@ -2,13 +2,11 @@ import './TimeSeriesView.styles.scss';
import logEvent from 'api/common/logEvent';
import ErrorInPlace from 'components/ErrorInPlace/ErrorInPlace';
import { PanelDataLoading } from 'components/PanelDataLoading/PanelDataLoading';
import Uplot from 'components/Uplot';
import { QueryParams } from 'constants/query';
import EmptyLogsSearch from 'container/EmptyLogsSearch/EmptyLogsSearch';
import { getLocalStorageGraphVisibilityState } from 'container/GridCardLayout/GridCard/utils';
import { LogsLoading } from 'container/LogsLoading/LogsLoading';
import NoData from 'container/MeterExplorer/Explorer/NoData';
import EmptyMetricsSearch from 'container/MetricsExplorer/Explorer/EmptyMetricsSearch';
import { MetricsLoading } from 'container/MetricsExplorer/MetricsLoading/MetricsLoading';
import NoLogs from 'container/NoLogs/NoLogs';
@ -173,10 +171,6 @@ function TimeSeriesView({
logEvent('Metrics Explorer: Data present', {
panelType: 'TIME_SERIES',
});
} else if (dataSource === DataSource.METER) {
logEvent('Meter Explorer: Data present', {
panelType: 'TIME_SERIES',
});
}
}
}, [isLoading, isError, chartData, dataSource]);
@ -211,6 +205,7 @@ function TimeSeriesView({
return (
<div className="time-series-view">
{isError && error && <ErrorInPlace error={error as APIError} />}
<div
className="graph-container"
style={{ height: '100%', width: '100%' }}
@ -220,7 +215,6 @@ function TimeSeriesView({
{isLoading && dataSource === DataSource.LOGS && <LogsLoading />}
{isLoading && dataSource === DataSource.TRACES && <TracesLoading />}
{isLoading && dataSource === DataSource.METRICS && <MetricsLoading />}
{isLoading && dataSource === DataSource.METER && <PanelDataLoading />}
{chartData &&
chartData[0] &&
@ -237,8 +231,7 @@ function TimeSeriesView({
!isLoading &&
!isError &&
!isFilterApplied &&
dataSource !== DataSource.METRICS &&
dataSource !== DataSource.METER && <NoLogs dataSource={dataSource} />}
dataSource !== DataSource.METRICS && <NoLogs dataSource={dataSource} />}
{chartData &&
chartData[0] &&
@ -247,13 +240,6 @@ function TimeSeriesView({
!isError &&
dataSource === DataSource.METRICS && <EmptyMetricsSearch />}
{chartData &&
chartData[0] &&
chartData[0]?.length === 0 &&
!isLoading &&
!isError &&
dataSource === DataSource.METER && <NoData />}
{!isLoading &&
!isError &&
chartData &&

View File

@ -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<QueryKeyValueSuggestionsResponseProps> | ErrorResponse
>;
}): UseQueryResult<
AxiosResponse<QueryKeyValueSuggestionsResponseProps>,
AxiosError
> =>
useQuery<AxiosResponse<QueryKeyValueSuggestionsResponseProps>, 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' | '',
}),
});

View File

@ -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 (
<div className="meter-explorer-page">
<RouteTab routes={routes} activeKey={pathname} history={history} />

View File

@ -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',
});

View File

@ -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],

View File

@ -38,7 +38,6 @@ const getUpdaterConfig = (
setSavedViewPreferences,
),
[DataSource.METRICS]: metricsUpdater,
[DataSource.METER]: metricsUpdater,
});
export function usePreferenceUpdater({

View File

@ -4,4 +4,5 @@ export interface IGetAggregateAttributePayload {
aggregateOperator: string;
dataSource: DataSource;
searchText: string;
source?: 'meter' | '';
}

View File

@ -87,6 +87,7 @@ export type IBuilderQuery = {
pageSize?: number;
offset?: number;
selectColumns?: BaseAutocompleteData[] | TelemetryFieldKey[];
source?: 'meter' | '';
};
export interface IClickHouseQuery {

View File

@ -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';

View File

@ -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[];
}

View File

@ -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: <T extends keyof QueryBuilderData>(
query: Query,

View File

@ -29,7 +29,6 @@ export function convertAggregationsToBaseAutocompleteData(
if (!aggregations || aggregations.length === 0) {
switch (dataSource) {
case DataSource.METRICS:
case DataSource.METER:
return [
{
id: uuid(),

View File

@ -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;
}