mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-07-31 18:51:59 +08:00

* fix: having value data type * feat: connect new builder to dashboard * Fix/query builder filters (#2623) * feat: rename query data type * fix: remove reset of groupBy * fix: filters search * fix: calls autocomplete times * fix: response mapper * fix: removee unnecessary field * fix: no check ts types for old query builder * fix: disable check utils old builder * feat: add query builder to the alerts * fix: alert response integration with query builder * fix: validation of query builder rules * fix: rules query builder * fix: filter value with similar keys * fix: null values for options * fix: query builder disabled when exist formula * fix: removing filter key with underscore * feat: add builder data to metric application (#2665) * feat: add builder data to metric application * fix: query types to single variant * fix: formula legend formatting * fix: argumant name * fix: date for graph --------- Co-authored-by: Palash Gupta <palashgdev@gmail.com> * fix: pipeline --------- Co-authored-by: Palash Gupta <palashgdev@gmail.com>
216 lines
6.4 KiB
TypeScript
216 lines
6.4 KiB
TypeScript
import { AutoComplete, Col, Input, Row, Select, Spin } from 'antd';
|
|
import { getMetricName } from 'api/metrics/getMetricName';
|
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
|
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
|
import React, { useEffect, useState } from 'react';
|
|
import { IMetricsBuilderQuery } from 'types/api/dashboard/getAll';
|
|
import { EReduceOperator } from 'types/common/dashboard';
|
|
|
|
import { AggregateFunctions } from '../Options';
|
|
import QueryHeader from '../QueryHeader';
|
|
import MetricTagKeyFilter from './MetricTagKeyFilter';
|
|
import { IOption } from './MetricTagKeyFilter/types';
|
|
import { GetTagKeys } from './MetricTagKeyFilter/utils';
|
|
import { IQueryBuilderQueryHandleChange } from './types';
|
|
|
|
const { Option } = Select;
|
|
|
|
interface IMetricsBuilderProps {
|
|
queryIndex: number | string;
|
|
selectedGraph: GRAPH_TYPES;
|
|
queryData: IMetricsBuilderQuery;
|
|
handleQueryChange: (args: IQueryBuilderQueryHandleChange) => void;
|
|
}
|
|
|
|
function MetricsBuilder({
|
|
queryIndex,
|
|
selectedGraph,
|
|
queryData,
|
|
handleQueryChange,
|
|
}: IMetricsBuilderProps): JSX.Element {
|
|
const [groupByOptions, setGroupByOptions] = useState<IOption[]>([]);
|
|
const [metricName, setMetricName] = useState<string | null>(
|
|
queryData.metricName,
|
|
);
|
|
|
|
const [metricNameList, setMetricNameList] = useState<string[]>([]);
|
|
const [metricNameLoading, setMetricNameLoading] = useState(false);
|
|
|
|
const handleMetricNameSelect = (e: string): void => {
|
|
handleQueryChange({ queryIndex, metricName: e });
|
|
setMetricName(e);
|
|
};
|
|
|
|
const handleMetricNameSearch = async (searchQuery = ''): Promise<void> => {
|
|
handleMetricNameSelect(searchQuery);
|
|
setMetricNameList([]);
|
|
setMetricNameLoading(true);
|
|
const { payload } = await getMetricName(searchQuery);
|
|
setMetricNameLoading(false);
|
|
if (!payload || !payload.data) {
|
|
return;
|
|
}
|
|
setMetricNameList(payload.data);
|
|
};
|
|
const [aggregateFunctionList, setAggregateFunctionList] = useState(
|
|
AggregateFunctions,
|
|
);
|
|
const handleAggregateFunctionsSearch = (searchQuery = ''): void => {
|
|
setAggregateFunctionList(
|
|
AggregateFunctions.filter(({ label }) =>
|
|
label.includes(searchQuery.toUpperCase()),
|
|
) || [],
|
|
);
|
|
};
|
|
|
|
useEffect(() => {
|
|
GetTagKeys(metricName || '').then((tagKeys) => {
|
|
setGroupByOptions(tagKeys);
|
|
});
|
|
}, [metricName]);
|
|
|
|
return (
|
|
<QueryHeader
|
|
name={queryData.name}
|
|
disabled={queryData.disabled}
|
|
onDisable={(): void =>
|
|
handleQueryChange({ queryIndex, toggleDisable: true })
|
|
}
|
|
onDelete={(): void => {
|
|
handleQueryChange({ queryIndex, toggleDelete: true });
|
|
}}
|
|
>
|
|
<div style={{ display: 'flex', flexDirection: 'column', padding: '0.5rem' }}>
|
|
<div>
|
|
<Select
|
|
onChange={(e): void =>
|
|
handleQueryChange({ queryIndex, aggregateFunction: e })
|
|
}
|
|
defaultValue={queryData.aggregateOperator || AggregateFunctions[0]}
|
|
style={{ minWidth: 150 }}
|
|
options={aggregateFunctionList}
|
|
showSearch
|
|
onSearch={handleAggregateFunctionsSearch}
|
|
filterOption={false}
|
|
/>
|
|
</div>
|
|
<Row style={{ gap: '3%', margin: '0.5rem 0' }}>
|
|
<Row style={{ flex: 2, gap: '3%' }}>
|
|
<Select
|
|
defaultValue="metrics"
|
|
showArrow={false}
|
|
dropdownStyle={{ display: 'none' }}
|
|
>
|
|
<Option value="metrics">Metrics</Option>
|
|
</Select>
|
|
|
|
<AutoComplete
|
|
showSearch
|
|
placeholder="Metric Name (Start typing to get suggestions)"
|
|
style={{ flex: 1, minWidth: 200 }}
|
|
showArrow={false}
|
|
filterOption={false}
|
|
onSearch={handleMetricNameSearch}
|
|
notFoundContent={metricNameLoading ? <Spin size="small" /> : null}
|
|
options={metricNameList.map((option) => ({
|
|
label: option,
|
|
value: option,
|
|
}))}
|
|
defaultValue={queryData.metricName}
|
|
value={metricName}
|
|
onSelect={handleMetricNameSelect}
|
|
/>
|
|
</Row>
|
|
<Col style={{ flex: 3 }}>
|
|
<Row style={{ gap: '3%', marginBottom: '1rem' }}>
|
|
<Select
|
|
defaultValue="WHERE"
|
|
showArrow={false}
|
|
dropdownStyle={{ display: 'none' }}
|
|
>
|
|
<Option value="WHERE">WHERE</Option>
|
|
</Select>
|
|
<MetricTagKeyFilter
|
|
metricName={metricName}
|
|
selectedTagFilters={queryData.tagFilters.items}
|
|
onSetQuery={(
|
|
updatedTagFilters: IMetricsBuilderQuery['tagFilters']['items'],
|
|
): void =>
|
|
handleQueryChange({ queryIndex, tagFilters: updatedTagFilters })
|
|
}
|
|
/>
|
|
</Row>
|
|
<Row style={{ gap: '3%', marginBottom: '1rem' }}>
|
|
{selectedGraph === PANEL_TYPES.TIME_SERIES ? (
|
|
<>
|
|
{' '}
|
|
<Select
|
|
defaultValue="GROUP BY"
|
|
showArrow={false}
|
|
dropdownStyle={{ display: 'none' }}
|
|
>
|
|
<Option value="GROUP BY">GROUP BY</Option>
|
|
</Select>
|
|
<Select
|
|
mode="multiple"
|
|
showSearch
|
|
style={{ flex: 1 }}
|
|
defaultActiveFirstOption={false}
|
|
filterOption={false}
|
|
notFoundContent={metricNameLoading ? <Spin size="small" /> : null}
|
|
options={groupByOptions}
|
|
defaultValue={queryData.groupBy}
|
|
onChange={(e): void => {
|
|
handleQueryChange({ queryIndex, groupBy: e });
|
|
}}
|
|
/>
|
|
</>
|
|
) : (
|
|
<>
|
|
<Select
|
|
defaultValue="REDUCE TO"
|
|
showArrow={false}
|
|
dropdownStyle={{ display: 'none' }}
|
|
>
|
|
<Option value="GROUP BY">REDUCE TO</Option>
|
|
</Select>
|
|
<Select
|
|
placeholder="Latest of values in timeframe"
|
|
style={{ flex: 1 }}
|
|
options={Object.keys(EReduceOperator)
|
|
.filter((op) => !(parseInt(op, 10) >= 0))
|
|
.map((op) => ({
|
|
label: op,
|
|
value: EReduceOperator[op as keyof typeof EReduceOperator],
|
|
}))}
|
|
defaultValue={
|
|
EReduceOperator[
|
|
(queryData.reduceTo as unknown) as keyof typeof EReduceOperator
|
|
]
|
|
}
|
|
onChange={(e): void => {
|
|
handleQueryChange({ queryIndex, reduceTo: e });
|
|
}}
|
|
/>
|
|
</>
|
|
)}
|
|
</Row>
|
|
</Col>
|
|
</Row>
|
|
<Row style={{ margin: '0.5rem 0' }}>
|
|
<Input
|
|
onChange={(e): void => {
|
|
handleQueryChange({ queryIndex, legend: e.target.value });
|
|
}}
|
|
size="middle"
|
|
defaultValue={queryData.legend}
|
|
addonBefore="Legend Format"
|
|
/>
|
|
</Row>
|
|
</div>
|
|
</QueryHeader>
|
|
);
|
|
}
|
|
|
|
export default MetricsBuilder;
|