mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 20:19:13 +08:00
feat: add query builder to the alerts (#2657)
* 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>
This commit is contained in:
parent
f7cd0d4934
commit
8679f2c37a
9
frontend/src/constants/alerts.ts
Normal file
9
frontend/src/constants/alerts.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
||||||
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
|
export const ALERTS_DATA_SOURCE_MAP: Record<AlertTypes, DataSource> = {
|
||||||
|
[AlertTypes.METRICS_BASED_ALERT]: DataSource.METRICS,
|
||||||
|
[AlertTypes.LOGS_BASED_ALERT]: DataSource.LOGS,
|
||||||
|
[AlertTypes.TRACES_BASED_ALERT]: DataSource.TRACES,
|
||||||
|
[AlertTypes.EXCEPTIONS_BASED_ALERT]: DataSource.TRACES,
|
||||||
|
};
|
@ -86,7 +86,7 @@ export const initialAggregateAttribute: IBuilderQuery['aggregateAttribute'] = {
|
|||||||
export const initialQueryBuilderFormValues: IBuilderQuery = {
|
export const initialQueryBuilderFormValues: IBuilderQuery = {
|
||||||
dataSource: DataSource.METRICS,
|
dataSource: DataSource.METRICS,
|
||||||
queryName: createNewBuilderItemName({ existNames: [], sourceNames: alphabet }),
|
queryName: createNewBuilderItemName({ existNames: [], sourceNames: alphabet }),
|
||||||
aggregateOperator: Object.values(MetricAggregateOperator)[0],
|
aggregateOperator: MetricAggregateOperator.NOOP,
|
||||||
aggregateAttribute: initialAggregateAttribute,
|
aggregateAttribute: initialAggregateAttribute,
|
||||||
tagFilters: { items: [], op: 'AND' },
|
tagFilters: { items: [], op: 'AND' },
|
||||||
expression: createNewBuilderItemName({
|
expression: createNewBuilderItemName({
|
||||||
|
5
frontend/src/constants/regExp.ts
Normal file
5
frontend/src/constants/regExp.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export const FORMULA_REGEXP = /F\d+/;
|
||||||
|
|
||||||
|
export const HAVING_FILTER_REGEXP = /^[-\d.,\s]+$/;
|
||||||
|
|
||||||
|
export const TYPE_ADDON_REGEXP = /_(.+)/;
|
@ -1,3 +1,7 @@
|
|||||||
|
import {
|
||||||
|
initialQueryBuilderFormValues,
|
||||||
|
PANEL_TYPES,
|
||||||
|
} from 'constants/queryBuilder';
|
||||||
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
||||||
import {
|
import {
|
||||||
AlertDef,
|
AlertDef,
|
||||||
@ -5,6 +9,12 @@ import {
|
|||||||
defaultEvalWindow,
|
defaultEvalWindow,
|
||||||
defaultMatchType,
|
defaultMatchType,
|
||||||
} from 'types/api/alerts/def';
|
} from 'types/api/alerts/def';
|
||||||
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
|
import {
|
||||||
|
DataSource,
|
||||||
|
LogsAggregatorOperator,
|
||||||
|
TracesAggregatorOperator,
|
||||||
|
} from 'types/common/queryBuilder';
|
||||||
|
|
||||||
const defaultAlertDescription =
|
const defaultAlertDescription =
|
||||||
'This alert is fired when the defined metric (current value: {{$value}}) crosses the threshold ({{$threshold}})';
|
'This alert is fired when the defined metric (current value: {{$value}}) crosses the threshold ({{$threshold}})';
|
||||||
@ -19,28 +29,16 @@ const defaultAnnotations = {
|
|||||||
export const alertDefaults: AlertDef = {
|
export const alertDefaults: AlertDef = {
|
||||||
alertType: AlertTypes.METRICS_BASED_ALERT,
|
alertType: AlertTypes.METRICS_BASED_ALERT,
|
||||||
condition: {
|
condition: {
|
||||||
compositeMetricQuery: {
|
compositeQuery: {
|
||||||
builderQueries: {
|
builderQueries: {
|
||||||
A: {
|
A: {
|
||||||
queryName: 'A',
|
...initialQueryBuilderFormValues,
|
||||||
name: 'A',
|
|
||||||
formulaOnly: false,
|
|
||||||
metricName: '',
|
|
||||||
tagFilters: {
|
|
||||||
op: 'AND',
|
|
||||||
items: [],
|
|
||||||
},
|
|
||||||
groupBy: [],
|
|
||||||
aggregateOperator: 1,
|
|
||||||
expression: 'A',
|
|
||||||
disabled: false,
|
|
||||||
toggleDisable: false,
|
|
||||||
toggleDelete: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
promQueries: {},
|
promQueries: {},
|
||||||
chQueries: {},
|
chQueries: {},
|
||||||
queryType: 1,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
|
panelType: PANEL_TYPES.TIME_SERIES,
|
||||||
},
|
},
|
||||||
op: defaultCompareOp,
|
op: defaultCompareOp,
|
||||||
matchType: defaultMatchType,
|
matchType: defaultMatchType,
|
||||||
@ -55,23 +53,12 @@ export const alertDefaults: AlertDef = {
|
|||||||
export const logAlertDefaults: AlertDef = {
|
export const logAlertDefaults: AlertDef = {
|
||||||
alertType: AlertTypes.LOGS_BASED_ALERT,
|
alertType: AlertTypes.LOGS_BASED_ALERT,
|
||||||
condition: {
|
condition: {
|
||||||
compositeMetricQuery: {
|
compositeQuery: {
|
||||||
builderQueries: {
|
builderQueries: {
|
||||||
A: {
|
A: {
|
||||||
queryName: 'A',
|
...initialQueryBuilderFormValues,
|
||||||
name: 'A',
|
aggregateOperator: LogsAggregatorOperator.COUNT,
|
||||||
formulaOnly: false,
|
dataSource: DataSource.LOGS,
|
||||||
metricName: '',
|
|
||||||
tagFilters: {
|
|
||||||
op: 'AND',
|
|
||||||
items: [],
|
|
||||||
},
|
|
||||||
groupBy: [],
|
|
||||||
aggregateOperator: 1,
|
|
||||||
expression: 'A',
|
|
||||||
disabled: false,
|
|
||||||
toggleDisable: false,
|
|
||||||
toggleDelete: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
promQueries: {},
|
promQueries: {},
|
||||||
@ -84,7 +71,8 @@ export const logAlertDefaults: AlertDef = {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
queryType: 2,
|
queryType: EQueryType.CLICKHOUSE,
|
||||||
|
panelType: PANEL_TYPES.TIME_SERIES,
|
||||||
},
|
},
|
||||||
op: defaultCompareOp,
|
op: defaultCompareOp,
|
||||||
matchType: '4',
|
matchType: '4',
|
||||||
@ -100,23 +88,12 @@ export const logAlertDefaults: AlertDef = {
|
|||||||
export const traceAlertDefaults: AlertDef = {
|
export const traceAlertDefaults: AlertDef = {
|
||||||
alertType: AlertTypes.TRACES_BASED_ALERT,
|
alertType: AlertTypes.TRACES_BASED_ALERT,
|
||||||
condition: {
|
condition: {
|
||||||
compositeMetricQuery: {
|
compositeQuery: {
|
||||||
builderQueries: {
|
builderQueries: {
|
||||||
A: {
|
A: {
|
||||||
queryName: 'A',
|
...initialQueryBuilderFormValues,
|
||||||
name: 'A',
|
aggregateOperator: TracesAggregatorOperator.COUNT,
|
||||||
formulaOnly: false,
|
dataSource: DataSource.TRACES,
|
||||||
metricName: '',
|
|
||||||
tagFilters: {
|
|
||||||
op: 'AND',
|
|
||||||
items: [],
|
|
||||||
},
|
|
||||||
groupBy: [],
|
|
||||||
aggregateOperator: 1,
|
|
||||||
expression: 'A',
|
|
||||||
disabled: false,
|
|
||||||
toggleDisable: false,
|
|
||||||
toggleDelete: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
promQueries: {},
|
promQueries: {},
|
||||||
@ -129,7 +106,8 @@ export const traceAlertDefaults: AlertDef = {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
queryType: 2,
|
queryType: EQueryType.CLICKHOUSE,
|
||||||
|
panelType: PANEL_TYPES.TIME_SERIES,
|
||||||
},
|
},
|
||||||
op: defaultCompareOp,
|
op: defaultCompareOp,
|
||||||
matchType: '4',
|
matchType: '4',
|
||||||
@ -145,23 +123,12 @@ export const traceAlertDefaults: AlertDef = {
|
|||||||
export const exceptionAlertDefaults: AlertDef = {
|
export const exceptionAlertDefaults: AlertDef = {
|
||||||
alertType: AlertTypes.EXCEPTIONS_BASED_ALERT,
|
alertType: AlertTypes.EXCEPTIONS_BASED_ALERT,
|
||||||
condition: {
|
condition: {
|
||||||
compositeMetricQuery: {
|
compositeQuery: {
|
||||||
builderQueries: {
|
builderQueries: {
|
||||||
A: {
|
A: {
|
||||||
queryName: 'A',
|
...initialQueryBuilderFormValues,
|
||||||
name: 'A',
|
aggregateOperator: TracesAggregatorOperator.COUNT,
|
||||||
formulaOnly: false,
|
dataSource: DataSource.TRACES,
|
||||||
metricName: '',
|
|
||||||
tagFilters: {
|
|
||||||
op: 'AND',
|
|
||||||
items: [],
|
|
||||||
},
|
|
||||||
groupBy: [],
|
|
||||||
aggregateOperator: 1,
|
|
||||||
expression: 'A',
|
|
||||||
disabled: false,
|
|
||||||
toggleDisable: false,
|
|
||||||
toggleDelete: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
promQueries: {},
|
promQueries: {},
|
||||||
@ -174,7 +141,8 @@ export const exceptionAlertDefaults: AlertDef = {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
queryType: 2,
|
queryType: EQueryType.CLICKHOUSE,
|
||||||
|
panelType: PANEL_TYPES.TIME_SERIES,
|
||||||
},
|
},
|
||||||
op: defaultCompareOp,
|
op: defaultCompareOp,
|
||||||
matchType: '4',
|
matchType: '4',
|
||||||
|
@ -60,10 +60,11 @@ function ChartPreview({
|
|||||||
|
|
||||||
switch (query?.queryType) {
|
switch (query?.queryType) {
|
||||||
case EQueryType.PROM:
|
case EQueryType.PROM:
|
||||||
return query.promQL?.length > 0 && query.promQL[0].query !== '';
|
return query.promql?.length > 0 && query.promql[0].query !== '';
|
||||||
case EQueryType.CLICKHOUSE:
|
case EQueryType.CLICKHOUSE:
|
||||||
return (
|
return (
|
||||||
query.clickHouse?.length > 0 && query.clickHouse[0].rawQuery?.length > 0
|
query.clickhouse_sql?.length > 0 &&
|
||||||
|
query.clickhouse_sql[0].rawQuery?.length > 0
|
||||||
);
|
);
|
||||||
case EQueryType.QUERY_BUILDER:
|
case EQueryType.QUERY_BUILDER:
|
||||||
return (
|
return (
|
||||||
@ -84,13 +85,13 @@ function ChartPreview({
|
|||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
GetMetricQueryRange({
|
GetMetricQueryRange({
|
||||||
query: query || {
|
query: query || {
|
||||||
queryType: 1,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
promQL: [],
|
promql: [],
|
||||||
builder: {
|
builder: {
|
||||||
queryFormulas: [],
|
queryFormulas: [],
|
||||||
queryData: [],
|
queryData: [],
|
||||||
},
|
},
|
||||||
clickHouse: [],
|
clickhouse_sql: [],
|
||||||
},
|
},
|
||||||
globalSelectedInterval: selectedInterval,
|
globalSelectedInterval: selectedInterval,
|
||||||
graphType,
|
graphType,
|
||||||
|
@ -1,36 +1,20 @@
|
|||||||
import { PlusOutlined } from '@ant-design/icons';
|
|
||||||
import { Button, Tabs } from 'antd';
|
import { Button, Tabs } from 'antd';
|
||||||
|
import { ALERTS_DATA_SOURCE_MAP } from 'constants/alerts';
|
||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import MetricsBuilderFormula from 'container/NewWidget/LeftContainer/QuerySection/QueryBuilder/queryBuilder/formula';
|
import { QueryBuilder } from 'container/QueryBuilder';
|
||||||
import MetricsBuilder from 'container/NewWidget/LeftContainer/QuerySection/QueryBuilder/queryBuilder/query';
|
import React from 'react';
|
||||||
import {
|
|
||||||
IQueryBuilderFormulaHandleChange,
|
|
||||||
IQueryBuilderQueryHandleChange,
|
|
||||||
} from 'container/NewWidget/LeftContainer/QuerySection/QueryBuilder/queryBuilder/types';
|
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
|
||||||
import React, { useCallback } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
||||||
import {
|
import { IChQueries, IPromQueries } from 'types/api/alerts/compositeQuery';
|
||||||
IChQueries,
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
IFormulaQueries,
|
|
||||||
IMetricQueries,
|
|
||||||
IPromQueries,
|
|
||||||
} from 'types/api/alerts/compositeQuery';
|
|
||||||
import { EAggregateOperator, EQueryType } from 'types/common/dashboard';
|
|
||||||
|
|
||||||
import ChQuerySection from './ChQuerySection';
|
import ChQuerySection from './ChQuerySection';
|
||||||
import PromqlSection from './PromqlSection';
|
import PromqlSection from './PromqlSection';
|
||||||
import { FormContainer, QueryButton, StepHeading } from './styles';
|
import { FormContainer, StepHeading } from './styles';
|
||||||
import { toIMetricsBuilderQuery } from './utils';
|
|
||||||
|
|
||||||
function QuerySection({
|
function QuerySection({
|
||||||
queryCategory,
|
queryCategory,
|
||||||
setQueryCategory,
|
setQueryCategory,
|
||||||
metricQueries,
|
|
||||||
setMetricQueries,
|
|
||||||
formulaQueries,
|
|
||||||
setFormulaQueries,
|
|
||||||
promQueries,
|
promQueries,
|
||||||
setPromQueries,
|
setPromQueries,
|
||||||
chQueries,
|
chQueries,
|
||||||
@ -41,9 +25,9 @@ function QuerySection({
|
|||||||
// init namespace for translations
|
// init namespace for translations
|
||||||
const { t } = useTranslation('alerts');
|
const { t } = useTranslation('alerts');
|
||||||
|
|
||||||
const handleQueryCategoryChange = (s: string): void => {
|
const handleQueryCategoryChange = (queryType: string): void => {
|
||||||
if (
|
if (
|
||||||
parseInt(s, 10) === EQueryType.PROM &&
|
queryType === EQueryType.PROM &&
|
||||||
(!promQueries || Object.keys(promQueries).length === 0)
|
(!promQueries || Object.keys(promQueries).length === 0)
|
||||||
) {
|
) {
|
||||||
setPromQueries({
|
setPromQueries({
|
||||||
@ -58,7 +42,7 @@ function QuerySection({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
parseInt(s, 10) === EQueryType.CLICKHOUSE &&
|
queryType === EQueryType.CLICKHOUSE &&
|
||||||
(!chQueries || Object.keys(chQueries).length === 0)
|
(!chQueries || Object.keys(chQueries).length === 0)
|
||||||
) {
|
) {
|
||||||
setChQueries({
|
setChQueries({
|
||||||
@ -71,148 +55,9 @@ function QuerySection({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setQueryCategory(parseInt(s, 10));
|
setQueryCategory(queryType as EQueryType);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getNextQueryLabel = useCallback((): string => {
|
|
||||||
let maxAscii = 0;
|
|
||||||
|
|
||||||
Object.keys(metricQueries).forEach((key) => {
|
|
||||||
const n = key.charCodeAt(0);
|
|
||||||
if (n > maxAscii) {
|
|
||||||
maxAscii = n - 64;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return String.fromCharCode(64 + maxAscii + 1);
|
|
||||||
}, [metricQueries]);
|
|
||||||
|
|
||||||
const handleFormulaChange = ({
|
|
||||||
formulaIndex,
|
|
||||||
expression,
|
|
||||||
legend,
|
|
||||||
toggleDisable,
|
|
||||||
toggleDelete,
|
|
||||||
}: IQueryBuilderFormulaHandleChange): void => {
|
|
||||||
const allFormulas = formulaQueries;
|
|
||||||
const current = allFormulas[formulaIndex];
|
|
||||||
if (expression !== undefined) {
|
|
||||||
current.expression = expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (legend !== undefined) {
|
|
||||||
current.legend = legend;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toggleDisable) {
|
|
||||||
current.disabled = !current.disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toggleDelete) {
|
|
||||||
delete allFormulas[formulaIndex];
|
|
||||||
} else {
|
|
||||||
allFormulas[formulaIndex] = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFormulaQueries({
|
|
||||||
...allFormulas,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMetricQueryChange = ({
|
|
||||||
queryIndex,
|
|
||||||
aggregateFunction,
|
|
||||||
metricName,
|
|
||||||
tagFilters,
|
|
||||||
groupBy,
|
|
||||||
legend,
|
|
||||||
toggleDisable,
|
|
||||||
toggleDelete,
|
|
||||||
}: IQueryBuilderQueryHandleChange): void => {
|
|
||||||
const allQueries = metricQueries;
|
|
||||||
const current = metricQueries[queryIndex];
|
|
||||||
if (aggregateFunction) {
|
|
||||||
current.aggregateOperator = aggregateFunction;
|
|
||||||
}
|
|
||||||
if (metricName) {
|
|
||||||
current.metricName = metricName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tagFilters && current.tagFilters) {
|
|
||||||
current.tagFilters.items = tagFilters;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (legend) {
|
|
||||||
current.legend = legend;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groupBy) {
|
|
||||||
current.groupBy = groupBy;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toggleDisable) {
|
|
||||||
current.disabled = !current.disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toggleDelete) {
|
|
||||||
delete allQueries[queryIndex];
|
|
||||||
} else {
|
|
||||||
allQueries[queryIndex] = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
setMetricQueries({
|
|
||||||
...allQueries,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const { notifications } = useNotifications();
|
|
||||||
|
|
||||||
const addMetricQuery = useCallback(() => {
|
|
||||||
if (Object.keys(metricQueries).length > 5) {
|
|
||||||
notifications.error({
|
|
||||||
message: t('metric_query_max_limit'),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryLabel = getNextQueryLabel();
|
|
||||||
|
|
||||||
const queries = metricQueries;
|
|
||||||
queries[queryLabel] = {
|
|
||||||
name: queryLabel,
|
|
||||||
queryName: queryLabel,
|
|
||||||
metricName: '',
|
|
||||||
formulaOnly: false,
|
|
||||||
aggregateOperator: EAggregateOperator.NOOP,
|
|
||||||
legend: '',
|
|
||||||
tagFilters: {
|
|
||||||
op: 'AND',
|
|
||||||
items: [],
|
|
||||||
},
|
|
||||||
groupBy: [],
|
|
||||||
disabled: false,
|
|
||||||
expression: queryLabel,
|
|
||||||
};
|
|
||||||
setMetricQueries({ ...queries });
|
|
||||||
}, [t, getNextQueryLabel, metricQueries, setMetricQueries, notifications]);
|
|
||||||
|
|
||||||
const addFormula = useCallback(() => {
|
|
||||||
// defaulting to F1 as only one formula is supported
|
|
||||||
// in alert definition
|
|
||||||
const queryLabel = 'F1';
|
|
||||||
|
|
||||||
const formulas = formulaQueries;
|
|
||||||
formulas[queryLabel] = {
|
|
||||||
queryName: queryLabel,
|
|
||||||
name: queryLabel,
|
|
||||||
formulaOnly: true,
|
|
||||||
expression: 'A',
|
|
||||||
disabled: false,
|
|
||||||
legend: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
setFormulaQueries({ ...formulas });
|
|
||||||
}, [formulaQueries, setFormulaQueries]);
|
|
||||||
|
|
||||||
const renderPromqlUI = (): JSX.Element => (
|
const renderPromqlUI = (): JSX.Element => (
|
||||||
<PromqlSection promQueries={promQueries} setPromQueries={setPromQueries} />
|
<PromqlSection promQueries={promQueries} setPromQueries={setPromQueries} />
|
||||||
);
|
);
|
||||||
@ -221,61 +66,14 @@ function QuerySection({
|
|||||||
<ChQuerySection chQueries={chQueries} setChQueries={setChQueries} />
|
<ChQuerySection chQueries={chQueries} setChQueries={setChQueries} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderFormulaButton = (): JSX.Element => (
|
|
||||||
<QueryButton onClick={addFormula} icon={<PlusOutlined />}>
|
|
||||||
{t('button_formula')}
|
|
||||||
</QueryButton>
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderQueryButton = (): JSX.Element => (
|
|
||||||
<QueryButton onClick={addMetricQuery} icon={<PlusOutlined />}>
|
|
||||||
{t('button_query')}
|
|
||||||
</QueryButton>
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderMetricUI = (): JSX.Element => (
|
const renderMetricUI = (): JSX.Element => (
|
||||||
<div>
|
<QueryBuilder
|
||||||
{metricQueries &&
|
panelType={PANEL_TYPES.TIME_SERIES}
|
||||||
Object.keys(metricQueries).map((key: string) => {
|
config={{
|
||||||
// todo(amol): need to handle this in fetch
|
queryVariant: 'static',
|
||||||
const current = metricQueries[key];
|
initialDataSource: ALERTS_DATA_SOURCE_MAP[alertType],
|
||||||
current.name = key;
|
}}
|
||||||
|
/>
|
||||||
return (
|
|
||||||
<MetricsBuilder
|
|
||||||
key={key}
|
|
||||||
queryIndex={key}
|
|
||||||
queryData={toIMetricsBuilderQuery(current)}
|
|
||||||
selectedGraph={PANEL_TYPES.TIME_SERIES}
|
|
||||||
handleQueryChange={handleMetricQueryChange}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
|
|
||||||
{queryCategory !== EQueryType.PROM && renderQueryButton()}
|
|
||||||
<div style={{ marginTop: '1rem' }}>
|
|
||||||
{formulaQueries &&
|
|
||||||
Object.keys(formulaQueries).map((key: string) => {
|
|
||||||
// todo(amol): need to handle this in fetch
|
|
||||||
const current = formulaQueries[key];
|
|
||||||
current.name = key;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MetricsBuilderFormula
|
|
||||||
key={key}
|
|
||||||
formulaIndex={key}
|
|
||||||
formulaData={current}
|
|
||||||
handleFormulaChange={handleFormulaChange}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{queryCategory === EQueryType.QUERY_BUILDER &&
|
|
||||||
(!formulaQueries || Object.keys(formulaQueries).length === 0) &&
|
|
||||||
metricQueries &&
|
|
||||||
Object.keys(metricQueries).length > 0 &&
|
|
||||||
renderFormulaButton()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleRunQuery = (): void => {
|
const handleRunQuery = (): void => {
|
||||||
@ -285,19 +83,18 @@ function QuerySection({
|
|||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
label: t('tab_qb'),
|
label: t('tab_qb'),
|
||||||
key: EQueryType.QUERY_BUILDER.toString(),
|
key: EQueryType.QUERY_BUILDER,
|
||||||
disabled: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('tab_chquery'),
|
label: t('tab_chquery'),
|
||||||
key: EQueryType.CLICKHOUSE.toString(),
|
key: EQueryType.CLICKHOUSE,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{ label: t('tab_qb'), key: EQueryType.QUERY_BUILDER.toString() },
|
{ label: t('tab_qb'), key: EQueryType.QUERY_BUILDER },
|
||||||
{ label: t('tab_chquery'), key: EQueryType.CLICKHOUSE.toString() },
|
{ label: t('tab_chquery'), key: EQueryType.CLICKHOUSE },
|
||||||
{ label: t('tab_promql'), key: EQueryType.PROM.toString() },
|
{ label: t('tab_promql'), key: EQueryType.PROM },
|
||||||
];
|
];
|
||||||
|
|
||||||
const renderTabs = (typ: AlertTypes): JSX.Element | null => {
|
const renderTabs = (typ: AlertTypes): JSX.Element | null => {
|
||||||
@ -309,16 +106,14 @@ function QuerySection({
|
|||||||
<Tabs
|
<Tabs
|
||||||
type="card"
|
type="card"
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
defaultActiveKey={EQueryType.CLICKHOUSE.toString()}
|
defaultActiveKey={EQueryType.QUERY_BUILDER}
|
||||||
activeKey={queryCategory.toString()}
|
activeKey={queryCategory}
|
||||||
onChange={handleQueryCategoryChange}
|
onChange={handleQueryCategoryChange}
|
||||||
tabBarExtraContent={
|
tabBarExtraContent={
|
||||||
<span style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
<span style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
||||||
{queryCategory === EQueryType.CLICKHOUSE && (
|
<Button type="primary" onClick={handleRunQuery}>
|
||||||
<Button type="primary" onClick={handleRunQuery}>
|
Run Query
|
||||||
Run Query
|
</Button>
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
items={tabs}
|
items={tabs}
|
||||||
@ -330,16 +125,14 @@ function QuerySection({
|
|||||||
<Tabs
|
<Tabs
|
||||||
type="card"
|
type="card"
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
defaultActiveKey={EQueryType.QUERY_BUILDER.toString()}
|
defaultActiveKey={EQueryType.QUERY_BUILDER}
|
||||||
activeKey={queryCategory.toString()}
|
activeKey={queryCategory}
|
||||||
onChange={handleQueryCategoryChange}
|
onChange={handleQueryCategoryChange}
|
||||||
tabBarExtraContent={
|
tabBarExtraContent={
|
||||||
<span style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
<span style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
||||||
{queryCategory === EQueryType.CLICKHOUSE && (
|
<Button type="primary" onClick={handleRunQuery}>
|
||||||
<Button type="primary" onClick={handleRunQuery}>
|
Run Query
|
||||||
Run Query
|
</Button>
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
items={items}
|
items={items}
|
||||||
@ -373,10 +166,6 @@ function QuerySection({
|
|||||||
interface QuerySectionProps {
|
interface QuerySectionProps {
|
||||||
queryCategory: EQueryType;
|
queryCategory: EQueryType;
|
||||||
setQueryCategory: (n: EQueryType) => void;
|
setQueryCategory: (n: EQueryType) => void;
|
||||||
metricQueries: IMetricQueries;
|
|
||||||
setMetricQueries: (b: IMetricQueries) => void;
|
|
||||||
formulaQueries: IFormulaQueries;
|
|
||||||
setFormulaQueries: (b: IFormulaQueries) => void;
|
|
||||||
promQueries: IPromQueries;
|
promQueries: IPromQueries;
|
||||||
setPromQueries: (p: IPromQueries) => void;
|
setPromQueries: (p: IPromQueries) => void;
|
||||||
chQueries: IChQueries;
|
chQueries: IChQueries;
|
||||||
|
@ -5,18 +5,16 @@ import testAlertApi from 'api/alerts/testAlert';
|
|||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
import QueryTypeTag from 'container/NewWidget/LeftContainer/QueryTypeTag';
|
import QueryTypeTag from 'container/NewWidget/LeftContainer/QueryTypeTag';
|
||||||
import PlotTag from 'container/NewWidget/LeftContainer/WidgetGraph/PlotTag';
|
import PlotTag from 'container/NewWidget/LeftContainer/WidgetGraph/PlotTag';
|
||||||
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
import { useNotifications } from 'hooks/useNotifications';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
|
import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi';
|
||||||
|
import { mapQueryDataToApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataToApi';
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useQueryClient } from 'react-query';
|
import { useQueryClient } from 'react-query';
|
||||||
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
||||||
import {
|
import { IChQueries, IPromQueries } from 'types/api/alerts/compositeQuery';
|
||||||
IChQueries,
|
|
||||||
IFormulaQueries,
|
|
||||||
IMetricQueries,
|
|
||||||
IPromQueries,
|
|
||||||
} from 'types/api/alerts/compositeQuery';
|
|
||||||
import {
|
import {
|
||||||
AlertDef,
|
AlertDef,
|
||||||
defaultEvalWindow,
|
defaultEvalWindow,
|
||||||
@ -36,15 +34,8 @@ import {
|
|||||||
PanelContainer,
|
PanelContainer,
|
||||||
StyledLeftContainer,
|
StyledLeftContainer,
|
||||||
} from './styles';
|
} from './styles';
|
||||||
import useDebounce from './useDebounce';
|
|
||||||
import UserGuide from './UserGuide';
|
import UserGuide from './UserGuide';
|
||||||
import {
|
import { prepareStagedQuery, toChartInterval } from './utils';
|
||||||
prepareBuilderQueries,
|
|
||||||
prepareStagedQuery,
|
|
||||||
toChartInterval,
|
|
||||||
toFormulaQueries,
|
|
||||||
toMetricQueries,
|
|
||||||
} from './utils';
|
|
||||||
|
|
||||||
function FormAlertRules({
|
function FormAlertRules({
|
||||||
alertType,
|
alertType,
|
||||||
@ -55,33 +46,21 @@ function FormAlertRules({
|
|||||||
// init namespace for translations
|
// init namespace for translations
|
||||||
const { t } = useTranslation('alerts');
|
const { t } = useTranslation('alerts');
|
||||||
|
|
||||||
|
const { queryBuilderData, initQueryBuilderData } = useQueryBuilder();
|
||||||
|
|
||||||
// use query client
|
// use query client
|
||||||
const ruleCache = useQueryClient();
|
const ruleCache = useQueryClient();
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
// queryRunId helps to override of query caching for clickhouse query
|
|
||||||
// tab. A random string will be assigned for each execution
|
|
||||||
const [runQueryId, setRunQueryId] = useState<string>();
|
|
||||||
|
|
||||||
// alertDef holds the form values to be posted
|
// alertDef holds the form values to be posted
|
||||||
const [alertDef, setAlertDef] = useState<AlertDef>(initialValue);
|
const [alertDef, setAlertDef] = useState<AlertDef>(initialValue);
|
||||||
|
|
||||||
// initQuery contains initial query when component was mounted
|
// initQuery contains initial query when component was mounted
|
||||||
const initQuery = initialValue?.condition?.compositeMetricQuery;
|
const initQuery = initialValue.condition.compositeQuery;
|
||||||
|
|
||||||
const [queryCategory, setQueryCategory] = useState<EQueryType>(
|
const [queryCategory, setQueryCategory] = useState<EQueryType>(
|
||||||
initQuery?.queryType,
|
initQuery.queryType,
|
||||||
);
|
|
||||||
|
|
||||||
// local state to handle metric queries
|
|
||||||
const [metricQueries, setMetricQueries] = useState<IMetricQueries>(
|
|
||||||
toMetricQueries(initQuery?.builderQueries),
|
|
||||||
);
|
|
||||||
|
|
||||||
// local state to handle formula queries
|
|
||||||
const [formulaQueries, setFormulaQueries] = useState<IFormulaQueries>(
|
|
||||||
toFormulaQueries(initQuery?.builderQueries),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// local state to handle promql queries
|
// local state to handle promql queries
|
||||||
@ -106,43 +85,31 @@ function FormAlertRules({
|
|||||||
// run query button is provided.
|
// run query button is provided.
|
||||||
const [manualStagedQuery, setManualStagedQuery] = useState<StagedQuery>();
|
const [manualStagedQuery, setManualStagedQuery] = useState<StagedQuery>();
|
||||||
|
|
||||||
// delay to reduce load on backend api with auto-run query. only for clickhouse
|
|
||||||
// queries we have manual run, hence both debounce and debounceStagedQuery are not required
|
|
||||||
const debounceDelay = queryCategory !== EQueryType.CLICKHOUSE ? 1000 : 0;
|
|
||||||
|
|
||||||
// debounce query to delay backend api call and chart update.
|
|
||||||
// used in query builder and promql tabs to enable auto-refresh
|
|
||||||
// of chart on user edit
|
|
||||||
const debouncedStagedQuery = useDebounce(stagedQuery, debounceDelay);
|
|
||||||
|
|
||||||
// this use effect initiates staged query and
|
// this use effect initiates staged query and
|
||||||
// other queries based on server data.
|
// other queries based on server data.
|
||||||
// useful when fetching of initial values (from api)
|
// useful when fetching of initial values (from api)
|
||||||
// is delayed
|
// is delayed
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initQuery = initialValue?.condition?.compositeMetricQuery;
|
const initQuery = initialValue?.condition?.compositeQuery;
|
||||||
const typ = initQuery?.queryType;
|
const type = initQuery.queryType;
|
||||||
|
|
||||||
// extract metric query from builderQueries
|
const builderData = mapQueryDataFromApi(
|
||||||
const mq = toMetricQueries(initQuery?.builderQueries);
|
initialValue?.condition?.compositeQuery?.builderQueries || {},
|
||||||
|
);
|
||||||
// extract formula query from builderQueries
|
|
||||||
const fq = toFormulaQueries(initQuery?.builderQueries);
|
|
||||||
|
|
||||||
// prepare staged query
|
// prepare staged query
|
||||||
const sq = prepareStagedQuery(
|
const sq = prepareStagedQuery(
|
||||||
typ,
|
type,
|
||||||
mq,
|
builderData.queryData,
|
||||||
fq,
|
builderData.queryFormulas,
|
||||||
initQuery?.promQueries,
|
initQuery?.promQueries,
|
||||||
initQuery?.chQueries,
|
initQuery?.chQueries,
|
||||||
);
|
);
|
||||||
const pq = initQuery?.promQueries;
|
const pq = initQuery?.promQueries;
|
||||||
const chq = initQuery?.chQueries;
|
const chq = initQuery?.chQueries;
|
||||||
|
|
||||||
setQueryCategory(typ);
|
setQueryCategory(type);
|
||||||
setMetricQueries(mq);
|
initQueryBuilderData(builderData);
|
||||||
setFormulaQueries(fq);
|
|
||||||
setPromQueries(pq);
|
setPromQueries(pq);
|
||||||
setStagedQuery(sq);
|
setStagedQuery(sq);
|
||||||
|
|
||||||
@ -151,7 +118,7 @@ function FormAlertRules({
|
|||||||
|
|
||||||
setChQueries(chq);
|
setChQueries(chq);
|
||||||
setAlertDef(initialValue);
|
setAlertDef(initialValue);
|
||||||
}, [initialValue]);
|
}, [initialValue, initQueryBuilderData]);
|
||||||
|
|
||||||
// this useEffect updates staging query when
|
// this useEffect updates staging query when
|
||||||
// any of its sub-parameters changes
|
// any of its sub-parameters changes
|
||||||
@ -159,16 +126,15 @@ function FormAlertRules({
|
|||||||
// prepare staged query
|
// prepare staged query
|
||||||
const sq: StagedQuery = prepareStagedQuery(
|
const sq: StagedQuery = prepareStagedQuery(
|
||||||
queryCategory,
|
queryCategory,
|
||||||
metricQueries,
|
queryBuilderData.queryData,
|
||||||
formulaQueries,
|
queryBuilderData.queryFormulas,
|
||||||
promQueries,
|
promQueries,
|
||||||
chQueries,
|
chQueries,
|
||||||
);
|
);
|
||||||
setStagedQuery(sq);
|
setStagedQuery(sq);
|
||||||
}, [queryCategory, chQueries, metricQueries, formulaQueries, promQueries]);
|
}, [queryCategory, chQueries, queryBuilderData, promQueries]);
|
||||||
|
|
||||||
const onRunQuery = (): void => {
|
const onRunQuery = (): void => {
|
||||||
setRunQueryId(Math.random().toString(36).substring(2, 15));
|
|
||||||
setManualStagedQuery(stagedQuery);
|
setManualStagedQuery(stagedQuery);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -190,6 +156,15 @@ function FormAlertRules({
|
|||||||
evalWindow: defaultEvalWindow,
|
evalWindow: defaultEvalWindow,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sq: StagedQuery = prepareStagedQuery(
|
||||||
|
val,
|
||||||
|
queryBuilderData.queryData,
|
||||||
|
queryBuilderData.queryFormulas,
|
||||||
|
promQueries,
|
||||||
|
chQueries,
|
||||||
|
);
|
||||||
|
setManualStagedQuery(sq);
|
||||||
};
|
};
|
||||||
const { notifications } = useNotifications();
|
const { notifications } = useNotifications();
|
||||||
|
|
||||||
@ -244,10 +219,9 @@ function FormAlertRules({
|
|||||||
}, [t, chQueries, queryCategory, notifications]);
|
}, [t, chQueries, queryCategory, notifications]);
|
||||||
|
|
||||||
const validateQBParams = useCallback((): boolean => {
|
const validateQBParams = useCallback((): boolean => {
|
||||||
let retval = true;
|
|
||||||
if (queryCategory !== EQueryType.QUERY_BUILDER) return true;
|
if (queryCategory !== EQueryType.QUERY_BUILDER) return true;
|
||||||
|
|
||||||
if (!metricQueries || Object.keys(metricQueries).length === 0) {
|
if (!queryBuilderData.queryData || queryBuilderData.queryData.length === 0) {
|
||||||
notifications.error({
|
notifications.error({
|
||||||
message: 'Error',
|
message: 'Error',
|
||||||
description: t('condition_required'),
|
description: t('condition_required'),
|
||||||
@ -263,27 +237,8 @@ function FormAlertRules({
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(metricQueries).forEach((key) => {
|
return true;
|
||||||
if (metricQueries[key].metricName === '') {
|
}, [t, alertDef, queryCategory, queryBuilderData, notifications]);
|
||||||
notifications.error({
|
|
||||||
message: 'Error',
|
|
||||||
description: t('metricname_missing', { where: metricQueries[key].name }),
|
|
||||||
});
|
|
||||||
retval = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(formulaQueries).forEach((key) => {
|
|
||||||
if (formulaQueries[key].expression === '') {
|
|
||||||
notifications.error({
|
|
||||||
message: 'Error',
|
|
||||||
description: t('expression_missing', formulaQueries[key].name),
|
|
||||||
});
|
|
||||||
retval = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return retval;
|
|
||||||
}, [t, alertDef, queryCategory, metricQueries, formulaQueries, notifications]);
|
|
||||||
|
|
||||||
const isFormValid = useCallback((): boolean => {
|
const isFormValid = useCallback((): boolean => {
|
||||||
if (!alertDef.alert || alertDef.alert === '') {
|
if (!alertDef.alert || alertDef.alert === '') {
|
||||||
@ -321,11 +276,12 @@ function FormAlertRules({
|
|||||||
queryCategory === EQueryType.PROM ? 'promql_rule' : 'threshold_rule',
|
queryCategory === EQueryType.PROM ? 'promql_rule' : 'threshold_rule',
|
||||||
condition: {
|
condition: {
|
||||||
...alertDef.condition,
|
...alertDef.condition,
|
||||||
compositeMetricQuery: {
|
compositeQuery: {
|
||||||
builderQueries: prepareBuilderQueries(metricQueries, formulaQueries),
|
builderQueries: mapQueryDataToApi(queryBuilderData).data,
|
||||||
promQueries,
|
promQueries,
|
||||||
chQueries,
|
chQueries,
|
||||||
queryType: queryCategory,
|
queryType: queryCategory,
|
||||||
|
panelType: initQuery.panelType,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -335,11 +291,11 @@ function FormAlertRules({
|
|||||||
const memoizedPreparePostData = useCallback(preparePostData, [
|
const memoizedPreparePostData = useCallback(preparePostData, [
|
||||||
queryCategory,
|
queryCategory,
|
||||||
alertDef,
|
alertDef,
|
||||||
metricQueries,
|
queryBuilderData,
|
||||||
formulaQueries,
|
|
||||||
promQueries,
|
promQueries,
|
||||||
chQueries,
|
chQueries,
|
||||||
alertType,
|
alertType,
|
||||||
|
initQuery,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const saveRule = useCallback(async () => {
|
const saveRule = useCallback(async () => {
|
||||||
@ -458,7 +414,7 @@ function FormAlertRules({
|
|||||||
headline={<PlotTag queryType={queryCategory} />}
|
headline={<PlotTag queryType={queryCategory} />}
|
||||||
name=""
|
name=""
|
||||||
threshold={alertDef.condition?.target}
|
threshold={alertDef.condition?.target}
|
||||||
query={debouncedStagedQuery}
|
query={manualStagedQuery}
|
||||||
selectedInterval={toChartInterval(alertDef.evalWindow)}
|
selectedInterval={toChartInterval(alertDef.evalWindow)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -468,7 +424,7 @@ function FormAlertRules({
|
|||||||
headline={<PlotTag queryType={queryCategory} />}
|
headline={<PlotTag queryType={queryCategory} />}
|
||||||
name="Chart Preview"
|
name="Chart Preview"
|
||||||
threshold={alertDef.condition?.target}
|
threshold={alertDef.condition?.target}
|
||||||
query={debouncedStagedQuery}
|
query={manualStagedQuery}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -478,7 +434,6 @@ function FormAlertRules({
|
|||||||
name="Chart Preview"
|
name="Chart Preview"
|
||||||
threshold={alertDef.condition?.target}
|
threshold={alertDef.condition?.target}
|
||||||
query={manualStagedQuery}
|
query={manualStagedQuery}
|
||||||
userQueryKey={runQueryId}
|
|
||||||
selectedInterval={toChartInterval(alertDef.evalWindow)}
|
selectedInterval={toChartInterval(alertDef.evalWindow)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -498,10 +453,6 @@ function FormAlertRules({
|
|||||||
<QuerySection
|
<QuerySection
|
||||||
queryCategory={queryCategory}
|
queryCategory={queryCategory}
|
||||||
setQueryCategory={onQueryCategoryChange}
|
setQueryCategory={onQueryCategoryChange}
|
||||||
metricQueries={metricQueries}
|
|
||||||
setMetricQueries={setMetricQueries}
|
|
||||||
formulaQueries={formulaQueries}
|
|
||||||
setFormulaQueries={setFormulaQueries}
|
|
||||||
promQueries={promQueries}
|
promQueries={promQueries}
|
||||||
setPromQueries={setPromQueries}
|
setPromQueries={setPromQueries}
|
||||||
chQueries={chQueries}
|
chQueries={chQueries}
|
||||||
|
@ -82,7 +82,6 @@ export const InputSmall = styled(Input)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const FormContainer = styled(Card)`
|
export const FormContainer = styled(Card)`
|
||||||
padding: 2em;
|
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -1,105 +1,27 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// @ts-ignore
|
|
||||||
// @ts-nocheck
|
|
||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import {
|
import {
|
||||||
IBuilderQueries,
|
|
||||||
IChQueries,
|
IChQueries,
|
||||||
IChQuery,
|
IChQuery,
|
||||||
IFormulaQueries,
|
|
||||||
IFormulaQuery,
|
|
||||||
IMetricQueries,
|
|
||||||
IMetricQuery,
|
|
||||||
IPromQueries,
|
IPromQueries,
|
||||||
IPromQuery,
|
IPromQuery,
|
||||||
} from 'types/api/alerts/compositeQuery';
|
} from 'types/api/alerts/compositeQuery';
|
||||||
|
import { Query as IStagedQuery } from 'types/api/dashboard/getAll';
|
||||||
import {
|
import {
|
||||||
IMetricsBuilderQuery,
|
IBuilderFormula,
|
||||||
Query as IStagedQuery,
|
IBuilderQuery,
|
||||||
} from 'types/api/dashboard/getAll';
|
} from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { EQueryType } from 'types/common/dashboard';
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
|
|
||||||
export const toFormulaQueries = (b: IBuilderQueries): IFormulaQueries => {
|
|
||||||
const f: IFormulaQueries = {};
|
|
||||||
if (!b) return f;
|
|
||||||
Object.keys(b).forEach((key) => {
|
|
||||||
if (key === 'F1') {
|
|
||||||
f[key] = b[key] as IFormulaQuery;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return f;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const toMetricQueries = (b: IBuilderQueries): IMetricQueries => {
|
|
||||||
const m: IMetricQueries = {};
|
|
||||||
if (!b) return m;
|
|
||||||
Object.keys(b).forEach((key) => {
|
|
||||||
if (key !== 'F1') {
|
|
||||||
m[key] = b[key] as IMetricQuery;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return m;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const toIMetricsBuilderQuery = (
|
|
||||||
q: IMetricQuery,
|
|
||||||
): IMetricsBuilderQuery => ({
|
|
||||||
name: q.name,
|
|
||||||
metricName: q.metricName,
|
|
||||||
tagFilters: q.tagFilters,
|
|
||||||
groupBy: q.groupBy,
|
|
||||||
aggregateOperator: q.aggregateOperator,
|
|
||||||
disabled: q.disabled,
|
|
||||||
legend: q.legend,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const prepareBuilderQueries = (
|
|
||||||
m: IMetricQueries,
|
|
||||||
f: IFormulaQueries,
|
|
||||||
): IBuilderQueries => {
|
|
||||||
if (!m) return {};
|
|
||||||
const b: IBuilderQueries = {
|
|
||||||
...m,
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.keys(f).forEach((key) => {
|
|
||||||
b[key] = {
|
|
||||||
...f[key],
|
|
||||||
aggregateOperator: undefined,
|
|
||||||
metricName: '',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return b;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const prepareStagedQuery = (
|
export const prepareStagedQuery = (
|
||||||
t: EQueryType,
|
t: EQueryType,
|
||||||
m: IMetricQueries,
|
m: IBuilderQuery[],
|
||||||
f: IFormulaQueries,
|
f: IBuilderFormula[],
|
||||||
p: IPromQueries,
|
p: IPromQueries,
|
||||||
c: IChQueries,
|
c: IChQueries,
|
||||||
): IStagedQuery => {
|
): IStagedQuery => {
|
||||||
const qbList: IMetricQuery[] = [];
|
|
||||||
const formulaList: IFormulaQuery[] = [];
|
|
||||||
const promList: IPromQuery[] = [];
|
const promList: IPromQuery[] = [];
|
||||||
const chQueryList: IChQuery[] = [];
|
const chQueryList: IChQuery[] = [];
|
||||||
|
|
||||||
// convert map[string]IMetricQuery to IMetricQuery[]
|
|
||||||
if (m) {
|
|
||||||
Object.keys(m).forEach((key) => {
|
|
||||||
qbList.push(m[key]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert map[string]IFormulaQuery to IFormulaQuery[]
|
|
||||||
if (f) {
|
|
||||||
Object.keys(f).forEach((key) => {
|
|
||||||
formulaList.push(f[key]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert map[string]IPromQuery to IPromQuery[]
|
// convert map[string]IPromQuery to IPromQuery[]
|
||||||
if (p) {
|
if (p) {
|
||||||
Object.keys(p).forEach((key) => {
|
Object.keys(p).forEach((key) => {
|
||||||
@ -115,13 +37,12 @@ export const prepareStagedQuery = (
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
queryType: t,
|
queryType: t,
|
||||||
promQL: promList,
|
promql: promList,
|
||||||
// TODO: change it later to actual builder
|
builder: {
|
||||||
metricsBuilder: {
|
queryFormulas: f,
|
||||||
formulas: formulaList,
|
queryData: m,
|
||||||
queryBuilder: qbList,
|
|
||||||
},
|
},
|
||||||
clickHouse: chQueryList,
|
clickhouse_sql: chQueryList,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,13 +42,13 @@ export const UpdateDashboard = async (
|
|||||||
panelTypes: graphType,
|
panelTypes: graphType,
|
||||||
query: {
|
query: {
|
||||||
queryType: EQueryType.QUERY_BUILDER,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
promQL: [
|
promql: [
|
||||||
{
|
{
|
||||||
name: GetQueryName([]) || '',
|
name: GetQueryName([]) || '',
|
||||||
...PromQLQueryTemplate,
|
...PromQLQueryTemplate,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
clickHouse: [
|
clickhouse_sql: [
|
||||||
{
|
{
|
||||||
name: GetQueryName([]) || '',
|
name: GetQueryName([]) || '',
|
||||||
...ClickHouseQueryTemplate,
|
...ClickHouseQueryTemplate,
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import {
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
IMetricsBuilderFormula,
|
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
IMetricsBuilderQuery,
|
import { QueryBuilderData } from 'types/common/queryBuilder';
|
||||||
IQueryBuilderTagFilterItems,
|
|
||||||
} from 'types/api/dashboard/getAll';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getQueryBuilderQueries,
|
getQueryBuilderQueries,
|
||||||
@ -13,16 +11,25 @@ export const databaseCallsRPS = ({
|
|||||||
servicename,
|
servicename,
|
||||||
legend,
|
legend,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}: DatabaseCallsRPSProps): {
|
}: DatabaseCallsRPSProps): QueryBuilderData => {
|
||||||
formulas: IMetricsBuilderFormula[];
|
const metricName: BaseAutocompleteData = {
|
||||||
queryBuilder: IMetricsBuilderQuery[];
|
dataType: 'float64',
|
||||||
} => {
|
isColumn: true,
|
||||||
const metricName = 'signoz_db_latency_count';
|
key: 'signoz_db_latency_count',
|
||||||
const groupBy = ['db_system'];
|
type: null,
|
||||||
const itemsA = [
|
};
|
||||||
|
const groupBy: BaseAutocompleteData[] = [
|
||||||
|
{ dataType: 'string', isColumn: false, key: 'db_system', type: 'tag' },
|
||||||
|
];
|
||||||
|
const itemsA: TagFilterItem[] = [
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'service_name',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'service_name',
|
||||||
|
type: 'resource',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: [`${servicename}`],
|
value: [`${servicename}`],
|
||||||
},
|
},
|
||||||
@ -40,20 +47,32 @@ export const databaseCallsRPS = ({
|
|||||||
export const databaseCallsAvgDuration = ({
|
export const databaseCallsAvgDuration = ({
|
||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}: DatabaseCallProps): {
|
}: DatabaseCallProps): QueryBuilderData => {
|
||||||
formulas: IMetricsBuilderFormula[];
|
const metricNameA: BaseAutocompleteData = {
|
||||||
queryBuilder: IMetricsBuilderQuery[];
|
dataType: 'float64',
|
||||||
} => {
|
isColumn: true,
|
||||||
const metricNameA = 'signoz_db_latency_sum';
|
key: 'signoz_db_latency_sum',
|
||||||
const metricNameB = 'signoz_db_latency_count';
|
type: null,
|
||||||
|
};
|
||||||
|
const metricNameB: BaseAutocompleteData = {
|
||||||
|
dataType: 'float64',
|
||||||
|
isColumn: true,
|
||||||
|
key: 'signoz_db_latency_count',
|
||||||
|
type: null,
|
||||||
|
};
|
||||||
const expression = 'A/B';
|
const expression = 'A/B';
|
||||||
const legendFormula = 'Average Duration';
|
const legendFormula = 'Average Duration';
|
||||||
const legend = '';
|
const legend = '';
|
||||||
const disabled = true;
|
const disabled = true;
|
||||||
const additionalItemsA = [
|
const additionalItemsA: TagFilterItem[] = [
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'service_name',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'service_name',
|
||||||
|
type: 'resource',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: [`${servicename}`],
|
value: [`${servicename}`],
|
||||||
},
|
},
|
||||||
@ -79,5 +98,5 @@ interface DatabaseCallsRPSProps extends DatabaseCallProps {
|
|||||||
|
|
||||||
interface DatabaseCallProps {
|
interface DatabaseCallProps {
|
||||||
servicename: string | undefined;
|
servicename: string | undefined;
|
||||||
tagFilterItems: IQueryBuilderTagFilterItems[] | [];
|
tagFilterItems: TagFilterItem[];
|
||||||
}
|
}
|
||||||
|
@ -1,45 +1,67 @@
|
|||||||
import {
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
IMetricsBuilderFormula,
|
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
IMetricsBuilderQuery,
|
import { QueryBuilderData } from 'types/common/queryBuilder';
|
||||||
IQueryBuilderTagFilterItems,
|
|
||||||
} from 'types/api/dashboard/getAll';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getQueryBuilderQueries,
|
getQueryBuilderQueries,
|
||||||
getQueryBuilderQuerieswithFormula,
|
getQueryBuilderQuerieswithFormula,
|
||||||
} from './MetricsPageQueriesFactory';
|
} from './MetricsPageQueriesFactory';
|
||||||
|
|
||||||
const groupBy = ['address'];
|
const groupBy: BaseAutocompleteData[] = [
|
||||||
|
{ dataType: 'string', isColumn: false, key: 'address', type: 'tag' },
|
||||||
|
];
|
||||||
|
|
||||||
export const externalCallErrorPercent = ({
|
export const externalCallErrorPercent = ({
|
||||||
servicename,
|
servicename,
|
||||||
legend,
|
legend,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}: ExternalCallDurationByAddressProps): {
|
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
|
||||||
formulas: IMetricsBuilderFormula[];
|
const metricNameA: BaseAutocompleteData = {
|
||||||
queryBuilder: IMetricsBuilderQuery[];
|
dataType: 'float64',
|
||||||
} => {
|
isColumn: true,
|
||||||
const metricNameA = 'signoz_external_call_latency_count';
|
key: 'signoz_external_call_latency_count',
|
||||||
const metricNameB = 'signoz_external_call_latency_count';
|
type: null,
|
||||||
const additionalItemsA = [
|
};
|
||||||
|
const metricNameB: BaseAutocompleteData = {
|
||||||
|
dataType: 'float64',
|
||||||
|
isColumn: true,
|
||||||
|
key: 'signoz_external_call_latency_count',
|
||||||
|
type: null,
|
||||||
|
};
|
||||||
|
const additionalItemsA: TagFilterItem[] = [
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'service_name',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'service_name',
|
||||||
|
type: 'resource',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: [`${servicename}`],
|
value: [`${servicename}`],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'status_code',
|
key: {
|
||||||
|
dataType: 'int64',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'status_code',
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: ['STATUS_CODE_ERROR'],
|
value: ['STATUS_CODE_ERROR'],
|
||||||
},
|
},
|
||||||
...tagFilterItems,
|
...tagFilterItems,
|
||||||
];
|
];
|
||||||
const additionalItemsB = [
|
const additionalItemsB: TagFilterItem[] = [
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'service_name',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'service_name',
|
||||||
|
type: 'resource',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: [`${servicename}`],
|
value: [`${servicename}`],
|
||||||
},
|
},
|
||||||
@ -64,20 +86,32 @@ export const externalCallErrorPercent = ({
|
|||||||
export const externalCallDuration = ({
|
export const externalCallDuration = ({
|
||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}: ExternalCallProps): {
|
}: ExternalCallProps): QueryBuilderData => {
|
||||||
formulas: IMetricsBuilderFormula[];
|
const metricNameA: BaseAutocompleteData = {
|
||||||
queryBuilder: IMetricsBuilderQuery[];
|
dataType: 'float64',
|
||||||
} => {
|
isColumn: true,
|
||||||
const metricNameA = 'signoz_external_call_latency_sum';
|
key: 'signoz_external_call_latency_sum',
|
||||||
const metricNameB = 'signoz_external_call_latency_count';
|
type: null,
|
||||||
|
};
|
||||||
|
const metricNameB: BaseAutocompleteData = {
|
||||||
|
dataType: 'float64',
|
||||||
|
isColumn: true,
|
||||||
|
key: 'signoz_external_call_latency_count',
|
||||||
|
type: null,
|
||||||
|
};
|
||||||
const expression = 'A/B';
|
const expression = 'A/B';
|
||||||
const legendFormula = 'Average Duration';
|
const legendFormula = 'Average Duration';
|
||||||
const legend = '';
|
const legend = '';
|
||||||
const disabled = true;
|
const disabled = true;
|
||||||
const additionalItemsA = [
|
const additionalItemsA: TagFilterItem[] = [
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'service_name',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'service_name',
|
||||||
|
type: 'resource',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: [`${servicename}`],
|
value: [`${servicename}`],
|
||||||
},
|
},
|
||||||
@ -101,15 +135,22 @@ export const externalCallRpsByAddress = ({
|
|||||||
servicename,
|
servicename,
|
||||||
legend,
|
legend,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}: ExternalCallDurationByAddressProps): {
|
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
|
||||||
formulas: IMetricsBuilderFormula[];
|
const metricName: BaseAutocompleteData = {
|
||||||
queryBuilder: IMetricsBuilderQuery[];
|
dataType: 'float64',
|
||||||
} => {
|
isColumn: true,
|
||||||
const metricName = 'signoz_external_call_latency_count';
|
key: 'signoz_external_call_latency_count',
|
||||||
const itemsA = [
|
type: null,
|
||||||
|
};
|
||||||
|
const itemsA: TagFilterItem[] = [
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'service_name',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'service_name',
|
||||||
|
type: 'resource',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: [`${servicename}`],
|
value: [`${servicename}`],
|
||||||
},
|
},
|
||||||
@ -127,19 +168,31 @@ export const externalCallDurationByAddress = ({
|
|||||||
servicename,
|
servicename,
|
||||||
legend,
|
legend,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}: ExternalCallDurationByAddressProps): {
|
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
|
||||||
formulas: IMetricsBuilderFormula[];
|
const metricNameA: BaseAutocompleteData = {
|
||||||
queryBuilder: IMetricsBuilderQuery[];
|
dataType: 'float64',
|
||||||
} => {
|
isColumn: true,
|
||||||
const metricNameA = 'signoz_external_call_latency_sum';
|
key: 'signoz_external_call_latency_sum',
|
||||||
const metricNameB = 'signoz_external_call_latency_count';
|
type: null,
|
||||||
|
};
|
||||||
|
const metricNameB: BaseAutocompleteData = {
|
||||||
|
dataType: 'float64',
|
||||||
|
isColumn: true,
|
||||||
|
key: 'signoz_external_call_latency_count',
|
||||||
|
type: null,
|
||||||
|
};
|
||||||
const expression = 'A/B';
|
const expression = 'A/B';
|
||||||
const legendFormula = legend;
|
const legendFormula = legend;
|
||||||
const disabled = true;
|
const disabled = true;
|
||||||
const additionalItemsA = [
|
const additionalItemsA: TagFilterItem[] = [
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'service_name',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'service_name',
|
||||||
|
type: 'resource',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: [`${servicename}`],
|
value: [`${servicename}`],
|
||||||
},
|
},
|
||||||
@ -166,5 +219,5 @@ interface ExternalCallDurationByAddressProps extends ExternalCallProps {
|
|||||||
|
|
||||||
export interface ExternalCallProps {
|
export interface ExternalCallProps {
|
||||||
servicename: string | undefined;
|
servicename: string | undefined;
|
||||||
tagFilterItems: IQueryBuilderTagFilterItems[];
|
tagFilterItems: TagFilterItem[];
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,30 @@
|
|||||||
import {
|
import {
|
||||||
IMetricsBuilderFormula,
|
initialFormulaBuilderFormValues,
|
||||||
IMetricsBuilderQuery,
|
initialQueryBuilderFormValues,
|
||||||
IQueryBuilderTagFilterItems,
|
} from 'constants/queryBuilder';
|
||||||
} from 'types/api/dashboard/getAll';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
|
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
import {
|
||||||
|
MetricAggregateOperator,
|
||||||
|
QueryBuilderData,
|
||||||
|
} from 'types/common/queryBuilder';
|
||||||
|
|
||||||
export const getQueryBuilderQueries = ({
|
export const getQueryBuilderQueries = ({
|
||||||
metricName,
|
metricName,
|
||||||
groupBy,
|
groupBy = [],
|
||||||
legend,
|
legend,
|
||||||
itemsA,
|
itemsA,
|
||||||
}: BuilderQueriesProps): {
|
}: BuilderQueriesProps): QueryBuilderData => ({
|
||||||
formulas: IMetricsBuilderFormula[];
|
queryFormulas: [],
|
||||||
queryBuilder: IMetricsBuilderQuery[];
|
queryData: [
|
||||||
} => ({
|
|
||||||
formulas: [],
|
|
||||||
queryBuilder: [
|
|
||||||
{
|
{
|
||||||
aggregateOperator: 18,
|
...initialQueryBuilderFormValues,
|
||||||
|
aggregateOperator: MetricAggregateOperator.SUM_RATE,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
groupBy,
|
groupBy,
|
||||||
|
aggregateAttribute: metricName,
|
||||||
legend,
|
legend,
|
||||||
metricName,
|
reduceTo: 'sum',
|
||||||
name: 'A',
|
|
||||||
reduceTo: 1,
|
|
||||||
tagFilters: {
|
tagFilters: {
|
||||||
items: itemsA,
|
items: itemsA,
|
||||||
op: 'AND',
|
op: 'AND',
|
||||||
@ -37,44 +39,42 @@ export const getQueryBuilderQuerieswithFormula = ({
|
|||||||
additionalItemsA,
|
additionalItemsA,
|
||||||
additionalItemsB,
|
additionalItemsB,
|
||||||
legend,
|
legend,
|
||||||
groupBy,
|
groupBy = [],
|
||||||
disabled,
|
disabled,
|
||||||
expression,
|
expression,
|
||||||
legendFormula,
|
legendFormula,
|
||||||
}: BuilderQuerieswithFormulaProps): {
|
}: BuilderQuerieswithFormulaProps): QueryBuilderData => ({
|
||||||
formulas: IMetricsBuilderFormula[];
|
queryFormulas: [
|
||||||
queryBuilder: IMetricsBuilderQuery[];
|
|
||||||
} => ({
|
|
||||||
formulas: [
|
|
||||||
{
|
{
|
||||||
disabled: false,
|
...initialFormulaBuilderFormValues,
|
||||||
expression,
|
expression,
|
||||||
name: 'F1',
|
|
||||||
legend: legendFormula,
|
legend: legendFormula,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
queryBuilder: [
|
queryData: [
|
||||||
{
|
{
|
||||||
aggregateOperator: 18,
|
...initialQueryBuilderFormValues,
|
||||||
|
aggregateOperator: MetricAggregateOperator.SUM_RATE,
|
||||||
disabled,
|
disabled,
|
||||||
groupBy,
|
groupBy,
|
||||||
legend,
|
legend,
|
||||||
metricName: metricNameA,
|
aggregateAttribute: metricNameA,
|
||||||
name: 'A',
|
reduceTo: 'sum',
|
||||||
reduceTo: 1,
|
|
||||||
tagFilters: {
|
tagFilters: {
|
||||||
items: additionalItemsA,
|
items: additionalItemsA,
|
||||||
op: 'AND',
|
op: 'AND',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
aggregateOperator: 18,
|
...initialQueryBuilderFormValues,
|
||||||
|
aggregateOperator: MetricAggregateOperator.SUM_RATE,
|
||||||
disabled,
|
disabled,
|
||||||
groupBy,
|
groupBy,
|
||||||
legend,
|
legend,
|
||||||
metricName: metricNameB,
|
aggregateAttribute: metricNameB,
|
||||||
name: 'B',
|
queryName: 'B',
|
||||||
reduceTo: 1,
|
expression: 'B',
|
||||||
|
reduceTo: 'sum',
|
||||||
tagFilters: {
|
tagFilters: {
|
||||||
items: additionalItemsB,
|
items: additionalItemsB,
|
||||||
op: 'AND',
|
op: 'AND',
|
||||||
@ -84,20 +84,20 @@ export const getQueryBuilderQuerieswithFormula = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
interface BuilderQueriesProps {
|
interface BuilderQueriesProps {
|
||||||
metricName: string;
|
metricName: BaseAutocompleteData;
|
||||||
groupBy?: string[];
|
groupBy?: BaseAutocompleteData[];
|
||||||
legend: string;
|
legend: string;
|
||||||
itemsA: IQueryBuilderTagFilterItems[];
|
itemsA: TagFilterItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BuilderQuerieswithFormulaProps {
|
interface BuilderQuerieswithFormulaProps {
|
||||||
metricNameA: string;
|
metricNameA: BaseAutocompleteData;
|
||||||
metricNameB: string;
|
metricNameB: BaseAutocompleteData;
|
||||||
legend: string;
|
legend: string;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
groupBy?: string[];
|
groupBy?: BaseAutocompleteData[];
|
||||||
expression: string;
|
expression: string;
|
||||||
legendFormula: string;
|
legendFormula: string;
|
||||||
additionalItemsA: IQueryBuilderTagFilterItems[];
|
additionalItemsA: TagFilterItem[];
|
||||||
additionalItemsB: IQueryBuilderTagFilterItems[];
|
additionalItemsB: TagFilterItem[];
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import {
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
IMetricsBuilderFormula,
|
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
IMetricsBuilderQuery,
|
import { QueryBuilderData } from 'types/common/queryBuilder';
|
||||||
IQueryBuilderTagFilterItems,
|
|
||||||
} from 'types/api/dashboard/getAll';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getQueryBuilderQueries,
|
getQueryBuilderQueries,
|
||||||
@ -13,19 +11,35 @@ export const operationPerSec = ({
|
|||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
topLevelOperations,
|
topLevelOperations,
|
||||||
}: OperationPerSecProps): IOverviewQueries => {
|
}: OperationPerSecProps): QueryBuilderData => {
|
||||||
const metricName = 'signoz_latency_count';
|
const metricName: BaseAutocompleteData = {
|
||||||
|
dataType: 'float64',
|
||||||
|
isColumn: true,
|
||||||
|
key: 'signoz_latency_count',
|
||||||
|
type: null,
|
||||||
|
};
|
||||||
const legend = 'Operations';
|
const legend = 'Operations';
|
||||||
const itemsA = [
|
|
||||||
|
const itemsA: TagFilterItem[] = [
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'service_name',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'service_name',
|
||||||
|
type: 'resource',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: [`${servicename}`],
|
value: [`${servicename}`],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'operation',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'operation',
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: topLevelOperations,
|
value: topLevelOperations,
|
||||||
},
|
},
|
||||||
@ -43,41 +57,76 @@ export const errorPercentage = ({
|
|||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
topLevelOperations,
|
topLevelOperations,
|
||||||
}: OperationPerSecProps): IOverviewQueries => {
|
}: OperationPerSecProps): QueryBuilderData => {
|
||||||
const metricNameA = 'signoz_calls_total';
|
const metricNameA: BaseAutocompleteData = {
|
||||||
const metricNameB = 'signoz_calls_total';
|
dataType: 'float64',
|
||||||
const additionalItemsA = [
|
isColumn: true,
|
||||||
|
key: 'signoz_calls_total',
|
||||||
|
type: null,
|
||||||
|
};
|
||||||
|
const metricNameB: BaseAutocompleteData = {
|
||||||
|
dataType: 'float64',
|
||||||
|
isColumn: true,
|
||||||
|
key: 'signoz_calls_total',
|
||||||
|
type: null,
|
||||||
|
};
|
||||||
|
const additionalItemsA: TagFilterItem[] = [
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'service_name',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'service_name',
|
||||||
|
type: 'resource',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: [`${servicename}`],
|
value: [`${servicename}`],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'operation',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'operation',
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: topLevelOperations,
|
value: topLevelOperations,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'status_code',
|
key: {
|
||||||
|
dataType: 'int64',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'status_code',
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: ['STATUS_CODE_ERROR'],
|
value: ['STATUS_CODE_ERROR'],
|
||||||
},
|
},
|
||||||
...tagFilterItems,
|
...tagFilterItems,
|
||||||
];
|
];
|
||||||
|
|
||||||
const additionalItemsB = [
|
const additionalItemsB: TagFilterItem[] = [
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'service_name',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'service_name',
|
||||||
|
type: 'resource',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: [`${servicename}`],
|
value: [`${servicename}`],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '',
|
id: '',
|
||||||
key: 'operation',
|
key: {
|
||||||
|
dataType: 'string',
|
||||||
|
isColumn: false,
|
||||||
|
key: 'operation',
|
||||||
|
type: 'tag',
|
||||||
|
},
|
||||||
op: 'IN',
|
op: 'IN',
|
||||||
value: topLevelOperations,
|
value: topLevelOperations,
|
||||||
},
|
},
|
||||||
@ -102,11 +151,6 @@ export const errorPercentage = ({
|
|||||||
|
|
||||||
export interface OperationPerSecProps {
|
export interface OperationPerSecProps {
|
||||||
servicename: string | undefined;
|
servicename: string | undefined;
|
||||||
tagFilterItems: IQueryBuilderTagFilterItems[];
|
tagFilterItems: TagFilterItem[];
|
||||||
topLevelOperations: string[];
|
topLevelOperations: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IOverviewQueries {
|
|
||||||
formulas: IMetricsBuilderFormula[];
|
|
||||||
queryBuilder: IMetricsBuilderQuery[];
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// @ts-nocheck
|
|
||||||
import { Col } from 'antd';
|
import { Col } from 'antd';
|
||||||
import FullView from 'container/GridGraphLayout/Graph/FullView/index.metricsBuilder';
|
import FullView from 'container/GridGraphLayout/Graph/FullView/index.metricsBuilder';
|
||||||
import {
|
import {
|
||||||
@ -14,6 +12,8 @@ import {
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { Widgets } from 'types/api/dashboard/getAll';
|
import { Widgets } from 'types/api/dashboard/getAll';
|
||||||
|
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
|
|
||||||
import { Card, GraphContainer, GraphTitle, Row } from '../styles';
|
import { Card, GraphContainer, GraphTitle, Row } from '../styles';
|
||||||
import { Button } from './styles';
|
import { Button } from './styles';
|
||||||
@ -29,7 +29,7 @@ function DBCall({ getWidgetQueryBuilder }: DBCallProps): JSX.Element {
|
|||||||
const [selectedTimeStamp, setSelectedTimeStamp] = useState<number>(0);
|
const [selectedTimeStamp, setSelectedTimeStamp] = useState<number>(0);
|
||||||
const { queries } = useResourceAttribute();
|
const { queries } = useResourceAttribute();
|
||||||
|
|
||||||
const tagFilterItems = useMemo(
|
const tagFilterItems: TagFilterItem[] = useMemo(
|
||||||
() =>
|
() =>
|
||||||
handleNonInQueryRange(resourceAttributesToTagFilterItems(queries)) || [],
|
handleNonInQueryRange(resourceAttributesToTagFilterItems(queries)) || [],
|
||||||
[queries],
|
[queries],
|
||||||
@ -48,29 +48,27 @@ function DBCall({ getWidgetQueryBuilder }: DBCallProps): JSX.Element {
|
|||||||
const databaseCallsRPSWidget = useMemo(
|
const databaseCallsRPSWidget = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getWidgetQueryBuilder({
|
getWidgetQueryBuilder({
|
||||||
queryType: 1,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
promQL: [],
|
promql: [],
|
||||||
// TODO: change it later to actual builder
|
builder: databaseCallsRPS({
|
||||||
metricsBuilder: databaseCallsRPS({
|
|
||||||
servicename,
|
servicename,
|
||||||
legend,
|
legend,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}),
|
}),
|
||||||
clickHouse: [],
|
clickhouse_sql: [],
|
||||||
}),
|
}),
|
||||||
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
||||||
);
|
);
|
||||||
const databaseCallsAverageDurationWidget = useMemo(
|
const databaseCallsAverageDurationWidget = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getWidgetQueryBuilder({
|
getWidgetQueryBuilder({
|
||||||
queryType: 1,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
promQL: [],
|
promql: [],
|
||||||
// TODO: change it later to actual builder
|
builder: databaseCallsAvgDuration({
|
||||||
metricsBuilder: databaseCallsAvgDuration({
|
|
||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}),
|
}),
|
||||||
clickHouse: [],
|
clickhouse_sql: [],
|
||||||
}),
|
}),
|
||||||
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// @ts-nocheck
|
|
||||||
import { Col } from 'antd';
|
import { Col } from 'antd';
|
||||||
import FullView from 'container/GridGraphLayout/Graph/FullView/index.metricsBuilder';
|
import FullView from 'container/GridGraphLayout/Graph/FullView/index.metricsBuilder';
|
||||||
import {
|
import {
|
||||||
@ -16,6 +14,7 @@ import {
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { Widgets } from 'types/api/dashboard/getAll';
|
import { Widgets } from 'types/api/dashboard/getAll';
|
||||||
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
|
|
||||||
import { Card, GraphContainer, GraphTitle, Row } from '../styles';
|
import { Card, GraphContainer, GraphTitle, Row } from '../styles';
|
||||||
import { legend } from './constant';
|
import { legend } from './constant';
|
||||||
@ -41,15 +40,14 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
|||||||
const externalCallErrorWidget = useMemo(
|
const externalCallErrorWidget = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getWidgetQueryBuilder({
|
getWidgetQueryBuilder({
|
||||||
queryType: 1,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
promQL: [],
|
promql: [],
|
||||||
// TODO: change it later to actual builder
|
builder: externalCallErrorPercent({
|
||||||
metricsBuilder: externalCallErrorPercent({
|
|
||||||
servicename,
|
servicename,
|
||||||
legend: legend.address,
|
legend: legend.address,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}),
|
}),
|
||||||
clickHouse: [],
|
clickhouse_sql: [],
|
||||||
}),
|
}),
|
||||||
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
||||||
);
|
);
|
||||||
@ -62,14 +60,13 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
|||||||
const externalCallDurationWidget = useMemo(
|
const externalCallDurationWidget = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getWidgetQueryBuilder({
|
getWidgetQueryBuilder({
|
||||||
queryType: 1,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
promQL: [],
|
promql: [],
|
||||||
// TODO: change it later to actual builder
|
builder: externalCallDuration({
|
||||||
metricsBuilder: externalCallDuration({
|
|
||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}),
|
}),
|
||||||
clickHouse: [],
|
clickhouse_sql: [],
|
||||||
}),
|
}),
|
||||||
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
||||||
);
|
);
|
||||||
@ -77,15 +74,14 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
|||||||
const externalCallRPSWidget = useMemo(
|
const externalCallRPSWidget = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getWidgetQueryBuilder({
|
getWidgetQueryBuilder({
|
||||||
queryType: 1,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
promQL: [],
|
promql: [],
|
||||||
// TODO: change it later to actual builder
|
builder: externalCallRpsByAddress({
|
||||||
metricsBuilder: externalCallRpsByAddress({
|
|
||||||
servicename,
|
servicename,
|
||||||
legend: legend.address,
|
legend: legend.address,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}),
|
}),
|
||||||
clickHouse: [],
|
clickhouse_sql: [],
|
||||||
}),
|
}),
|
||||||
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
||||||
);
|
);
|
||||||
@ -93,15 +89,14 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
|||||||
const externalCallDurationAddressWidget = useMemo(
|
const externalCallDurationAddressWidget = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getWidgetQueryBuilder({
|
getWidgetQueryBuilder({
|
||||||
queryType: 1,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
promQL: [],
|
promql: [],
|
||||||
// TODO: change it later to actual builder
|
builder: externalCallDurationByAddress({
|
||||||
metricsBuilder: externalCallDurationByAddress({
|
|
||||||
servicename,
|
servicename,
|
||||||
legend: legend.address,
|
legend: legend.address,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
}),
|
}),
|
||||||
clickHouse: [],
|
clickhouse_sql: [],
|
||||||
}),
|
}),
|
||||||
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// @ts-nocheck
|
|
||||||
import { ActiveElement, Chart, ChartData, ChartEvent } from 'chart.js';
|
import { ActiveElement, Chart, ChartData, ChartEvent } from 'chart.js';
|
||||||
import Graph from 'components/Graph';
|
import Graph from 'components/Graph';
|
||||||
import { QueryParams } from 'constants/query';
|
import { QueryParams } from 'constants/query';
|
||||||
@ -21,6 +19,7 @@ import { useLocation, useParams } from 'react-router-dom';
|
|||||||
import { UpdateTimeInterval } from 'store/actions';
|
import { UpdateTimeInterval } from 'store/actions';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import { Widgets } from 'types/api/dashboard/getAll';
|
import { Widgets } from 'types/api/dashboard/getAll';
|
||||||
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
import MetricReducer from 'types/reducer/metrics';
|
import MetricReducer from 'types/reducer/metrics';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -84,15 +83,14 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
|||||||
const operationPerSecWidget = useMemo(
|
const operationPerSecWidget = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getWidgetQueryBuilder({
|
getWidgetQueryBuilder({
|
||||||
queryType: 1,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
promQL: [],
|
promql: [],
|
||||||
// TODO: change it later to actual builder
|
builder: operationPerSec({
|
||||||
metricsBuilder: operationPerSec({
|
|
||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
topLevelOperations,
|
topLevelOperations,
|
||||||
}),
|
}),
|
||||||
clickHouse: [],
|
clickhouse_sql: [],
|
||||||
}),
|
}),
|
||||||
[getWidgetQueryBuilder, servicename, topLevelOperations, tagFilterItems],
|
[getWidgetQueryBuilder, servicename, topLevelOperations, tagFilterItems],
|
||||||
);
|
);
|
||||||
@ -100,15 +98,14 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
|||||||
const errorPercentageWidget = useMemo(
|
const errorPercentageWidget = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getWidgetQueryBuilder({
|
getWidgetQueryBuilder({
|
||||||
queryType: 1,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
promQL: [],
|
promql: [],
|
||||||
// TODO: change it later to actual builder
|
builder: errorPercentage({
|
||||||
metricsBuilder: errorPercentage({
|
|
||||||
servicename,
|
servicename,
|
||||||
tagFilterItems,
|
tagFilterItems,
|
||||||
topLevelOperations,
|
topLevelOperations,
|
||||||
}),
|
}),
|
||||||
clickHouse: [],
|
clickhouse_sql: [],
|
||||||
}),
|
}),
|
||||||
[servicename, topLevelOperations, tagFilterItems, getWidgetQueryBuilder],
|
[servicename, topLevelOperations, tagFilterItems, getWidgetQueryBuilder],
|
||||||
);
|
);
|
||||||
|
@ -4,7 +4,7 @@ import ROUTES from 'constants/routes';
|
|||||||
import { routeConfig } from 'container/SideNav/config';
|
import { routeConfig } from 'container/SideNav/config';
|
||||||
import { getQueryString } from 'container/SideNav/helper';
|
import { getQueryString } from 'container/SideNav/helper';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
import { IQueryBuilderTagFilterItems } from 'types/api/dashboard/getAll';
|
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { Tags } from 'types/reducer/trace';
|
import { Tags } from 'types/reducer/trace';
|
||||||
|
|
||||||
export const dbSystemTags: Tags[] = [
|
export const dbSystemTags: Tags[] = [
|
||||||
@ -90,9 +90,7 @@ export function onGraphClickHandler(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const handleNonInQueryRange = (
|
export const handleNonInQueryRange = (tags: TagFilterItem[]): TagFilterItem[] =>
|
||||||
tags: IQueryBuilderTagFilterItems[],
|
|
||||||
): IQueryBuilderTagFilterItems[] =>
|
|
||||||
tags.map((tag) => {
|
tags.map((tag) => {
|
||||||
if (tag.op === 'Not IN') {
|
if (tag.op === 'Not IN') {
|
||||||
return {
|
return {
|
||||||
|
@ -13,7 +13,7 @@ import { IClickHouseQueryHandleChange } from './types';
|
|||||||
interface IClickHouseQueryContainerProps {
|
interface IClickHouseQueryContainerProps {
|
||||||
queryData: Query;
|
queryData: Query;
|
||||||
updateQueryData: (args: IHandleUpdatedQuery) => void;
|
updateQueryData: (args: IHandleUpdatedQuery) => void;
|
||||||
clickHouseQueries: Query['clickHouse'];
|
clickHouseQueries: Query['clickhouse_sql'];
|
||||||
}
|
}
|
||||||
function ClickHouseQueryContainer({
|
function ClickHouseQueryContainer({
|
||||||
queryData,
|
queryData,
|
||||||
|
@ -69,8 +69,6 @@ function MetricsBuilder({
|
|||||||
});
|
});
|
||||||
}, [metricName]);
|
}, [metricName]);
|
||||||
|
|
||||||
// TODO: rewrite to Form component from antd
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<QueryHeader
|
<QueryHeader
|
||||||
name={queryData.name}
|
name={queryData.name}
|
||||||
|
@ -1,21 +1,12 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// TODO: fix it after merge actual functionality
|
|
||||||
// @ts-nocheck
|
|
||||||
import { Query } from 'types/api/dashboard/getAll';
|
import { Query } from 'types/api/dashboard/getAll';
|
||||||
|
|
||||||
import {
|
import { WIDGET_QUERY_BUILDER_QUERY_KEY_NAME } from '../../constants';
|
||||||
WIDGET_QUERY_BUILDER_FORMULA_KEY_NAME,
|
|
||||||
WIDGET_QUERY_BUILDER_QUERY_KEY_NAME,
|
|
||||||
} from '../../constants';
|
|
||||||
|
|
||||||
const QUERY_AND_FORMULA_LIMIT = 10;
|
const QUERY_AND_FORMULA_LIMIT = 10;
|
||||||
|
|
||||||
export const canCreateQueryAndFormula = (query: Query): boolean => {
|
export const canCreateQueryAndFormula = (query: Query): boolean => {
|
||||||
const queries = query[WIDGET_QUERY_BUILDER_QUERY_KEY_NAME].queryBuilder;
|
const queries = query[WIDGET_QUERY_BUILDER_QUERY_KEY_NAME].queryData;
|
||||||
const formulas =
|
const formulas = query[WIDGET_QUERY_BUILDER_QUERY_KEY_NAME].queryFormulas;
|
||||||
query[WIDGET_QUERY_BUILDER_QUERY_KEY_NAME][
|
|
||||||
WIDGET_QUERY_BUILDER_FORMULA_KEY_NAME
|
|
||||||
];
|
|
||||||
|
|
||||||
return queries.length + formulas.length < QUERY_AND_FORMULA_LIMIT;
|
return queries.length + formulas.length < QUERY_AND_FORMULA_LIMIT;
|
||||||
};
|
};
|
||||||
|
@ -1,21 +1,10 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// @ts-ignore
|
|
||||||
// @ts-nocheck
|
|
||||||
|
|
||||||
import { EQueryType } from 'types/common/dashboard';
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
|
|
||||||
import { EQueryTypeToQueryKeyMapping } from './types';
|
export const WIDGET_PROMQL_QUERY_KEY_NAME = EQueryType.PROM;
|
||||||
|
|
||||||
export const WIDGET_PROMQL_QUERY_KEY_NAME: EQueryTypeToQueryKeyMapping.PROM =
|
export const WIDGET_CLICKHOUSE_QUERY_KEY_NAME = EQueryType.CLICKHOUSE;
|
||||||
EQueryTypeToQueryKeyMapping[EQueryType[EQueryType.PROM]];
|
|
||||||
|
|
||||||
export const WIDGET_CLICKHOUSE_QUERY_KEY_NAME: EQueryTypeToQueryKeyMapping.CLICKHOUSE = EQueryTypeToQueryKeyMapping[
|
export const WIDGET_QUERY_BUILDER_QUERY_KEY_NAME = EQueryType.QUERY_BUILDER;
|
||||||
EQueryType[EQueryType.CLICKHOUSE]
|
|
||||||
] as string;
|
|
||||||
|
|
||||||
export const WIDGET_QUERY_BUILDER_QUERY_KEY_NAME: EQueryTypeToQueryKeyMapping.QUERY_BUILDER = EQueryTypeToQueryKeyMapping[
|
|
||||||
EQueryType[EQueryType.QUERY_BUILDER]
|
|
||||||
] as string;
|
|
||||||
|
|
||||||
type TFormulas = 'formulas';
|
type TFormulas = 'formulas';
|
||||||
export const WIDGET_QUERY_BUILDER_FORMULA_KEY_NAME: TFormulas = 'formulas';
|
export const WIDGET_QUERY_BUILDER_FORMULA_KEY_NAME: TFormulas = 'formulas';
|
||||||
|
@ -30,7 +30,6 @@ import ClickHouseQueryContainer from './QueryBuilder/clickHouse';
|
|||||||
import PromQLQueryContainer from './QueryBuilder/promQL';
|
import PromQLQueryContainer from './QueryBuilder/promQL';
|
||||||
import TabHeader from './TabHeader';
|
import TabHeader from './TabHeader';
|
||||||
import { IHandleUpdatedQuery } from './types';
|
import { IHandleUpdatedQuery } from './types';
|
||||||
import { getQueryKey } from './utils/getQueryKey';
|
|
||||||
import { showUnstagedStashConfirmBox } from './utils/userSettings';
|
import { showUnstagedStashConfirmBox } from './utils/userSettings';
|
||||||
|
|
||||||
function QuerySection({
|
function QuerySection({
|
||||||
@ -76,15 +75,10 @@ function QuerySection({
|
|||||||
queryA: Query,
|
queryA: Query,
|
||||||
queryB: Query,
|
queryB: Query,
|
||||||
queryCategory: EQueryType,
|
queryCategory: EQueryType,
|
||||||
): boolean => {
|
): boolean => !isEqual(queryA[queryCategory], queryB[queryCategory]);
|
||||||
const keyOfConcern = getQueryKey(queryCategory);
|
|
||||||
return !isEqual(queryA[keyOfConcern], queryB[keyOfConcern]);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleUnstagedChanges(
|
handleUnstagedChanges(queryDiff(query, localQueryChanges, queryCategory));
|
||||||
queryDiff(query, localQueryChanges, parseInt(`${queryCategory}`, 10)),
|
|
||||||
);
|
|
||||||
}, [handleUnstagedChanges, localQueryChanges, query, queryCategory]);
|
}, [handleUnstagedChanges, localQueryChanges, query, queryCategory]);
|
||||||
|
|
||||||
const regenRctKeys = (): void => {
|
const regenRctKeys = (): void => {
|
||||||
@ -111,11 +105,7 @@ function QuerySection({
|
|||||||
|
|
||||||
const handleQueryCategoryChange = (qCategory: string): void => {
|
const handleQueryCategoryChange = (qCategory: string): void => {
|
||||||
// If true, then it means that the user has made some changes and haven't staged them
|
// If true, then it means that the user has made some changes and haven't staged them
|
||||||
const unstagedChanges = queryDiff(
|
const unstagedChanges = queryDiff(query, localQueryChanges, queryCategory);
|
||||||
query,
|
|
||||||
localQueryChanges,
|
|
||||||
parseInt(`${queryCategory}`, 10),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (unstagedChanges && showUnstagedStashConfirmBox()) {
|
if (unstagedChanges && showUnstagedStashConfirmBox()) {
|
||||||
// eslint-disable-next-line no-alert
|
// eslint-disable-next-line no-alert
|
||||||
@ -125,10 +115,10 @@ function QuerySection({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setQueryCategory(parseInt(`${qCategory}`, 10));
|
setQueryCategory(qCategory as EQueryType);
|
||||||
const newLocalQuery = {
|
const newLocalQuery = {
|
||||||
...cloneDeep(query),
|
...cloneDeep(query),
|
||||||
queryType: parseInt(`${qCategory}`, 10),
|
queryType: qCategory as EQueryType,
|
||||||
};
|
};
|
||||||
setLocalQueryChanges(newLocalQuery);
|
setLocalQueryChanges(newLocalQuery);
|
||||||
regenRctKeys();
|
regenRctKeys();
|
||||||
@ -147,7 +137,7 @@ function QuerySection({
|
|||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
key: EQueryType.QUERY_BUILDER.toString(),
|
key: EQueryType.QUERY_BUILDER,
|
||||||
label: 'Query Builder',
|
label: 'Query Builder',
|
||||||
tab: (
|
tab: (
|
||||||
<TabHeader
|
<TabHeader
|
||||||
@ -162,7 +152,7 @@ function QuerySection({
|
|||||||
children: <QueryBuilder panelType={selectedGraph} />,
|
children: <QueryBuilder panelType={selectedGraph} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: EQueryType.CLICKHOUSE.toString(),
|
key: EQueryType.CLICKHOUSE,
|
||||||
label: 'ClickHouse Query',
|
label: 'ClickHouse Query',
|
||||||
tab: (
|
tab: (
|
||||||
<TabHeader
|
<TabHeader
|
||||||
@ -186,7 +176,7 @@ function QuerySection({
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: EQueryType.PROM.toString(),
|
key: EQueryType.PROM,
|
||||||
label: 'PromQL',
|
label: 'PromQL',
|
||||||
tab: (
|
tab: (
|
||||||
<TabHeader
|
<TabHeader
|
||||||
@ -213,8 +203,8 @@ function QuerySection({
|
|||||||
<Tabs
|
<Tabs
|
||||||
type="card"
|
type="card"
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
defaultActiveKey={queryCategory.toString()}
|
defaultActiveKey={queryCategory}
|
||||||
activeKey={queryCategory.toString()}
|
activeKey={queryCategory}
|
||||||
onChange={handleQueryCategoryChange}
|
onChange={handleQueryCategoryChange}
|
||||||
tabBarExtraContent={
|
tabBarExtraContent={
|
||||||
<span style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
<span style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
||||||
|
@ -1,19 +1,5 @@
|
|||||||
import { Query } from 'types/api/dashboard/getAll';
|
import { Query } from 'types/api/dashboard/getAll';
|
||||||
|
|
||||||
export type TQueryCategories = 'query_builder' | 'clickhouse_query' | 'promql';
|
|
||||||
|
|
||||||
export enum EQueryCategories {
|
|
||||||
query_builder = 0,
|
|
||||||
clickhouse_query,
|
|
||||||
promql,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum EQueryTypeToQueryKeyMapping {
|
|
||||||
QUERY_BUILDER = 'builder',
|
|
||||||
CLICKHOUSE = 'clickHouse',
|
|
||||||
PROM = 'promQL',
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IHandleUpdatedQuery {
|
export interface IHandleUpdatedQuery {
|
||||||
updatedQuery: Query;
|
updatedQuery: Query;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
import { EQueryType } from 'types/common/dashboard';
|
|
||||||
|
|
||||||
import { EQueryTypeToQueryKeyMapping } from '../types';
|
|
||||||
|
|
||||||
export const getQueryKey = (
|
|
||||||
queryCategory: EQueryType,
|
|
||||||
): EQueryTypeToQueryKeyMapping =>
|
|
||||||
EQueryTypeToQueryKeyMapping[
|
|
||||||
EQueryType[queryCategory] as keyof typeof EQueryTypeToQueryKeyMapping
|
|
||||||
];
|
|
@ -19,26 +19,27 @@ export const QueryBuilder = memo(function QueryBuilder({
|
|||||||
const {
|
const {
|
||||||
queryBuilderData,
|
queryBuilderData,
|
||||||
setupInitialDataSource,
|
setupInitialDataSource,
|
||||||
resetQueryBuilderData,
|
resetQueryBuilderInfo,
|
||||||
addNewQuery,
|
addNewQuery,
|
||||||
addNewFormula,
|
addNewFormula,
|
||||||
|
handleSetPanelType,
|
||||||
} = useQueryBuilder();
|
} = useQueryBuilder();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (config && config.queryVariant === 'static') {
|
if (config && config.queryVariant === 'static') {
|
||||||
setupInitialDataSource(config.initialDataSource);
|
setupInitialDataSource(config.initialDataSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (): void => {
|
|
||||||
setupInitialDataSource(null);
|
|
||||||
};
|
|
||||||
}, [config, setupInitialDataSource]);
|
}, [config, setupInitialDataSource]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleSetPanelType(panelType);
|
||||||
|
}, [handleSetPanelType, panelType]);
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() => (): void => {
|
() => (): void => {
|
||||||
resetQueryBuilderData();
|
resetQueryBuilderInfo();
|
||||||
},
|
},
|
||||||
[resetQueryBuilderData],
|
[resetQueryBuilderInfo],
|
||||||
);
|
);
|
||||||
|
|
||||||
const isDisabledQueryButton = useMemo(
|
const isDisabledQueryButton = useMemo(
|
||||||
@ -51,6 +52,13 @@ export const QueryBuilder = memo(function QueryBuilder({
|
|||||||
[queryBuilderData],
|
[queryBuilderData],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isAvailableToDisableQuery = useMemo(
|
||||||
|
() =>
|
||||||
|
queryBuilderData.queryData.length > 1 ||
|
||||||
|
queryBuilderData.queryFormulas.length > 0,
|
||||||
|
[queryBuilderData],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row gutter={[0, 20]} justify="start">
|
<Row gutter={[0, 20]} justify="start">
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
@ -59,10 +67,9 @@ export const QueryBuilder = memo(function QueryBuilder({
|
|||||||
<Col key={query.queryName} span={24}>
|
<Col key={query.queryName} span={24}>
|
||||||
<Query
|
<Query
|
||||||
index={index}
|
index={index}
|
||||||
isAvailableToDisable={queryBuilderData.queryData.length > 1}
|
isAvailableToDisable={isAvailableToDisableQuery}
|
||||||
queryVariant={config?.queryVariant || 'dropdown'}
|
queryVariant={config?.queryVariant || 'dropdown'}
|
||||||
query={query}
|
query={query}
|
||||||
panelType={panelType}
|
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
))}
|
))}
|
||||||
|
@ -3,7 +3,7 @@ import styled from 'styled-components';
|
|||||||
export const StyledLabel = styled.div`
|
export const StyledLabel = styled.div`
|
||||||
padding: 0 0.6875rem;
|
padding: 0 0.6875rem;
|
||||||
min-height: 2rem;
|
min-height: 2rem;
|
||||||
width: 100%;
|
min-width: 5.625rem;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -7,7 +7,6 @@ export const StyledButton = styled(Button)<{ $isAvailableToDisable: boolean }>`
|
|||||||
padding: ${(props): string =>
|
padding: ${(props): string =>
|
||||||
props.$isAvailableToDisable ? '0.43rem' : '0.43rem 0.68rem'};
|
props.$isAvailableToDisable ? '0.43rem' : '0.43rem 0.68rem'};
|
||||||
border-radius: 0.375rem;
|
border-radius: 0.375rem;
|
||||||
margin-right: 0.5rem;
|
|
||||||
pointer-events: ${(props): string =>
|
pointer-events: ${(props): string =>
|
||||||
props.$isAvailableToDisable ? 'default' : 'none'};
|
props.$isAvailableToDisable ? 'default' : 'none'};
|
||||||
`;
|
`;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { ITEMS } from 'container/NewDashboard/ComponentsSlider/menuItems';
|
|
||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
export type QueryProps = {
|
export type QueryProps = {
|
||||||
@ -6,5 +5,4 @@ export type QueryProps = {
|
|||||||
isAvailableToDisable: boolean;
|
isAvailableToDisable: boolean;
|
||||||
query: IBuilderQuery;
|
query: IBuilderQuery;
|
||||||
queryVariant: 'static' | 'dropdown';
|
queryVariant: 'static' | 'dropdown';
|
||||||
panelType: ITEMS;
|
|
||||||
};
|
};
|
||||||
|
@ -20,6 +20,7 @@ import AggregateEveryFilter from 'container/QueryBuilder/filters/AggregateEveryF
|
|||||||
import LimitFilter from 'container/QueryBuilder/filters/LimitFilter/LimitFilter';
|
import LimitFilter from 'container/QueryBuilder/filters/LimitFilter/LimitFilter';
|
||||||
import { OrderByFilter } from 'container/QueryBuilder/filters/OrderByFilter';
|
import { OrderByFilter } from 'container/QueryBuilder/filters/OrderByFilter';
|
||||||
import QueryBuilderSearch from 'container/QueryBuilder/filters/QueryBuilderSearch';
|
import QueryBuilderSearch from 'container/QueryBuilder/filters/QueryBuilderSearch';
|
||||||
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
import { useQueryOperations } from 'hooks/queryBuilder/useQueryOperations';
|
import { useQueryOperations } from 'hooks/queryBuilder/useQueryOperations';
|
||||||
// ** Hooks
|
// ** Hooks
|
||||||
import React, { ChangeEvent, memo, ReactNode, useCallback } from 'react';
|
import React, { ChangeEvent, memo, ReactNode, useCallback } from 'react';
|
||||||
@ -34,8 +35,8 @@ export const Query = memo(function Query({
|
|||||||
isAvailableToDisable,
|
isAvailableToDisable,
|
||||||
queryVariant,
|
queryVariant,
|
||||||
query,
|
query,
|
||||||
panelType,
|
|
||||||
}: QueryProps): JSX.Element {
|
}: QueryProps): JSX.Element {
|
||||||
|
const { panelType } = useQueryBuilder();
|
||||||
const {
|
const {
|
||||||
operators,
|
operators,
|
||||||
isMetricsDataSource,
|
isMetricsDataSource,
|
||||||
@ -45,7 +46,7 @@ export const Query = memo(function Query({
|
|||||||
handleChangeQueryData,
|
handleChangeQueryData,
|
||||||
handleChangeOperator,
|
handleChangeOperator,
|
||||||
handleDeleteQuery,
|
handleDeleteQuery,
|
||||||
} = useQueryOperations({ index, query, panelType });
|
} = useQueryOperations({ index, query });
|
||||||
|
|
||||||
const handleChangeAggregateEvery = useCallback(
|
const handleChangeAggregateEvery = useCallback(
|
||||||
(value: IBuilderQuery['stepInterval']) => {
|
(value: IBuilderQuery['stepInterval']) => {
|
||||||
@ -211,7 +212,7 @@ export const Query = memo(function Query({
|
|||||||
return (
|
return (
|
||||||
<ListItemWrapper onDelete={handleDeleteQuery}>
|
<ListItemWrapper onDelete={handleDeleteQuery}>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Row align="middle">
|
<Row align="middle" gutter={[5, 11]}>
|
||||||
<Col>
|
<Col>
|
||||||
<ListMarker
|
<ListMarker
|
||||||
isDisabled={query.disabled}
|
isDisabled={query.disabled}
|
||||||
@ -220,17 +221,19 @@ export const Query = memo(function Query({
|
|||||||
index={index}
|
index={index}
|
||||||
isAvailableToDisable={isAvailableToDisable}
|
isAvailableToDisable={isAvailableToDisable}
|
||||||
/>
|
/>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
{queryVariant === 'dropdown' ? (
|
{queryVariant === 'dropdown' ? (
|
||||||
<DataSourceDropdown
|
<DataSourceDropdown
|
||||||
onChange={handleChangeDataSource}
|
onChange={handleChangeDataSource}
|
||||||
value={query.dataSource}
|
value={query.dataSource}
|
||||||
style={{ marginRight: '0.5rem', minWidth: '5.625rem' }}
|
style={{ minWidth: '5.625rem' }}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<FilterLabel label={transformToUpperCase(query.dataSource)} />
|
<FilterLabel label={transformToUpperCase(query.dataSource)} />
|
||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
<Col flex="1">
|
<Col flex="1 1 20rem">
|
||||||
<Row gutter={[11, 5]}>
|
<Row gutter={[11, 5]}>
|
||||||
{isMetricsDataSource && (
|
{isMetricsDataSource && (
|
||||||
<Col>
|
<Col>
|
||||||
|
@ -3,11 +3,12 @@ import { AutoComplete, Spin } from 'antd';
|
|||||||
// ** Api
|
// ** Api
|
||||||
import { getAggregateAttribute } from 'api/queryBuilder/getAggregateAttribute';
|
import { getAggregateAttribute } from 'api/queryBuilder/getAggregateAttribute';
|
||||||
import { initialAggregateAttribute } from 'constants/queryBuilder';
|
import { initialAggregateAttribute } from 'constants/queryBuilder';
|
||||||
|
import { getFilterObjectValue } from 'lib/newQueryBuilder/getFilterObjectValue';
|
||||||
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
|
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
|
||||||
import React, { memo, useMemo, useState } from 'react';
|
import React, { memo, useMemo, useState } from 'react';
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
import { SelectOption } from 'types/common/select';
|
import { ExtendedSelectOption } from 'types/common/select';
|
||||||
import { transformToUpperCase } from 'utils/transformToUpperCase';
|
import { transformToUpperCase } from 'utils/transformToUpperCase';
|
||||||
|
|
||||||
import { selectStyle } from '../QueryBuilderSearch/config';
|
import { selectStyle } from '../QueryBuilderSearch/config';
|
||||||
@ -36,23 +37,35 @@ export const AggregatorFilter = memo(function AggregatorFilter({
|
|||||||
{ enabled: !!query.aggregateOperator && !!query.dataSource },
|
{ enabled: !!query.aggregateOperator && !!query.dataSource },
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSearchAttribute = (searchText: string): void =>
|
const handleSearchAttribute = (searchText: string): void => {
|
||||||
setSearchText(searchText);
|
const { key } = getFilterObjectValue(searchText);
|
||||||
|
setSearchText(key);
|
||||||
|
};
|
||||||
|
|
||||||
const optionsData: SelectOption<string, string>[] =
|
const optionsData: ExtendedSelectOption[] =
|
||||||
data?.payload?.attributeKeys?.map((item) => ({
|
data?.payload?.attributeKeys?.map((item) => ({
|
||||||
label: transformStringWithPrefix({
|
label: transformStringWithPrefix({
|
||||||
str: item.key,
|
str: item.key,
|
||||||
prefix: item.type || '',
|
prefix: item.type || '',
|
||||||
condition: !item.isColumn,
|
condition: !item.isColumn,
|
||||||
}),
|
}),
|
||||||
value: item.key,
|
value: transformStringWithPrefix({
|
||||||
|
str: item.key,
|
||||||
|
prefix: item.type || '',
|
||||||
|
condition: !item.isColumn,
|
||||||
|
}),
|
||||||
|
key: transformStringWithPrefix({
|
||||||
|
str: item.key,
|
||||||
|
prefix: item.type || '',
|
||||||
|
condition: !item.isColumn,
|
||||||
|
}),
|
||||||
})) || [];
|
})) || [];
|
||||||
|
|
||||||
const handleChangeAttribute = (value: string): void => {
|
const handleChangeAttribute = (value: string): void => {
|
||||||
|
const { key, isColumn } = getFilterObjectValue(value);
|
||||||
const currentAttributeObj = data?.payload?.attributeKeys?.find(
|
const currentAttributeObj = data?.payload?.attributeKeys?.find(
|
||||||
(item) => item.key === value,
|
(item) => item.key === key && isColumn === item.isColumn,
|
||||||
) || { ...initialAggregateAttribute, key: value };
|
) || { ...initialAggregateAttribute, key };
|
||||||
|
|
||||||
setSearchText('');
|
setSearchText('');
|
||||||
onChange(currentAttributeObj);
|
onChange(currentAttributeObj);
|
||||||
|
@ -6,11 +6,3 @@ export type GroupByFilterProps = {
|
|||||||
onChange: (values: BaseAutocompleteData[]) => void;
|
onChange: (values: BaseAutocompleteData[]) => void;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GroupByFilterValue = {
|
|
||||||
disabled: boolean | undefined;
|
|
||||||
key: string;
|
|
||||||
label: string;
|
|
||||||
title: string | undefined;
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
|
@ -2,19 +2,17 @@ import { Select, Spin } from 'antd';
|
|||||||
import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys';
|
import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys';
|
||||||
// ** Constants
|
// ** Constants
|
||||||
import { QueryBuilderKeys } from 'constants/queryBuilder';
|
import { QueryBuilderKeys } from 'constants/queryBuilder';
|
||||||
|
import { getFilterObjectValue } from 'lib/newQueryBuilder/getFilterObjectValue';
|
||||||
// ** Components
|
// ** Components
|
||||||
// ** Helpers
|
// ** Helpers
|
||||||
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
|
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
|
||||||
import React, { memo, useState } from 'react';
|
import React, { memo, useMemo, useState } from 'react';
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { SelectOption } from 'types/common/select';
|
import { ExtendedSelectOption } from 'types/common/select';
|
||||||
|
|
||||||
import { selectStyle } from '../QueryBuilderSearch/config';
|
import { selectStyle } from '../QueryBuilderSearch/config';
|
||||||
import {
|
import { GroupByFilterProps } from './GroupByFilter.interfaces';
|
||||||
GroupByFilterProps,
|
|
||||||
GroupByFilterValue,
|
|
||||||
} from './GroupByFilter.interfaces';
|
|
||||||
|
|
||||||
export const GroupByFilter = memo(function GroupByFilter({
|
export const GroupByFilter = memo(function GroupByFilter({
|
||||||
query,
|
query,
|
||||||
@ -48,28 +46,44 @@ export const GroupByFilter = memo(function GroupByFilter({
|
|||||||
setIsFocused(true);
|
setIsFocused(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const optionsData: SelectOption<string, string>[] =
|
const optionsData: ExtendedSelectOption[] = useMemo(() => {
|
||||||
data?.payload?.attributeKeys?.map((item) => ({
|
if (data && data.payload && data.payload.attributeKeys) {
|
||||||
label: transformStringWithPrefix({
|
return data.payload.attributeKeys.map((item) => ({
|
||||||
str: item.key,
|
label: transformStringWithPrefix({
|
||||||
prefix: item.type || '',
|
str: item.key,
|
||||||
condition: !item.isColumn,
|
prefix: item.type || '',
|
||||||
}),
|
condition: !item.isColumn,
|
||||||
value: item.key,
|
}),
|
||||||
})) || [];
|
value: transformStringWithPrefix({
|
||||||
|
str: item.key,
|
||||||
|
prefix: item.type || '',
|
||||||
|
condition: !item.isColumn,
|
||||||
|
}),
|
||||||
|
key: transformStringWithPrefix({
|
||||||
|
str: item.key,
|
||||||
|
prefix: item.type || '',
|
||||||
|
condition: !item.isColumn,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
const handleChange = (values: GroupByFilterValue[]): void => {
|
return [];
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
const handleChange = (values: ExtendedSelectOption[]): void => {
|
||||||
const groupByValues: BaseAutocompleteData[] = values.map((item) => {
|
const groupByValues: BaseAutocompleteData[] = values.map((item) => {
|
||||||
const responseKeys = data?.payload?.attributeKeys || [];
|
const responseKeys = data?.payload?.attributeKeys || [];
|
||||||
|
const { key, isColumn } = getFilterObjectValue(item.value);
|
||||||
|
|
||||||
const existGroupResponse = responseKeys.find(
|
const existGroupResponse = responseKeys.find(
|
||||||
(group) => group.key === item.value,
|
(group) => group.key === key && group.isColumn === isColumn,
|
||||||
);
|
);
|
||||||
if (existGroupResponse) {
|
if (existGroupResponse) {
|
||||||
return existGroupResponse;
|
return existGroupResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
const existGroupQuery = query.groupBy.find(
|
const existGroupQuery = query.groupBy.find(
|
||||||
(group) => group.key === item.value,
|
(group) => group.key === key && group.isColumn === isColumn,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (existGroupQuery) {
|
if (existGroupQuery) {
|
||||||
@ -78,7 +92,7 @@ export const GroupByFilter = memo(function GroupByFilter({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
isColumn: null,
|
isColumn: null,
|
||||||
key: item.value,
|
key,
|
||||||
dataType: null,
|
dataType: null,
|
||||||
type: null,
|
type: null,
|
||||||
};
|
};
|
||||||
@ -88,16 +102,22 @@ export const GroupByFilter = memo(function GroupByFilter({
|
|||||||
onChange(groupByValues);
|
onChange(groupByValues);
|
||||||
};
|
};
|
||||||
|
|
||||||
const values: GroupByFilterValue[] = query.groupBy.map((item) => ({
|
const values: ExtendedSelectOption[] = query.groupBy.map((item) => ({
|
||||||
label: transformStringWithPrefix({
|
label: transformStringWithPrefix({
|
||||||
str: item.key,
|
str: item.key,
|
||||||
prefix: item.type || '',
|
prefix: item.type || '',
|
||||||
condition: !item.isColumn,
|
condition: !item.isColumn,
|
||||||
}),
|
}),
|
||||||
key: item.key,
|
key: transformStringWithPrefix({
|
||||||
value: item.key,
|
str: item.key,
|
||||||
disabled: undefined,
|
prefix: item.type || '',
|
||||||
title: undefined,
|
condition: !item.isColumn,
|
||||||
|
}),
|
||||||
|
value: transformStringWithPrefix({
|
||||||
|
str: item.key,
|
||||||
|
prefix: item.type || '',
|
||||||
|
condition: !item.isColumn,
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -110,8 +130,8 @@ export const GroupByFilter = memo(function GroupByFilter({
|
|||||||
showArrow={false}
|
showArrow={false}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
onFocus={onFocus}
|
onFocus={onFocus}
|
||||||
filterOption={false}
|
|
||||||
options={optionsData}
|
options={optionsData}
|
||||||
|
filterOption={false}
|
||||||
labelInValue
|
labelInValue
|
||||||
value={values}
|
value={values}
|
||||||
notFoundContent={isFetching ? <Spin size="small" /> : null}
|
notFoundContent={isFetching ? <Spin size="small" /> : null}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Select } from 'antd';
|
import { Select } from 'antd';
|
||||||
// ** Constants
|
// ** Constants
|
||||||
import { HAVING_OPERATORS, initialHavingValues } from 'constants/queryBuilder';
|
import { HAVING_OPERATORS, initialHavingValues } from 'constants/queryBuilder';
|
||||||
|
import { HAVING_FILTER_REGEXP } from 'constants/regExp';
|
||||||
import { HavingFilterTag } from 'container/QueryBuilder/components';
|
import { HavingFilterTag } from 'container/QueryBuilder/components';
|
||||||
import { HavingTagRenderProps } from 'container/QueryBuilder/components/HavingFilterTag/HavingFilterTag.interfaces';
|
import { HavingTagRenderProps } from 'container/QueryBuilder/components/HavingFilterTag/HavingFilterTag.interfaces';
|
||||||
// ** Hooks
|
// ** Hooks
|
||||||
@ -101,9 +102,7 @@ export function HavingFilter({
|
|||||||
const values = getHavingObject(search).value.join(' ');
|
const values = getHavingObject(search).value.join(' ');
|
||||||
|
|
||||||
if (values) {
|
if (values) {
|
||||||
const numRegexp = /^[-\d.,\s]+$/;
|
return HAVING_FILTER_REGEXP.test(values);
|
||||||
|
|
||||||
return numRegexp.test(values);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -75,10 +75,13 @@ function QueryBuilderSearch({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initialTagFilters: TagFilter = { items: [], op: 'AND' };
|
const initialTagFilters: TagFilter = { items: [], op: 'AND' };
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
initialTagFilters.items = tags.map((tag) => {
|
initialTagFilters.items = tags.map((tag) => {
|
||||||
const [tagKey, tagOperator, ...tagValue] = tag.split(' ');
|
const [tagKey, tagOperator, ...tagValue] = tag.split(' ');
|
||||||
return {
|
return {
|
||||||
id: uuid().slice(0, 8),
|
id: uuid().slice(0, 8),
|
||||||
|
// TODO: key should be fixed by Chintan Sudani
|
||||||
key: tagKey,
|
key: tagKey,
|
||||||
op: tagOperator,
|
op: tagOperator,
|
||||||
value: tagValue.map((i) => i.replace(',', '')),
|
value: tagValue.map((i) => i.replace(',', '')),
|
||||||
|
@ -2,11 +2,9 @@ import {
|
|||||||
initialAggregateAttribute,
|
initialAggregateAttribute,
|
||||||
initialQueryBuilderFormValues,
|
initialQueryBuilderFormValues,
|
||||||
mapOfFilters,
|
mapOfFilters,
|
||||||
mapOfOperators,
|
|
||||||
PANEL_TYPES,
|
|
||||||
} from 'constants/queryBuilder';
|
} from 'constants/queryBuilder';
|
||||||
import { ITEMS } from 'container/NewDashboard/ComponentsSlider/menuItems';
|
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
|
import { getOperatorsBySourceAndPanelType } from 'lib/newQueryBuilder/getOperatorsBySourceAndPanelType';
|
||||||
import { findDataTypeOfOperator } from 'lib/query/findDataTypeOfOperator';
|
import { findDataTypeOfOperator } from 'lib/query/findDataTypeOfOperator';
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
@ -15,14 +13,14 @@ import {
|
|||||||
HandleChangeQueryData,
|
HandleChangeQueryData,
|
||||||
UseQueryOperations,
|
UseQueryOperations,
|
||||||
} from 'types/common/operations.types';
|
} from 'types/common/operations.types';
|
||||||
import { DataSource, StringOperators } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
export const useQueryOperations: UseQueryOperations = ({
|
export const useQueryOperations: UseQueryOperations = ({ query, index }) => {
|
||||||
query,
|
const {
|
||||||
index,
|
handleSetQueryData,
|
||||||
panelType,
|
removeEntityByIndex,
|
||||||
}) => {
|
panelType,
|
||||||
const { handleSetQueryData, removeEntityByIndex } = useQueryBuilder();
|
} = useQueryBuilder();
|
||||||
const [operators, setOperators] = useState<string[]>([]);
|
const [operators, setOperators] = useState<string[]>([]);
|
||||||
const [listOfAdditionalFilters, setListOfAdditionalFilters] = useState<
|
const [listOfAdditionalFilters, setListOfAdditionalFilters] = useState<
|
||||||
string[]
|
string[]
|
||||||
@ -57,24 +55,6 @@ export const useQueryOperations: UseQueryOperations = ({
|
|||||||
[index, query, handleSetQueryData],
|
[index, query, handleSetQueryData],
|
||||||
);
|
);
|
||||||
|
|
||||||
const getNewOperators = useCallback(
|
|
||||||
(dataSource: DataSource, currentPanelType: ITEMS): string[] => {
|
|
||||||
let operatorsByDataSource = mapOfOperators[dataSource];
|
|
||||||
|
|
||||||
if (
|
|
||||||
dataSource !== DataSource.METRICS &&
|
|
||||||
currentPanelType !== PANEL_TYPES.LIST
|
|
||||||
) {
|
|
||||||
operatorsByDataSource = operatorsByDataSource.filter(
|
|
||||||
(operator) => operator !== StringOperators.NOOP,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return operatorsByDataSource;
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const getNewListOfAdditionalFilters = useCallback(
|
const getNewListOfAdditionalFilters = useCallback(
|
||||||
(dataSource: DataSource): string[] =>
|
(dataSource: DataSource): string[] =>
|
||||||
mapOfFilters[dataSource].map((item) => item.text),
|
mapOfFilters[dataSource].map((item) => item.text),
|
||||||
@ -96,7 +76,10 @@ export const useQueryOperations: UseQueryOperations = ({
|
|||||||
|
|
||||||
const handleChangeDataSource = useCallback(
|
const handleChangeDataSource = useCallback(
|
||||||
(nextSource: DataSource): void => {
|
(nextSource: DataSource): void => {
|
||||||
const newOperators = getNewOperators(nextSource, panelType);
|
const newOperators = getOperatorsBySourceAndPanelType({
|
||||||
|
dataSource: nextSource,
|
||||||
|
panelType,
|
||||||
|
});
|
||||||
|
|
||||||
const entries = Object.entries(initialQueryBuilderFormValues).filter(
|
const entries = Object.entries(initialQueryBuilderFormValues).filter(
|
||||||
([key]) => key !== 'queryName' && key !== 'expression',
|
([key]) => key !== 'queryName' && key !== 'expression',
|
||||||
@ -114,7 +97,7 @@ export const useQueryOperations: UseQueryOperations = ({
|
|||||||
setOperators(newOperators);
|
setOperators(newOperators);
|
||||||
handleSetQueryData(index, newQuery);
|
handleSetQueryData(index, newQuery);
|
||||||
},
|
},
|
||||||
[index, query, panelType, handleSetQueryData, getNewOperators],
|
[index, query, panelType, handleSetQueryData],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDeleteQuery = useCallback(() => {
|
const handleDeleteQuery = useCallback(() => {
|
||||||
@ -139,11 +122,12 @@ export const useQueryOperations: UseQueryOperations = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (operators.length === 0) {
|
const initialOperators = getOperatorsBySourceAndPanelType({
|
||||||
const initialOperators = getNewOperators(dataSource, panelType);
|
dataSource,
|
||||||
setOperators(initialOperators);
|
panelType,
|
||||||
}
|
});
|
||||||
}, [operators, dataSource, panelType, getNewOperators]);
|
setOperators(initialOperators);
|
||||||
|
}, [dataSource, panelType]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const additionalFilters = getNewListOfAdditionalFilters(dataSource);
|
const additionalFilters = getNewListOfAdditionalFilters(dataSource);
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
} from 'hooks/useResourceAttribute/types';
|
} from 'hooks/useResourceAttribute/types';
|
||||||
import { decode } from 'js-base64';
|
import { decode } from 'js-base64';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
import { IQueryBuilderTagFilterItems } from 'types/api/dashboard/getAll';
|
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { OperatorValues, Tags } from 'types/reducer/trace';
|
import { OperatorValues, Tags } from 'types/reducer/trace';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
@ -63,10 +63,10 @@ export const convertRawQueriesToTraceSelectedTags = (
|
|||||||
/* Convert resource attributes to tagFilter items for queryBuilder */
|
/* Convert resource attributes to tagFilter items for queryBuilder */
|
||||||
export const resourceAttributesToTagFilterItems = (
|
export const resourceAttributesToTagFilterItems = (
|
||||||
queries: IResourceAttribute[],
|
queries: IResourceAttribute[],
|
||||||
): IQueryBuilderTagFilterItems[] =>
|
): TagFilterItem[] =>
|
||||||
queries.map((res) => ({
|
queries.map((res) => ({
|
||||||
id: `${res.id}`,
|
id: `${res.id}`,
|
||||||
key: `${res.tagKey}`,
|
key: { key: res.tagKey, isColumn: false, type: null, dataType: null },
|
||||||
op: `${res.operator}`,
|
op: `${res.operator}`,
|
||||||
value: `${res.tagValue}`.split(','),
|
value: `${res.tagValue}`.split(','),
|
||||||
}));
|
}));
|
||||||
|
@ -17,7 +17,7 @@ export const convertNewDataToOld = (
|
|||||||
QueryData['values']
|
QueryData['values']
|
||||||
>((acc, currentInfo) => {
|
>((acc, currentInfo) => {
|
||||||
const renderValues: [number, string] = [
|
const renderValues: [number, string] = [
|
||||||
currentInfo.timestamp,
|
currentInfo.timestamp / 1000,
|
||||||
currentInfo.value,
|
currentInfo.value,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
31
frontend/src/lib/newQueryBuilder/getFilterObjectValue.ts
Normal file
31
frontend/src/lib/newQueryBuilder/getFilterObjectValue.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { TYPE_ADDON_REGEXP } from 'constants/regExp';
|
||||||
|
import {
|
||||||
|
AutocompleteType,
|
||||||
|
BaseAutocompleteData,
|
||||||
|
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
|
|
||||||
|
const isTypeExist = (str: string): boolean => {
|
||||||
|
const types: AutocompleteType[] = ['tag', 'resource'];
|
||||||
|
let isExist = false;
|
||||||
|
types.forEach((type) => {
|
||||||
|
if (str.includes(type)) {
|
||||||
|
isExist = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return isExist;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getFilterObjectValue = (
|
||||||
|
value: string,
|
||||||
|
): Omit<BaseAutocompleteData, 'dataType' | 'type'> => {
|
||||||
|
const isExist = isTypeExist(value);
|
||||||
|
|
||||||
|
if (!isExist) {
|
||||||
|
return { isColumn: true, key: value };
|
||||||
|
}
|
||||||
|
|
||||||
|
const splittedValue = value.split(TYPE_ADDON_REGEXP);
|
||||||
|
|
||||||
|
return { isColumn: false, key: splittedValue[1] };
|
||||||
|
};
|
@ -0,0 +1,24 @@
|
|||||||
|
import { mapOfOperators, PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
|
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
||||||
|
import { DataSource, StringOperators } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
|
type GetQueryOperatorsParams = {
|
||||||
|
dataSource: DataSource;
|
||||||
|
panelType: GRAPH_TYPES;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Modify this function if need special conditions for filtering of the operators
|
||||||
|
export const getOperatorsBySourceAndPanelType = ({
|
||||||
|
dataSource,
|
||||||
|
panelType,
|
||||||
|
}: GetQueryOperatorsParams): string[] => {
|
||||||
|
let operatorsByDataSource = mapOfOperators[dataSource];
|
||||||
|
|
||||||
|
if (dataSource !== DataSource.METRICS && panelType !== PANEL_TYPES.LIST) {
|
||||||
|
operatorsByDataSource = operatorsByDataSource.filter(
|
||||||
|
(operator) => operator !== StringOperators.NOOP,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return operatorsByDataSource;
|
||||||
|
};
|
@ -0,0 +1,20 @@
|
|||||||
|
import { initialQueryBuilderFormValues } from 'constants/queryBuilder';
|
||||||
|
import { isQuery, QueryBuilderData } from 'types/common/queryBuilder';
|
||||||
|
import { QueryDataResourse } from 'types/common/queryBuilderMappers.types';
|
||||||
|
|
||||||
|
export const mapQueryDataFromApi = (
|
||||||
|
data: QueryDataResourse,
|
||||||
|
): QueryBuilderData => {
|
||||||
|
const queryData: QueryBuilderData['queryData'] = [];
|
||||||
|
const queryFormulas: QueryBuilderData['queryFormulas'] = [];
|
||||||
|
|
||||||
|
Object.entries(data).forEach(([, value]) => {
|
||||||
|
if (isQuery(value)) {
|
||||||
|
queryData.push({ ...initialQueryBuilderFormValues, ...value });
|
||||||
|
} else {
|
||||||
|
queryFormulas.push(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { queryData, queryFormulas };
|
||||||
|
};
|
@ -1,15 +1,9 @@
|
|||||||
import {
|
|
||||||
IBuilderFormula,
|
|
||||||
IBuilderQuery,
|
|
||||||
} from 'types/api/queryBuilder/queryBuilderData';
|
|
||||||
import { QueryBuilderData } from 'types/common/queryBuilder';
|
import { QueryBuilderData } from 'types/common/queryBuilder';
|
||||||
|
import {
|
||||||
type MapQueryDataToApiResult = {
|
MapFormula,
|
||||||
data: Record<string, IBuilderQuery | IBuilderFormula>;
|
MapQuery,
|
||||||
newLegendMap: Record<string, string>;
|
MapQueryDataToApiResult,
|
||||||
};
|
} from 'types/common/queryBuilderMappers.types';
|
||||||
type MapQuery = Record<string, IBuilderQuery>;
|
|
||||||
type MapFormula = Record<string, IBuilderFormula>;
|
|
||||||
|
|
||||||
export const mapQueryDataToApi = (
|
export const mapQueryDataToApi = (
|
||||||
data: QueryBuilderData,
|
data: QueryBuilderData,
|
||||||
@ -41,6 +35,8 @@ export const mapQueryDataToApi = (
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
newLegendMap[formula.queryName] = formula.legend;
|
||||||
|
|
||||||
return newResult;
|
return newResult;
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
|
@ -3,11 +3,13 @@ import {
|
|||||||
formulasNames,
|
formulasNames,
|
||||||
initialFormulaBuilderFormValues,
|
initialFormulaBuilderFormValues,
|
||||||
initialQueryBuilderFormValues,
|
initialQueryBuilderFormValues,
|
||||||
mapOfOperators,
|
|
||||||
MAX_FORMULAS,
|
MAX_FORMULAS,
|
||||||
MAX_QUERIES,
|
MAX_QUERIES,
|
||||||
|
PANEL_TYPES,
|
||||||
} from 'constants/queryBuilder';
|
} from 'constants/queryBuilder';
|
||||||
|
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
||||||
import { createNewBuilderItemName } from 'lib/newQueryBuilder/createNewBuilderItemName';
|
import { createNewBuilderItemName } from 'lib/newQueryBuilder/createNewBuilderItemName';
|
||||||
|
import { getOperatorsBySourceAndPanelType } from 'lib/newQueryBuilder/getOperatorsBySourceAndPanelType';
|
||||||
import React, {
|
import React, {
|
||||||
createContext,
|
createContext,
|
||||||
PropsWithChildren,
|
PropsWithChildren,
|
||||||
@ -16,7 +18,6 @@ import React, {
|
|||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
// ** Types
|
// ** Types
|
||||||
// TODO: Rename Types on the Reusable type for any source
|
|
||||||
import {
|
import {
|
||||||
IBuilderFormula,
|
IBuilderFormula,
|
||||||
IBuilderQuery,
|
IBuilderQuery,
|
||||||
@ -30,9 +31,12 @@ import {
|
|||||||
export const QueryBuilderContext = createContext<QueryBuilderContextType>({
|
export const QueryBuilderContext = createContext<QueryBuilderContextType>({
|
||||||
queryBuilderData: { queryData: [], queryFormulas: [] },
|
queryBuilderData: { queryData: [], queryFormulas: [] },
|
||||||
initialDataSource: null,
|
initialDataSource: null,
|
||||||
|
panelType: PANEL_TYPES.TIME_SERIES,
|
||||||
resetQueryBuilderData: () => {},
|
resetQueryBuilderData: () => {},
|
||||||
|
resetQueryBuilderInfo: () => {},
|
||||||
handleSetQueryData: () => {},
|
handleSetQueryData: () => {},
|
||||||
handleSetFormulaData: () => {},
|
handleSetFormulaData: () => {},
|
||||||
|
handleSetPanelType: () => {},
|
||||||
initQueryBuilderData: () => {},
|
initQueryBuilderData: () => {},
|
||||||
setupInitialDataSource: () => {},
|
setupInitialDataSource: () => {},
|
||||||
removeEntityByIndex: () => {},
|
removeEntityByIndex: () => {},
|
||||||
@ -48,25 +52,28 @@ const initialQueryBuilderData: QueryBuilderData = {
|
|||||||
export function QueryBuilderProvider({
|
export function QueryBuilderProvider({
|
||||||
children,
|
children,
|
||||||
}: PropsWithChildren): JSX.Element {
|
}: PropsWithChildren): JSX.Element {
|
||||||
// TODO: this is temporary. It will be used when we have fixed dataSource and need create new query with this data source
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const [initialDataSource, setInitialDataSource] = useState<DataSource | null>(
|
const [initialDataSource, setInitialDataSource] = useState<DataSource | null>(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: when initialDataSource will be setuped, on create button initial dataSource will from initialDataSource
|
const [panelType, setPanelType] = useState<GRAPH_TYPES>(
|
||||||
|
PANEL_TYPES.TIME_SERIES,
|
||||||
|
);
|
||||||
|
|
||||||
const [queryBuilderData, setQueryBuilderData] = useState<QueryBuilderData>({
|
const [queryBuilderData, setQueryBuilderData] = useState<QueryBuilderData>({
|
||||||
queryData: [],
|
queryData: [],
|
||||||
queryFormulas: [],
|
queryFormulas: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
// ** Method for resetting query builder data
|
const resetQueryBuilderInfo = useCallback((): void => {
|
||||||
const resetQueryBuilderData = useCallback((): void => {
|
setInitialDataSource(null);
|
||||||
|
setPanelType(PANEL_TYPES.TIME_SERIES);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const resetQueryBuilderData = useCallback(() => {
|
||||||
setQueryBuilderData(initialQueryBuilderData);
|
setQueryBuilderData(initialQueryBuilderData);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// ** Method for setuping query builder data
|
|
||||||
// ** Before setuping transform data from backend to frontend format
|
|
||||||
const initQueryBuilderData = useCallback(
|
const initQueryBuilderData = useCallback(
|
||||||
(queryBuilderData: QueryBuilderData): void => {
|
(queryBuilderData: QueryBuilderData): void => {
|
||||||
setQueryBuilderData(queryBuilderData);
|
setQueryBuilderData(queryBuilderData);
|
||||||
@ -101,14 +108,17 @@ export function QueryBuilderProvider({
|
|||||||
...(initialDataSource
|
...(initialDataSource
|
||||||
? {
|
? {
|
||||||
dataSource: initialDataSource,
|
dataSource: initialDataSource,
|
||||||
aggregateOperator: mapOfOperators[initialDataSource][0],
|
aggregateOperator: getOperatorsBySourceAndPanelType({
|
||||||
|
dataSource: initialDataSource,
|
||||||
|
panelType,
|
||||||
|
})[0],
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
return newQuery;
|
return newQuery;
|
||||||
},
|
},
|
||||||
[initialDataSource],
|
[initialDataSource, panelType],
|
||||||
);
|
);
|
||||||
|
|
||||||
const createNewFormula = useCallback((formulas: IBuilderFormula[]) => {
|
const createNewFormula = useCallback((formulas: IBuilderFormula[]) => {
|
||||||
@ -184,7 +194,6 @@ export function QueryBuilderProvider({
|
|||||||
[updateQueryBuilderData],
|
[updateQueryBuilderData],
|
||||||
);
|
);
|
||||||
const handleSetFormulaData = useCallback(
|
const handleSetFormulaData = useCallback(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
(index: number, formulaData: IBuilderFormula): void => {
|
(index: number, formulaData: IBuilderFormula): void => {
|
||||||
setQueryBuilderData((prevState) => {
|
setQueryBuilderData((prevState) => {
|
||||||
const updatedFormulasBuilderData = updateFormulaBuilderData(
|
const updatedFormulasBuilderData = updateFormulaBuilderData(
|
||||||
@ -202,13 +211,20 @@ export function QueryBuilderProvider({
|
|||||||
[updateFormulaBuilderData],
|
[updateFormulaBuilderData],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleSetPanelType = useCallback((newPanelType: GRAPH_TYPES) => {
|
||||||
|
setPanelType(newPanelType);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const contextValues: QueryBuilderContextType = useMemo(
|
const contextValues: QueryBuilderContextType = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
queryBuilderData,
|
queryBuilderData,
|
||||||
initialDataSource,
|
initialDataSource,
|
||||||
|
panelType,
|
||||||
resetQueryBuilderData,
|
resetQueryBuilderData,
|
||||||
|
resetQueryBuilderInfo,
|
||||||
handleSetQueryData,
|
handleSetQueryData,
|
||||||
handleSetFormulaData,
|
handleSetFormulaData,
|
||||||
|
handleSetPanelType,
|
||||||
initQueryBuilderData,
|
initQueryBuilderData,
|
||||||
setupInitialDataSource,
|
setupInitialDataSource,
|
||||||
removeEntityByIndex,
|
removeEntityByIndex,
|
||||||
@ -218,9 +234,12 @@ export function QueryBuilderProvider({
|
|||||||
[
|
[
|
||||||
queryBuilderData,
|
queryBuilderData,
|
||||||
initialDataSource,
|
initialDataSource,
|
||||||
|
panelType,
|
||||||
resetQueryBuilderData,
|
resetQueryBuilderData,
|
||||||
|
resetQueryBuilderInfo,
|
||||||
handleSetQueryData,
|
handleSetQueryData,
|
||||||
handleSetFormulaData,
|
handleSetFormulaData,
|
||||||
|
handleSetPanelType,
|
||||||
initQueryBuilderData,
|
initQueryBuilderData,
|
||||||
setupInitialDataSource,
|
setupInitialDataSource,
|
||||||
removeEntityByIndex,
|
removeEntityByIndex,
|
||||||
|
@ -60,13 +60,13 @@ export const GetDashboard = ({
|
|||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
queryType: EQueryType.QUERY_BUILDER,
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
promQL: [
|
promql: [
|
||||||
{
|
{
|
||||||
name: GetQueryName([]) as string,
|
name: GetQueryName([]) as string,
|
||||||
...PromQLQueryTemplate,
|
...PromQLQueryTemplate,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
clickHouse: [
|
clickhouse_sql: [
|
||||||
{
|
{
|
||||||
name: GetQueryName([]) as string,
|
name: GetQueryName([]) as string,
|
||||||
...ClickHouseQueryTemplate,
|
...ClickHouseQueryTemplate,
|
||||||
|
@ -6,7 +6,6 @@ import { getMetricsQueryRange } from 'api/metrics/getQueryRange';
|
|||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
||||||
import { ITEMS } from 'container/NewDashboard/ComponentsSlider/menuItems';
|
import { ITEMS } from 'container/NewDashboard/ComponentsSlider/menuItems';
|
||||||
import { EQueryTypeToQueryKeyMapping } from 'container/NewWidget/LeftContainer/QuerySection/types';
|
|
||||||
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
|
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
|
||||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||||
import GetMaxMinTime from 'lib/getMaxMinTime';
|
import GetMaxMinTime from 'lib/getMaxMinTime';
|
||||||
@ -38,24 +37,21 @@ export async function GetMetricQueryRange({
|
|||||||
globalSelectedInterval: Time;
|
globalSelectedInterval: Time;
|
||||||
variables?: Record<string, unknown>;
|
variables?: Record<string, unknown>;
|
||||||
}): Promise<SuccessResponse<MetricRangePayloadProps> | ErrorResponse> {
|
}): Promise<SuccessResponse<MetricRangePayloadProps> | ErrorResponse> {
|
||||||
const { queryType } = query;
|
const queryData = query[query.queryType];
|
||||||
const queryKey: Record<EQueryTypeToQueryKeyMapping, string> =
|
|
||||||
EQueryTypeToQueryKeyMapping[EQueryType[query.queryType]];
|
|
||||||
const queryData = query[queryKey];
|
|
||||||
let legendMap: Record<string, string> = {};
|
let legendMap: Record<string, string> = {};
|
||||||
|
|
||||||
const QueryPayload = {
|
const QueryPayload = {
|
||||||
compositeQuery: {
|
compositeQuery: {
|
||||||
queryType: queryKey,
|
queryType: query.queryType,
|
||||||
panelType: graphType,
|
panelType: graphType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (queryType as EQueryType) {
|
switch (query.queryType) {
|
||||||
case EQueryType.QUERY_BUILDER: {
|
case EQueryType.QUERY_BUILDER: {
|
||||||
const { queryData, queryFormulas } = query.builder;
|
const { queryData: data, queryFormulas } = query.builder;
|
||||||
const builderQueries = mapQueryDataToApi({
|
const builderQueries = mapQueryDataToApi({
|
||||||
queryData,
|
queryData: data,
|
||||||
queryFormulas,
|
queryFormulas,
|
||||||
});
|
});
|
||||||
legendMap = builderQueries.newLegendMap;
|
legendMap = builderQueries.newLegendMap;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// this list must exactly match with the backend
|
// this list must exactly match with the backend
|
||||||
export enum AlertTypes {
|
export enum AlertTypes {
|
||||||
NONE = 'NONE',
|
|
||||||
METRICS_BASED_ALERT = 'METRIC_BASED_ALERT',
|
METRICS_BASED_ALERT = 'METRIC_BASED_ALERT',
|
||||||
LOGS_BASED_ALERT = 'LOGS_BASED_ALERT',
|
LOGS_BASED_ALERT = 'LOGS_BASED_ALERT',
|
||||||
TRACES_BASED_ALERT = 'TRACES_BASED_ALERT',
|
TRACES_BASED_ALERT = 'TRACES_BASED_ALERT',
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
||||||
import {
|
import {
|
||||||
IClickHouseQuery,
|
IClickHouseQuery,
|
||||||
IMetricsBuilderFormula,
|
IMetricsBuilderFormula,
|
||||||
@ -6,12 +7,14 @@ import {
|
|||||||
IQueryBuilderTagFilters,
|
IQueryBuilderTagFilters,
|
||||||
} from 'types/api/dashboard/getAll';
|
} from 'types/api/dashboard/getAll';
|
||||||
import { EAggregateOperator, EQueryType } from 'types/common/dashboard';
|
import { EAggregateOperator, EQueryType } from 'types/common/dashboard';
|
||||||
|
import { QueryDataResourse } from 'types/common/queryBuilderMappers.types';
|
||||||
|
|
||||||
export interface ICompositeMetricQuery {
|
export interface ICompositeMetricQuery {
|
||||||
builderQueries: IBuilderQueries;
|
builderQueries: QueryDataResourse;
|
||||||
promQueries: IPromQueries;
|
promQueries: IPromQueries;
|
||||||
chQueries: IChQueries;
|
chQueries: IChQueries;
|
||||||
queryType: EQueryType;
|
queryType: EQueryType;
|
||||||
|
panelType: GRAPH_TYPES;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IChQueries {
|
export interface IChQueries {
|
||||||
|
@ -24,7 +24,7 @@ export interface AlertDef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface RuleCondition {
|
export interface RuleCondition {
|
||||||
compositeMetricQuery: ICompositeMetricQuery;
|
compositeQuery: ICompositeMetricQuery;
|
||||||
op?: string | undefined;
|
op?: string | undefined;
|
||||||
target?: number | undefined;
|
target?: number | undefined;
|
||||||
matchType?: string | undefined;
|
matchType?: string | undefined;
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
export type QueryType = 1 | 2 | 3;
|
|
||||||
|
|
||||||
export const QUERY_BUILDER: QueryType = 1;
|
|
||||||
export const PROMQL: QueryType = 3;
|
|
||||||
|
|
||||||
export const resolveQueryCategoryName = (s: number): string => {
|
|
||||||
switch (s) {
|
|
||||||
case 1:
|
|
||||||
return 'Query Builder';
|
|
||||||
case 2:
|
|
||||||
return 'Clickhouse Query';
|
|
||||||
case 3:
|
|
||||||
return 'PromQL';
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
};
|
|
@ -92,9 +92,9 @@ export interface PromQLWidgets extends IBaseWidget {
|
|||||||
}
|
}
|
||||||
export interface Query {
|
export interface Query {
|
||||||
queryType: EQueryType;
|
queryType: EQueryType;
|
||||||
promQL: IPromQLQuery[];
|
promql: IPromQLQuery[];
|
||||||
builder: QueryBuilderData;
|
builder: QueryBuilderData;
|
||||||
clickHouse: IClickHouseQuery[];
|
clickhouse_sql: IClickHouseQuery[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IMetricsBuilderFormula {
|
export interface IMetricsBuilderFormula {
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
export enum EQueryTypeToQueryKeyMapping {
|
|
||||||
QUERY_BUILDER = 'metricsBuilder',
|
|
||||||
CLICKHOUSE = 'clickHouse',
|
|
||||||
PROM = 'promQL',
|
|
||||||
}
|
|
@ -2,11 +2,13 @@ export type LocalDataType = 'number' | 'string' | 'bool';
|
|||||||
|
|
||||||
export type DataType = 'int64' | 'float64' | 'string' | 'bool';
|
export type DataType = 'int64' | 'float64' | 'string' | 'bool';
|
||||||
|
|
||||||
|
export type AutocompleteType = 'tag' | 'resource';
|
||||||
|
|
||||||
export interface BaseAutocompleteData {
|
export interface BaseAutocompleteData {
|
||||||
dataType: DataType | null;
|
dataType: DataType | null;
|
||||||
isColumn: boolean | null;
|
isColumn: boolean | null;
|
||||||
key: string;
|
key: string;
|
||||||
type: 'tag' | 'resource' | null;
|
type: AutocompleteType | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IQueryAutocompleteResponse {
|
export interface IQueryAutocompleteResponse {
|
||||||
|
@ -13,14 +13,13 @@ export interface IBuilderFormula {
|
|||||||
|
|
||||||
export interface TagFilterItem {
|
export interface TagFilterItem {
|
||||||
id: string;
|
id: string;
|
||||||
key: string;
|
key?: BaseAutocompleteData;
|
||||||
// TODO: type it in the future
|
|
||||||
op: string;
|
op: string;
|
||||||
value: string[];
|
value: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TagFilter {
|
export interface TagFilter {
|
||||||
items: TagFilterItem[] | [];
|
items: TagFilterItem[];
|
||||||
// TODO: type it in the future
|
// TODO: type it in the future
|
||||||
op: string;
|
op: string;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
export enum EQueryType {
|
export enum EQueryType {
|
||||||
QUERY_BUILDER = 1,
|
QUERY_BUILDER = 'builder',
|
||||||
CLICKHOUSE,
|
CLICKHOUSE = 'clickhouse_sql',
|
||||||
PROM,
|
PROM = 'promql',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EAggregateOperator {
|
export enum EAggregateOperator {
|
||||||
|
@ -3,10 +3,7 @@ import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteRe
|
|||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
type UseQueryOperationsParams = Pick<
|
type UseQueryOperationsParams = Pick<QueryProps, 'index' | 'query'>;
|
||||||
QueryProps,
|
|
||||||
'index' | 'panelType' | 'query'
|
|
||||||
>;
|
|
||||||
|
|
||||||
export type HandleChangeQueryData = <
|
export type HandleChangeQueryData = <
|
||||||
Key extends keyof IBuilderQuery,
|
Key extends keyof IBuilderQuery,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
||||||
import {
|
import {
|
||||||
IBuilderFormula,
|
IBuilderFormula,
|
||||||
IBuilderQuery,
|
IBuilderQuery,
|
||||||
@ -45,7 +46,6 @@ export enum NumberOperators {
|
|||||||
HIST_QUANTILE_99 = 'hist_quantile_99',
|
HIST_QUANTILE_99 = 'hist_quantile_99',
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add boolean operators from backend
|
|
||||||
export enum BoolOperators {
|
export enum BoolOperators {
|
||||||
NOOP = 'noop',
|
NOOP = 'noop',
|
||||||
COUNT = 'count',
|
COUNT = 'count',
|
||||||
@ -147,13 +147,20 @@ export type QueryBuilderData = {
|
|||||||
queryFormulas: IBuilderFormula[];
|
queryFormulas: IBuilderFormula[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// ** TODO: temporary types for context, fix it during development
|
export const isQuery = (
|
||||||
|
query: IBuilderFormula | IBuilderQuery,
|
||||||
|
): query is IBuilderQuery =>
|
||||||
|
'dataSource' in query && 'aggregateOperator' in query;
|
||||||
|
|
||||||
export type QueryBuilderContextType = {
|
export type QueryBuilderContextType = {
|
||||||
queryBuilderData: QueryBuilderData;
|
queryBuilderData: QueryBuilderData;
|
||||||
initialDataSource: DataSource | null;
|
initialDataSource: DataSource | null;
|
||||||
|
panelType: GRAPH_TYPES;
|
||||||
resetQueryBuilderData: () => void;
|
resetQueryBuilderData: () => void;
|
||||||
|
resetQueryBuilderInfo: () => void;
|
||||||
handleSetQueryData: (index: number, queryData: IBuilderQuery) => void;
|
handleSetQueryData: (index: number, queryData: IBuilderQuery) => void;
|
||||||
handleSetFormulaData: (index: number, formulaData: IBuilderFormula) => void;
|
handleSetFormulaData: (index: number, formulaData: IBuilderFormula) => void;
|
||||||
|
handleSetPanelType: (newPanelType: GRAPH_TYPES) => void;
|
||||||
initQueryBuilderData: (queryBuilderData: QueryBuilderData) => void;
|
initQueryBuilderData: (queryBuilderData: QueryBuilderData) => void;
|
||||||
setupInitialDataSource: (newInitialDataSource: DataSource | null) => void;
|
setupInitialDataSource: (newInitialDataSource: DataSource | null) => void;
|
||||||
removeEntityByIndex: (type: keyof QueryBuilderData, index: number) => void;
|
removeEntityByIndex: (type: keyof QueryBuilderData, index: number) => void;
|
||||||
|
14
frontend/src/types/common/queryBuilderMappers.types.ts
Normal file
14
frontend/src/types/common/queryBuilderMappers.types.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {
|
||||||
|
IBuilderFormula,
|
||||||
|
IBuilderQuery,
|
||||||
|
} from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
|
||||||
|
export type MapQuery = Record<string, IBuilderQuery>;
|
||||||
|
export type MapFormula = Record<string, IBuilderFormula>;
|
||||||
|
|
||||||
|
export type QueryDataResourse = Record<string, IBuilderQuery | IBuilderFormula>;
|
||||||
|
|
||||||
|
export type MapQueryDataToApiResult = {
|
||||||
|
data: QueryDataResourse;
|
||||||
|
newLegendMap: Record<string, string>;
|
||||||
|
};
|
@ -2,3 +2,11 @@ export type SelectOption<Value, Label extends unknown = string> = {
|
|||||||
value: Value;
|
value: Value;
|
||||||
label: Label;
|
label: Label;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ExtendedSelectOption = {
|
||||||
|
disabled?: boolean;
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
title?: string;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user