signoz/frontend/src/constants/queryBuilder.ts
Vikrant Gupta 191d9b0648
feat: introducing collapsable rows for dashboards (#4806)
* feat: dashboard panel grouping initial setup

* feat: added panel map to the dashboard response and subsequent types for the same

* feat: added panel map to the dashboard response and subsequent types for the same

* feat: added settings modal

* feat: handle panel collapse and open changes

* feat: handle creating panel map when dashboard layout changes

* feat: handle creating panel map when dashboard layout changes

* feat: refactor code

* feat: handle multiple collapsable rows

* fix: type issues

* feat: handle row collapse button and scroll

* feat: handle y axis movement for rows

* feat: handle delete row

* feat: handle settings name change

* feat: disable collapse/uncollapse when dashboard loading to avoid async states

* feat: decrease the height of the grouping row

* fix: row height management

* fix: handle empty row case

* feat: remove resize handle from the row

* feat: handle re-arrangement of panels

* feat: increase height of default new widget

* feat: added safety checks
2024-04-30 14:36:47 +05:30

408 lines
9.7 KiB
TypeScript

// ** Helpers
import { createIdFromObjectFields } from 'lib/createIdFromObjectFields';
import { createNewBuilderItemName } from 'lib/newQueryBuilder/createNewBuilderItemName';
import {
AutocompleteType,
BaseAutocompleteData,
DataTypes,
LocalDataType,
} from 'types/api/queryBuilder/queryAutocompleteResponse';
import {
HavingForm,
IBuilderFormula,
IBuilderQuery,
IClickHouseQuery,
IPromQLQuery,
Query,
QueryState,
TagFilter,
} from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard';
import {
BoolOperators,
DataSource,
LogsAggregatorOperator,
MetricAggregateOperator,
NumberOperators,
QueryAdditionalFilter,
QueryBuilderData,
ReduceOperators,
StringOperators,
TracesAggregatorOperator,
} from 'types/common/queryBuilder';
import { SelectOption } from 'types/common/select';
import { v4 as uuid } from 'uuid';
import {
logsAggregateOperatorOptions,
metricAggregateOperatorOptions,
metricsGaugeAggregateOperatorOptions,
metricsGaugeSpaceAggregateOperatorOptions,
metricsHistogramSpaceAggregateOperatorOptions,
metricsSumAggregateOperatorOptions,
metricsSumSpaceAggregateOperatorOptions,
tracesAggregateOperatorOptions,
} from './queryBuilderOperators';
export const MAX_FORMULAS = 20;
export const MAX_QUERIES = 26;
export const idDivider = '--';
export const selectValueDivider = '__';
export const baseAutoCompleteIdKeysOrder: (keyof Omit<
BaseAutocompleteData,
'id' | 'isJSON'
>)[] = ['key', 'dataType', 'type', 'isColumn'];
export const autocompleteType: Record<AutocompleteType, AutocompleteType> = {
resource: 'resource',
tag: 'tag',
'': '',
};
export const formulasNames: string[] = Array.from(
Array(MAX_FORMULAS),
(_, i) => `F${i + 1}`,
);
const alpha: number[] = Array.from(Array(MAX_QUERIES), (_, i) => i + 65);
export const alphabet: string[] = alpha.map((str) => String.fromCharCode(str));
export enum QueryBuilderKeys {
GET_AGGREGATE_ATTRIBUTE = 'GET_AGGREGATE_ATTRIBUTE',
GET_AGGREGATE_KEYS = 'GET_AGGREGATE_KEYS',
}
export const mapOfOperators = {
metrics: metricAggregateOperatorOptions,
logs: logsAggregateOperatorOptions,
traces: tracesAggregateOperatorOptions,
};
export const metricsOperatorsByType = {
Sum: metricsSumAggregateOperatorOptions,
Gauge: metricsGaugeAggregateOperatorOptions,
};
export const metricsSpaceAggregationOperatorsByType = {
Sum: metricsSumSpaceAggregateOperatorOptions,
Gauge: metricsGaugeSpaceAggregateOperatorOptions,
Histogram: metricsHistogramSpaceAggregateOperatorOptions,
ExponentialHistogram: metricsHistogramSpaceAggregateOperatorOptions,
};
export const mapOfQueryFilters: Record<DataSource, QueryAdditionalFilter[]> = {
metrics: [
// eslint-disable-next-line sonarjs/no-duplicate-string
{ text: 'Aggregation interval', field: 'stepInterval' },
{ text: 'Having', field: 'having' },
],
logs: [
{ text: 'Order by', field: 'orderBy' },
{ text: 'Limit', field: 'limit' },
{ text: 'Having', field: 'having' },
{ text: 'Aggregation interval', field: 'stepInterval' },
],
traces: [
{ text: 'Order by', field: 'orderBy' },
{ text: 'Limit', field: 'limit' },
{ text: 'Having', field: 'having' },
{ text: 'Aggregation interval', field: 'stepInterval' },
],
};
const commonFormulaFilters: QueryAdditionalFilter[] = [
{
text: 'Having',
field: 'having',
},
{ text: 'Order by', field: 'orderBy' },
{ text: 'Limit', field: 'limit' },
];
export const mapOfFormulaToFilters: Record<
DataSource,
QueryAdditionalFilter[]
> = {
metrics: commonFormulaFilters,
logs: commonFormulaFilters,
traces: commonFormulaFilters,
};
export const REDUCE_TO_VALUES: SelectOption<ReduceOperators, string>[] = [
{ value: 'last', label: 'Latest of values in timeframe' },
{ value: 'sum', label: 'Sum of values in timeframe' },
{ value: 'avg', label: 'Average of values in timeframe' },
{ value: 'max', label: 'Max of values in timeframe' },
{ value: 'min', label: 'Min of values in timeframe' },
];
export const initialHavingValues: HavingForm = {
columnName: '',
op: '',
value: [],
};
export const initialAutocompleteData: BaseAutocompleteData = {
id: createIdFromObjectFields(
{ dataType: null, key: '', isColumn: null, type: null },
baseAutoCompleteIdKeysOrder,
),
dataType: DataTypes.EMPTY,
key: '',
isColumn: false,
type: '',
isJSON: false,
};
export const initialFilters: TagFilter = {
items: [],
op: 'AND',
};
export const initialQueryBuilderFormValues: IBuilderQuery = {
dataSource: DataSource.METRICS,
queryName: createNewBuilderItemName({ existNames: [], sourceNames: alphabet }),
aggregateOperator: MetricAggregateOperator.COUNT,
aggregateAttribute: initialAutocompleteData,
timeAggregation: MetricAggregateOperator.RATE,
spaceAggregation: MetricAggregateOperator.SUM,
functions: [],
filters: { items: [], op: 'AND' },
expression: createNewBuilderItemName({
existNames: [],
sourceNames: alphabet,
}),
disabled: false,
having: [],
stepInterval: 60,
limit: null,
orderBy: [],
groupBy: [],
legend: '',
reduceTo: 'avg',
};
const initialQueryBuilderFormLogsValues: IBuilderQuery = {
...initialQueryBuilderFormValues,
aggregateOperator: LogsAggregatorOperator.COUNT,
dataSource: DataSource.LOGS,
};
const initialQueryBuilderFormTracesValues: IBuilderQuery = {
...initialQueryBuilderFormValues,
aggregateOperator: TracesAggregatorOperator.COUNT,
dataSource: DataSource.TRACES,
};
export const initialQueryBuilderFormValuesMap: Record<
DataSource,
IBuilderQuery
> = {
metrics: initialQueryBuilderFormValues,
logs: initialQueryBuilderFormLogsValues,
traces: initialQueryBuilderFormTracesValues,
};
export const initialFormulaBuilderFormValues: IBuilderFormula = {
queryName: createNewBuilderItemName({
existNames: [],
sourceNames: formulasNames,
}),
expression: '',
disabled: false,
legend: '',
};
export const initialQueryPromQLData: IPromQLQuery = {
name: createNewBuilderItemName({ existNames: [], sourceNames: alphabet }),
query: '',
legend: '',
disabled: false,
};
export const initialClickHouseData: IClickHouseQuery = {
name: createNewBuilderItemName({ existNames: [], sourceNames: alphabet }),
legend: '',
disabled: false,
query: '',
};
export const initialQueryBuilderData: QueryBuilderData = {
queryData: [initialQueryBuilderFormValues],
queryFormulas: [],
};
export const initialSingleQueryMap: Record<
EQueryType.PROM | EQueryType.CLICKHOUSE,
IClickHouseQuery | IPromQLQuery
> = { clickhouse_sql: initialClickHouseData, promql: initialQueryPromQLData };
export const initialQueryState: QueryState = {
id: uuid(),
builder: initialQueryBuilderData,
clickhouse_sql: [initialClickHouseData],
promql: [initialQueryPromQLData],
};
const initialQueryWithType: Query = {
...initialQueryState,
queryType: EQueryType.QUERY_BUILDER,
};
const initialQueryLogsWithType: Query = {
...initialQueryWithType,
builder: {
...initialQueryWithType.builder,
queryData: [initialQueryBuilderFormValuesMap.logs],
},
};
const initialQueryTracesWithType: Query = {
...initialQueryWithType,
builder: {
...initialQueryWithType.builder,
queryData: [initialQueryBuilderFormValuesMap.traces],
},
};
export const initialQueriesMap: Record<DataSource, Query> = {
metrics: initialQueryWithType,
logs: initialQueryLogsWithType,
traces: initialQueryTracesWithType,
};
export const operatorsByTypes: Record<LocalDataType, string[]> = {
string: Object.values(StringOperators),
number: Object.values(NumberOperators),
bool: Object.values(BoolOperators),
};
// eslint-disable-next-line @typescript-eslint/naming-convention
export enum PANEL_TYPES {
TIME_SERIES = 'graph',
VALUE = 'value',
TABLE = 'table',
LIST = 'list',
TRACE = 'trace',
BAR = 'bar',
PIE = 'pie',
EMPTY_WIDGET = 'EMPTY_WIDGET',
}
// eslint-disable-next-line @typescript-eslint/naming-convention
export enum PANEL_GROUP_TYPES {
ROW = 'row',
}
// eslint-disable-next-line @typescript-eslint/naming-convention
export enum ATTRIBUTE_TYPES {
SUM = 'Sum',
GAUGE = 'Gauge',
HISTOGRAM = 'Histogram',
EXPONENTIAL_HISTOGRAM = 'ExponentialHistogram',
}
export type IQueryBuilderState = 'search';
export const QUERY_BUILDER_SEARCH_VALUES = {
MULTIPLY: 'MULTIPLY_VALUE',
SINGLE: 'SINGLE_VALUE',
NON: 'NON_VALUE',
NOT_VALID: 'NOT_VALID',
};
export const OPERATORS = {
IN: 'IN',
NIN: 'NOT_IN',
LIKE: 'LIKE',
NLIKE: 'NOT_LIKE',
REGEX: 'REGEX',
NREGEX: 'NOT_REGEX',
'=': '=',
'!=': '!=',
EXISTS: 'EXISTS',
NOT_EXISTS: 'NOT_EXISTS',
CONTAINS: 'CONTAINS',
NOT_CONTAINS: 'NOT_CONTAINS',
'>=': '>=',
'>': '>',
'<=': '<=',
'<': '<',
HAS: 'HAS',
NHAS: 'NHAS',
};
export const QUERY_BUILDER_OPERATORS_BY_TYPES = {
string: [
OPERATORS['='],
OPERATORS['!='],
OPERATORS.IN,
OPERATORS.NIN,
OPERATORS.LIKE,
OPERATORS.NLIKE,
OPERATORS.CONTAINS,
OPERATORS.NOT_CONTAINS,
OPERATORS.EXISTS,
OPERATORS.NOT_EXISTS,
OPERATORS.REGEX,
OPERATORS.NREGEX,
],
int64: [
OPERATORS['='],
OPERATORS['!='],
OPERATORS.IN,
OPERATORS.NIN,
OPERATORS.EXISTS,
OPERATORS.NOT_EXISTS,
OPERATORS['>='],
OPERATORS['>'],
OPERATORS['<='],
OPERATORS['<'],
],
float64: [
OPERATORS['='],
OPERATORS['!='],
OPERATORS.IN,
OPERATORS.NIN,
OPERATORS.EXISTS,
OPERATORS.NOT_EXISTS,
OPERATORS['>='],
OPERATORS['>'],
OPERATORS['<='],
OPERATORS['<'],
],
bool: [
OPERATORS['='],
OPERATORS['!='],
OPERATORS.EXISTS,
OPERATORS.NOT_EXISTS,
],
universal: [
OPERATORS['='],
OPERATORS['!='],
OPERATORS.IN,
OPERATORS.NIN,
OPERATORS.EXISTS,
OPERATORS.NOT_EXISTS,
OPERATORS.LIKE,
OPERATORS.NLIKE,
OPERATORS['>='],
OPERATORS['>'],
OPERATORS['<='],
OPERATORS['<'],
OPERATORS.CONTAINS,
OPERATORS.NOT_CONTAINS,
],
};
export const HAVING_OPERATORS: string[] = [
OPERATORS['='],
OPERATORS['!='],
OPERATORS.IN,
OPERATORS.NIN,
OPERATORS['>='],
OPERATORS['>'],
OPERATORS['<='],
OPERATORS['<'],
];