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