mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-15 12:55:59 +08:00
fix: column name with legend (#3200)
* fix: column name with legend * fix: render columns with data * fix: index * fix: render rows * fix: remove log * fix: return operators for entiry metric * fix: remove noop and rate for table metric * fix: for request * chore: allow count attribute to be empty --------- Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
This commit is contained in:
parent
a2c03243cb
commit
5469cd34fa
@ -125,7 +125,7 @@ export const initialFilters: TagFilter = {
|
|||||||
export const initialQueryBuilderFormValues: IBuilderQuery = {
|
export const initialQueryBuilderFormValues: IBuilderQuery = {
|
||||||
dataSource: DataSource.METRICS,
|
dataSource: DataSource.METRICS,
|
||||||
queryName: createNewBuilderItemName({ existNames: [], sourceNames: alphabet }),
|
queryName: createNewBuilderItemName({ existNames: [], sourceNames: alphabet }),
|
||||||
aggregateOperator: MetricAggregateOperator.NOOP,
|
aggregateOperator: MetricAggregateOperator.COUNT,
|
||||||
aggregateAttribute: initialAutocompleteData,
|
aggregateAttribute: initialAutocompleteData,
|
||||||
filters: { items: [], op: 'AND' },
|
filters: { items: [], op: 'AND' },
|
||||||
expression: createNewBuilderItemName({
|
expression: createNewBuilderItemName({
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { mapOfOperators, PANEL_TYPES } from 'constants/queryBuilder';
|
import { mapOfOperators, PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { DataSource, StringOperators } from 'types/common/queryBuilder';
|
import {
|
||||||
|
DataSource,
|
||||||
|
MetricAggregateOperator,
|
||||||
|
StringOperators,
|
||||||
|
} from 'types/common/queryBuilder';
|
||||||
import { SelectOption } from 'types/common/select';
|
import { SelectOption } from 'types/common/select';
|
||||||
|
|
||||||
type GetQueryOperatorsParams = {
|
type GetQueryOperatorsParams = {
|
||||||
@ -19,6 +23,13 @@ export const getOperatorsBySourceAndPanelType = ({
|
|||||||
(operator) => operator.value === StringOperators.NOOP,
|
(operator) => operator.value === StringOperators.NOOP,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (panelType === PANEL_TYPES.TABLE && dataSource === DataSource.METRICS) {
|
||||||
|
operatorsByDataSource = operatorsByDataSource.filter(
|
||||||
|
(operator) =>
|
||||||
|
operator.value !== MetricAggregateOperator.NOOP &&
|
||||||
|
operator.value !== MetricAggregateOperator.RATE,
|
||||||
|
);
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
dataSource !== DataSource.METRICS &&
|
dataSource !== DataSource.METRICS &&
|
||||||
panelType !== PANEL_TYPES.LIST &&
|
panelType !== PANEL_TYPES.LIST &&
|
||||||
|
@ -6,7 +6,6 @@ import {
|
|||||||
} from 'constants/queryBuilder';
|
} from 'constants/queryBuilder';
|
||||||
import { FORMULA_REGEXP } from 'constants/regExp';
|
import { FORMULA_REGEXP } from 'constants/regExp';
|
||||||
import { QueryTableProps } from 'container/QueryTable/QueryTable.intefaces';
|
import { QueryTableProps } from 'container/QueryTable/QueryTable.intefaces';
|
||||||
import { toCapitalize } from 'lib/toCapitalize';
|
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import {
|
import {
|
||||||
IBuilderFormula,
|
IBuilderFormula,
|
||||||
@ -145,7 +144,7 @@ const addOperatorFormulaColumns = (
|
|||||||
let formulaLabel = `${formulaQuery.queryName}(${formulaQuery.expression})`;
|
let formulaLabel = `${formulaQuery.queryName}(${formulaQuery.expression})`;
|
||||||
|
|
||||||
if (formulaQuery.legend) {
|
if (formulaQuery.legend) {
|
||||||
formulaLabel += ` - ${formulaQuery.legend}`;
|
formulaLabel = formulaQuery.legend;
|
||||||
}
|
}
|
||||||
|
|
||||||
const formulaColumn: DynamicColumn = {
|
const formulaColumn: DynamicColumn = {
|
||||||
@ -171,18 +170,14 @@ const addOperatorFormulaColumns = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentQueryData.legend) {
|
if (currentQueryData.legend) {
|
||||||
operatorLabel += ` - ${currentQueryData.legend}`;
|
operatorLabel = currentQueryData.legend;
|
||||||
} else {
|
|
||||||
operatorLabel += ` - ${currentQueryData.queryName}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const resultValue = `${toCapitalize(operatorLabel)}`;
|
|
||||||
|
|
||||||
const operatorColumn: DynamicColumn = {
|
const operatorColumn: DynamicColumn = {
|
||||||
query,
|
query,
|
||||||
field: currentQueryData.queryName,
|
field: currentQueryData.queryName,
|
||||||
dataIndex: currentQueryData.queryName,
|
dataIndex: currentQueryData.queryName,
|
||||||
title: customLabel || resultValue,
|
title: customLabel || operatorLabel,
|
||||||
data: [],
|
data: [],
|
||||||
type: 'operator',
|
type: 'operator',
|
||||||
// sortable: isNumber,
|
// sortable: isNumber,
|
||||||
@ -218,26 +213,24 @@ const getDynamicColumns: GetDynamicColumns = (queryTableData, query) => {
|
|||||||
const dynamicColumns: DynamicColumns = [];
|
const dynamicColumns: DynamicColumns = [];
|
||||||
|
|
||||||
queryTableData.forEach((currentQuery) => {
|
queryTableData.forEach((currentQuery) => {
|
||||||
|
const { series, queryName, list } = currentQuery;
|
||||||
|
|
||||||
const currentStagedQuery = getQueryByName(
|
const currentStagedQuery = getQueryByName(
|
||||||
query.builder,
|
query.builder,
|
||||||
currentQuery.queryName,
|
queryName,
|
||||||
isFormula(currentQuery.queryName) ? 'queryFormulas' : 'queryData',
|
isFormula(queryName) ? 'queryFormulas' : 'queryData',
|
||||||
);
|
);
|
||||||
if (currentQuery.list) {
|
if (list) {
|
||||||
currentQuery.list.forEach((listItem) => {
|
list.forEach((listItem) => {
|
||||||
Object.keys(listItem.data).forEach((label) => {
|
Object.keys(listItem.data).forEach((label) => {
|
||||||
addListLabels(currentStagedQuery, label as ListItemKey, dynamicColumns);
|
addListLabels(currentStagedQuery, label as ListItemKey, dynamicColumns);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentQuery.series) {
|
if (series) {
|
||||||
const isValuesColumnExist = currentQuery.series.some(
|
const isValuesColumnExist = series.some((item) => item.values.length > 0);
|
||||||
(item) => item.values.length > 0,
|
const isEveryValuesExist = series.every((item) => item.values.length > 0);
|
||||||
);
|
|
||||||
const isEveryValuesExist = currentQuery.series.every(
|
|
||||||
(item) => item.values.length > 0,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isValuesColumnExist) {
|
if (isValuesColumnExist) {
|
||||||
addOperatorFormulaColumns(
|
addOperatorFormulaColumns(
|
||||||
@ -247,7 +240,7 @@ const getDynamicColumns: GetDynamicColumns = (queryTableData, query) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentQuery.series.forEach((seria) => {
|
series.forEach((seria) => {
|
||||||
Object.keys(seria.labels).forEach((label) => {
|
Object.keys(seria.labels).forEach((label) => {
|
||||||
if (label === currentQuery?.queryName) return;
|
if (label === currentQuery?.queryName) return;
|
||||||
|
|
||||||
@ -277,12 +270,54 @@ const fillEmptyRowCells = (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const fillData = (
|
const findSeriaValueFromAnotherQuery = (
|
||||||
seria: SeriesItem,
|
currentLabels: Record<string, string>,
|
||||||
columns: DynamicColumns,
|
nextQuery: QueryDataV3 | null,
|
||||||
|
): SeriesItem | null => {
|
||||||
|
if (!nextQuery || !nextQuery.series) return null;
|
||||||
|
|
||||||
|
let value = null;
|
||||||
|
|
||||||
|
const labelEntries = Object.entries(currentLabels);
|
||||||
|
|
||||||
|
nextQuery.series.forEach((seria) => {
|
||||||
|
const localLabelEntries = Object.entries(seria.labels);
|
||||||
|
if (localLabelEntries.length !== labelEntries.length) return;
|
||||||
|
|
||||||
|
const isExistLabels = localLabelEntries.find(([key, value]) =>
|
||||||
|
labelEntries.find(
|
||||||
|
([currentKey, currentValue]) =>
|
||||||
|
currentKey === key && currentValue === value,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isExistLabels) {
|
||||||
|
value = seria;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isEqualQueriesByLabel = (
|
||||||
|
equalQueries: string[],
|
||||||
queryName: string,
|
queryName: string,
|
||||||
value?: SeriesItem['values'][number],
|
): boolean => equalQueries.includes(queryName);
|
||||||
|
|
||||||
|
const fillDataFromSeries = (
|
||||||
|
currentQuery: QueryDataV3,
|
||||||
|
queryTableData: QueryDataV3[],
|
||||||
|
columns: DynamicColumns,
|
||||||
|
equalQueriesByLabels: string[],
|
||||||
|
// TODO: fix it
|
||||||
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||||
): void => {
|
): void => {
|
||||||
|
const { series, queryName } = currentQuery;
|
||||||
|
const isEqualQuery = isEqualQueriesByLabel(equalQueriesByLabels, queryName);
|
||||||
|
|
||||||
|
if (!series) return;
|
||||||
|
|
||||||
|
series.forEach((seria) => {
|
||||||
const labelEntries = Object.entries(seria.labels);
|
const labelEntries = Object.entries(seria.labels);
|
||||||
|
|
||||||
const unusedColumnsKeys = new Set<keyof RowData>(
|
const unusedColumnsKeys = new Set<keyof RowData>(
|
||||||
@ -290,12 +325,41 @@ const fillData = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
columns.forEach((column) => {
|
columns.forEach((column) => {
|
||||||
if (queryName === column.field && value) {
|
if (queryName === column.field) {
|
||||||
column.data.push(parseFloat(value.value).toFixed(2));
|
if (seria.values.length === 0) return;
|
||||||
|
|
||||||
|
column.data.push(parseFloat(seria.values[0].value).toFixed(2));
|
||||||
unusedColumnsKeys.delete(column.field);
|
unusedColumnsKeys.delete(column.field);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (column.type !== 'field' && column.field !== queryName) {
|
||||||
|
const nextQueryData =
|
||||||
|
queryTableData.find((q) => q.queryName === column.field) || null;
|
||||||
|
|
||||||
|
const targetSeria = findSeriaValueFromAnotherQuery(
|
||||||
|
seria.labels,
|
||||||
|
nextQueryData,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (targetSeria) {
|
||||||
|
const isEqual = isEqualQueriesByLabel(equalQueriesByLabels, column.field);
|
||||||
|
if (!isEqual) {
|
||||||
|
equalQueriesByLabels.push(column.field);
|
||||||
|
}
|
||||||
|
|
||||||
|
column.data.push(parseFloat(targetSeria.values[0].value).toFixed(2));
|
||||||
|
} else {
|
||||||
|
column.data.push('N/A');
|
||||||
|
}
|
||||||
|
|
||||||
|
unusedColumnsKeys.delete(column.field);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEqualQuery) return;
|
||||||
|
|
||||||
labelEntries.forEach(([key, currentValue]) => {
|
labelEntries.forEach(([key, currentValue]) => {
|
||||||
if (column.field === key) {
|
if (column.field === key) {
|
||||||
column.data.push(currentValue);
|
column.data.push(currentValue);
|
||||||
@ -305,21 +369,6 @@ const fillData = (
|
|||||||
|
|
||||||
fillEmptyRowCells(unusedColumnsKeys, columns, column);
|
fillEmptyRowCells(unusedColumnsKeys, columns, column);
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
const fillDataFromSeria = (
|
|
||||||
seria: SeriesItem,
|
|
||||||
columns: DynamicColumns,
|
|
||||||
queryName: string,
|
|
||||||
): void => {
|
|
||||||
if (seria.values.length === 0) {
|
|
||||||
fillData(seria, columns, queryName);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
seria.values.forEach((value) => {
|
|
||||||
fillData(seria, columns, queryName, value);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -348,15 +397,20 @@ const fillColumnsData: FillColumnData = (queryTableData, cols) => {
|
|||||||
const formulas = cols.filter((item) => item.type === 'formula');
|
const formulas = cols.filter((item) => item.type === 'formula');
|
||||||
const resultColumns = [...fields, ...operators, ...formulas];
|
const resultColumns = [...fields, ...operators, ...formulas];
|
||||||
|
|
||||||
queryTableData.forEach((currentQuery) => {
|
const equalQueriesByLabels: string[] = [];
|
||||||
if (currentQuery.series) {
|
|
||||||
currentQuery.series.forEach((seria) => {
|
|
||||||
fillDataFromSeria(seria, resultColumns, currentQuery.queryName);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentQuery.list) {
|
queryTableData.forEach((currentQuery) => {
|
||||||
currentQuery.list.forEach((listItem) => {
|
const { list } = currentQuery;
|
||||||
|
|
||||||
|
fillDataFromSeries(
|
||||||
|
currentQuery,
|
||||||
|
queryTableData,
|
||||||
|
resultColumns,
|
||||||
|
equalQueriesByLabels,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (list) {
|
||||||
|
list.forEach((listItem) => {
|
||||||
fillDataFromList(listItem, resultColumns);
|
fillDataFromList(listItem, resultColumns);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,8 @@ func (a AggregateOperator) RequireAttribute(dataSource DataSource) bool {
|
|||||||
switch dataSource {
|
switch dataSource {
|
||||||
case DataSourceMetrics:
|
case DataSourceMetrics:
|
||||||
switch a {
|
switch a {
|
||||||
case AggregateOperatorNoOp:
|
case AggregateOperatorNoOp,
|
||||||
|
AggregateOperatorCount:
|
||||||
return false
|
return false
|
||||||
default:
|
default:
|
||||||
return true
|
return true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user