mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-17 15:36:48 +00:00
fix: backward compatibility for explorer in case of aggregateAttribute is not present (#9000)
This commit is contained in:
parent
faadc60c74
commit
abeadc7672
@ -1,10 +1,16 @@
|
|||||||
/* eslint-disable sonarjs/no-duplicate-string */
|
/* eslint-disable sonarjs/no-duplicate-string */
|
||||||
/* eslint-disable import/no-unresolved */
|
/* eslint-disable import/no-unresolved */
|
||||||
import { negateOperator, OPERATORS } from 'constants/antlrQueryConstants';
|
import { negateOperator, OPERATORS } from 'constants/antlrQueryConstants';
|
||||||
|
import {
|
||||||
|
BaseAutocompleteData,
|
||||||
|
DataTypes,
|
||||||
|
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
import { extractQueryPairs } from 'utils/queryContextUtils';
|
import { extractQueryPairs } from 'utils/queryContextUtils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
convertAggregationToExpression,
|
||||||
convertFiltersToExpression,
|
convertFiltersToExpression,
|
||||||
convertFiltersToExpressionWithExistingQuery,
|
convertFiltersToExpressionWithExistingQuery,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
@ -769,3 +775,200 @@ describe('convertFiltersToExpression', () => {
|
|||||||
expect(result.filter.expression).toBe("service.name = 'old-service'");
|
expect(result.filter.expression).toBe("service.name = 'old-service'");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('convertAggregationToExpression', () => {
|
||||||
|
const mockAttribute: BaseAutocompleteData = {
|
||||||
|
id: 'test-id',
|
||||||
|
key: 'test_metric',
|
||||||
|
type: 'string',
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should return undefined when no aggregateOperator is provided', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: '',
|
||||||
|
aggregateAttribute: mockAttribute,
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
});
|
||||||
|
expect(result).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert metrics aggregation with required temporality field', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: 'sum',
|
||||||
|
aggregateAttribute: mockAttribute,
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
timeAggregation: 'avg',
|
||||||
|
spaceAggregation: 'max',
|
||||||
|
alias: 'test_alias',
|
||||||
|
reduceTo: 'sum',
|
||||||
|
temporality: 'delta',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
metricName: 'test_metric',
|
||||||
|
timeAggregation: 'avg',
|
||||||
|
spaceAggregation: 'max',
|
||||||
|
reduceTo: 'sum',
|
||||||
|
temporality: 'delta',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle noop operators by converting to count', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: 'noop',
|
||||||
|
aggregateAttribute: mockAttribute,
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
timeAggregation: 'noop',
|
||||||
|
spaceAggregation: 'noop',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
metricName: 'test_metric',
|
||||||
|
timeAggregation: 'count',
|
||||||
|
spaceAggregation: 'count',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle missing attribute key gracefully', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: 'sum',
|
||||||
|
aggregateAttribute: { ...mockAttribute, key: '' },
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
metricName: '',
|
||||||
|
timeAggregation: 'sum',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert traces aggregation to expression format', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: 'count',
|
||||||
|
aggregateAttribute: mockAttribute,
|
||||||
|
dataSource: DataSource.TRACES,
|
||||||
|
alias: 'trace_alias',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
expression: 'count(test_metric)',
|
||||||
|
alias: 'trace_alias',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert logs aggregation to expression format', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: 'avg',
|
||||||
|
aggregateAttribute: mockAttribute,
|
||||||
|
dataSource: DataSource.LOGS,
|
||||||
|
alias: 'log_alias',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
expression: 'avg(test_metric)',
|
||||||
|
alias: 'log_alias',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle aggregation without attribute key for traces/logs', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: 'count',
|
||||||
|
aggregateAttribute: { ...mockAttribute, key: '' },
|
||||||
|
dataSource: DataSource.TRACES,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
expression: 'count()',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle missing alias for traces/logs', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: 'sum',
|
||||||
|
aggregateAttribute: mockAttribute,
|
||||||
|
dataSource: DataSource.LOGS,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
expression: 'sum(test_metric)',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use aggregateOperator as fallback for time and space aggregation', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: 'max',
|
||||||
|
aggregateAttribute: mockAttribute,
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
metricName: 'test_metric',
|
||||||
|
timeAggregation: 'max',
|
||||||
|
spaceAggregation: 'max',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle undefined aggregateAttribute parameter with metrics', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: 'sum',
|
||||||
|
aggregateAttribute: mockAttribute,
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
metricName: 'test_metric',
|
||||||
|
timeAggregation: 'sum',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
reduceTo: undefined,
|
||||||
|
temporality: undefined,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle undefined aggregateAttribute parameter with traces', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: 'noop',
|
||||||
|
aggregateAttribute: (undefined as unknown) as BaseAutocompleteData,
|
||||||
|
dataSource: DataSource.TRACES,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
expression: 'count()',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle undefined aggregateAttribute parameter with logs', () => {
|
||||||
|
const result = convertAggregationToExpression({
|
||||||
|
aggregateOperator: 'noop',
|
||||||
|
aggregateAttribute: (undefined as unknown) as BaseAutocompleteData,
|
||||||
|
dataSource: DataSource.LOGS,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
expression: 'count()',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import {
|
|||||||
TraceAggregation,
|
TraceAggregation,
|
||||||
} from 'types/api/v5/queryRange';
|
} from 'types/api/v5/queryRange';
|
||||||
import { EQueryType } from 'types/common/dashboard';
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||||
import { extractQueryPairs } from 'utils/queryContextUtils';
|
import { extractQueryPairs } from 'utils/queryContextUtils';
|
||||||
import { unquote } from 'utils/stringUtils';
|
import { unquote } from 'utils/stringUtils';
|
||||||
import { isFunctionOperator, isNonValueOperator } from 'utils/tokenUtils';
|
import { isFunctionOperator, isNonValueOperator } from 'utils/tokenUtils';
|
||||||
@ -580,14 +580,25 @@ export const convertHavingToExpression = (
|
|||||||
* @returns New aggregation format based on data source
|
* @returns New aggregation format based on data source
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const convertAggregationToExpression = (
|
export const convertAggregationToExpression = ({
|
||||||
aggregateOperator: string,
|
aggregateOperator,
|
||||||
aggregateAttribute: BaseAutocompleteData,
|
aggregateAttribute,
|
||||||
dataSource: DataSource,
|
dataSource,
|
||||||
timeAggregation?: string,
|
timeAggregation,
|
||||||
spaceAggregation?: string,
|
spaceAggregation,
|
||||||
alias?: string,
|
alias,
|
||||||
): (TraceAggregation | LogAggregation | MetricAggregation)[] | undefined => {
|
reduceTo,
|
||||||
|
temporality,
|
||||||
|
}: {
|
||||||
|
aggregateOperator: string;
|
||||||
|
aggregateAttribute: BaseAutocompleteData;
|
||||||
|
dataSource: DataSource;
|
||||||
|
timeAggregation?: string;
|
||||||
|
spaceAggregation?: string;
|
||||||
|
alias?: string;
|
||||||
|
reduceTo?: ReduceOperators;
|
||||||
|
temporality?: string;
|
||||||
|
}): (TraceAggregation | LogAggregation | MetricAggregation)[] | undefined => {
|
||||||
// Skip if no operator or attribute key
|
// Skip if no operator or attribute key
|
||||||
if (!aggregateOperator) {
|
if (!aggregateOperator) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -605,7 +616,9 @@ export const convertAggregationToExpression = (
|
|||||||
if (dataSource === DataSource.METRICS) {
|
if (dataSource === DataSource.METRICS) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
metricName: aggregateAttribute.key,
|
metricName: aggregateAttribute?.key || '',
|
||||||
|
reduceTo,
|
||||||
|
temporality,
|
||||||
timeAggregation: (normalizedTimeAggregation || normalizedOperator) as any,
|
timeAggregation: (normalizedTimeAggregation || normalizedOperator) as any,
|
||||||
spaceAggregation: (normalizedSpaceAggregation || normalizedOperator) as any,
|
spaceAggregation: (normalizedSpaceAggregation || normalizedOperator) as any,
|
||||||
} as MetricAggregation,
|
} as MetricAggregation,
|
||||||
@ -613,7 +626,9 @@ export const convertAggregationToExpression = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For traces and logs, use expression format
|
// For traces and logs, use expression format
|
||||||
const expression = `${normalizedOperator}(${aggregateAttribute.key})`;
|
const expression = aggregateAttribute?.key
|
||||||
|
? `${normalizedOperator}(${aggregateAttribute?.key})`
|
||||||
|
: `${normalizedOperator}()`;
|
||||||
|
|
||||||
if (dataSource === DataSource.TRACES) {
|
if (dataSource === DataSource.TRACES) {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@ -47,13 +47,15 @@ export const useGetCompositeQueryParam = (): Query | null => {
|
|||||||
|
|
||||||
// Convert aggregation if needed
|
// Convert aggregation if needed
|
||||||
if (!query.aggregations && query.aggregateOperator) {
|
if (!query.aggregations && query.aggregateOperator) {
|
||||||
const convertedAggregation = convertAggregationToExpression(
|
const convertedAggregation = convertAggregationToExpression({
|
||||||
query.aggregateOperator,
|
aggregateOperator: query.aggregateOperator,
|
||||||
query.aggregateAttribute as BaseAutocompleteData,
|
aggregateAttribute: query.aggregateAttribute as BaseAutocompleteData,
|
||||||
query.dataSource,
|
dataSource: query.dataSource,
|
||||||
query.timeAggregation,
|
timeAggregation: query.timeAggregation,
|
||||||
query.spaceAggregation,
|
spaceAggregation: query.spaceAggregation,
|
||||||
) as any; // Type assertion to handle union type
|
reduceTo: query.reduceTo,
|
||||||
|
temporality: query.temporality,
|
||||||
|
}) as any; // Type assertion to handle union type
|
||||||
convertedQuery.aggregations = convertedAggregation;
|
convertedQuery.aggregations = convertedAggregation;
|
||||||
}
|
}
|
||||||
return convertedQuery;
|
return convertedQuery;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user