mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-17 15:36:48 +00:00
ISSUE:2806 - View traces/logs functionality across the product with new QB (#9207)
* fix: issue-2806 view traces/logs functionality across the product with new qb * test: added test for getfilter * test: updated tests
This commit is contained in:
parent
1b818dd05d
commit
8b21ba5db9
@ -634,4 +634,260 @@ describe('prepareQueryRangePayloadV5', () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('builds payload for builder queries with filters array but no filter expression', () => {
|
||||||
|
const props: GetQueryResultsProps = {
|
||||||
|
query: {
|
||||||
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
|
id: 'q8',
|
||||||
|
unit: undefined,
|
||||||
|
promql: [],
|
||||||
|
clickhouse_sql: [],
|
||||||
|
builder: {
|
||||||
|
queryData: [
|
||||||
|
baseBuilderQuery({
|
||||||
|
dataSource: DataSource.LOGS,
|
||||||
|
filter: { expression: '' },
|
||||||
|
filters: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
key: { key: 'service.name', type: 'string' },
|
||||||
|
op: '=',
|
||||||
|
value: 'payment-service',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
key: { key: 'http.status_code', type: 'number' },
|
||||||
|
op: '>=',
|
||||||
|
value: 400,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
key: { key: 'message', type: 'string' },
|
||||||
|
op: 'contains',
|
||||||
|
value: 'error',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
op: 'AND',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
queryFormulas: [],
|
||||||
|
queryTraceOperator: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
graphType: PANEL_TYPES.LIST,
|
||||||
|
selectedTime: 'GLOBAL_TIME',
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = prepareQueryRangePayloadV5(props);
|
||||||
|
|
||||||
|
expect(result.legendMap).toEqual({ A: 'Legend A' });
|
||||||
|
expect(result.queryPayload.compositeQuery.queries).toHaveLength(1);
|
||||||
|
|
||||||
|
const builderQuery = result.queryPayload.compositeQuery.queries.find(
|
||||||
|
(q) => q.type === 'builder_query',
|
||||||
|
) as QueryEnvelope;
|
||||||
|
const logSpec = builderQuery.spec as LogBuilderQuery;
|
||||||
|
|
||||||
|
expect(logSpec.name).toBe('A');
|
||||||
|
expect(logSpec.signal).toBe('logs');
|
||||||
|
expect(logSpec.filter).toEqual({
|
||||||
|
expression:
|
||||||
|
"service.name = 'payment-service' AND http.status_code >= 400 AND message contains 'error'",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses filter.expression when only expression is provided', () => {
|
||||||
|
const props: GetQueryResultsProps = {
|
||||||
|
query: {
|
||||||
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
|
id: 'q9',
|
||||||
|
unit: undefined,
|
||||||
|
promql: [],
|
||||||
|
clickhouse_sql: [],
|
||||||
|
builder: {
|
||||||
|
queryData: [
|
||||||
|
baseBuilderQuery({
|
||||||
|
dataSource: DataSource.LOGS,
|
||||||
|
filter: { expression: 'http.status_code >= 500' },
|
||||||
|
filters: (undefined as unknown) as IBuilderQuery['filters'],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
queryFormulas: [],
|
||||||
|
queryTraceOperator: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
graphType: PANEL_TYPES.LIST,
|
||||||
|
selectedTime: 'GLOBAL_TIME',
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = prepareQueryRangePayloadV5(props);
|
||||||
|
const builderQuery = result.queryPayload.compositeQuery.queries.find(
|
||||||
|
(q) => q.type === 'builder_query',
|
||||||
|
) as QueryEnvelope;
|
||||||
|
const logSpec = builderQuery.spec as LogBuilderQuery;
|
||||||
|
expect(logSpec.filter).toEqual({ expression: 'http.status_code >= 500' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('derives expression from filters when filter is undefined', () => {
|
||||||
|
const props: GetQueryResultsProps = {
|
||||||
|
query: {
|
||||||
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
|
id: 'q10',
|
||||||
|
unit: undefined,
|
||||||
|
promql: [],
|
||||||
|
clickhouse_sql: [],
|
||||||
|
builder: {
|
||||||
|
queryData: [
|
||||||
|
baseBuilderQuery({
|
||||||
|
dataSource: DataSource.LOGS,
|
||||||
|
filter: (undefined as unknown) as IBuilderQuery['filter'],
|
||||||
|
filters: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
key: { key: 'service.name', type: 'string' },
|
||||||
|
op: '=',
|
||||||
|
value: 'checkout',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
op: 'AND',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
queryFormulas: [],
|
||||||
|
queryTraceOperator: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
graphType: PANEL_TYPES.LIST,
|
||||||
|
selectedTime: 'GLOBAL_TIME',
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = prepareQueryRangePayloadV5(props);
|
||||||
|
const builderQuery = result.queryPayload.compositeQuery.queries.find(
|
||||||
|
(q) => q.type === 'builder_query',
|
||||||
|
) as QueryEnvelope;
|
||||||
|
const logSpec = builderQuery.spec as LogBuilderQuery;
|
||||||
|
expect(logSpec.filter).toEqual({ expression: "service.name = 'checkout'" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('prefers filter.expression over filters when both are present', () => {
|
||||||
|
const props: GetQueryResultsProps = {
|
||||||
|
query: {
|
||||||
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
|
id: 'q11',
|
||||||
|
unit: undefined,
|
||||||
|
promql: [],
|
||||||
|
clickhouse_sql: [],
|
||||||
|
builder: {
|
||||||
|
queryData: [
|
||||||
|
baseBuilderQuery({
|
||||||
|
dataSource: DataSource.LOGS,
|
||||||
|
filter: { expression: "service.name = 'frontend'" },
|
||||||
|
filters: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
key: { key: 'service.name', type: 'string' },
|
||||||
|
op: '=',
|
||||||
|
value: 'backend',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
op: 'AND',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
queryFormulas: [],
|
||||||
|
queryTraceOperator: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
graphType: PANEL_TYPES.LIST,
|
||||||
|
selectedTime: 'GLOBAL_TIME',
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = prepareQueryRangePayloadV5(props);
|
||||||
|
const builderQuery = result.queryPayload.compositeQuery.queries.find(
|
||||||
|
(q) => q.type === 'builder_query',
|
||||||
|
) as QueryEnvelope;
|
||||||
|
const logSpec = builderQuery.spec as LogBuilderQuery;
|
||||||
|
expect(logSpec.filter).toEqual({ expression: "service.name = 'frontend'" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty expression when neither filter nor filters provided', () => {
|
||||||
|
const props: GetQueryResultsProps = {
|
||||||
|
query: {
|
||||||
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
|
id: 'q12',
|
||||||
|
unit: undefined,
|
||||||
|
promql: [],
|
||||||
|
clickhouse_sql: [],
|
||||||
|
builder: {
|
||||||
|
queryData: [
|
||||||
|
baseBuilderQuery({
|
||||||
|
dataSource: DataSource.LOGS,
|
||||||
|
filter: (undefined as unknown) as IBuilderQuery['filter'],
|
||||||
|
filters: (undefined as unknown) as IBuilderQuery['filters'],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
queryFormulas: [],
|
||||||
|
queryTraceOperator: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
graphType: PANEL_TYPES.LIST,
|
||||||
|
selectedTime: 'GLOBAL_TIME',
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = prepareQueryRangePayloadV5(props);
|
||||||
|
const builderQuery = result.queryPayload.compositeQuery.queries.find(
|
||||||
|
(q) => q.type === 'builder_query',
|
||||||
|
) as QueryEnvelope;
|
||||||
|
const logSpec = builderQuery.spec as LogBuilderQuery;
|
||||||
|
expect(logSpec.filter).toEqual({ expression: '' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty expression when filters provided with empty items', () => {
|
||||||
|
const props: GetQueryResultsProps = {
|
||||||
|
query: {
|
||||||
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
|
id: 'q13',
|
||||||
|
unit: undefined,
|
||||||
|
promql: [],
|
||||||
|
clickhouse_sql: [],
|
||||||
|
builder: {
|
||||||
|
queryData: [
|
||||||
|
baseBuilderQuery({
|
||||||
|
dataSource: DataSource.LOGS,
|
||||||
|
filter: { expression: '' },
|
||||||
|
filters: { items: [], op: 'AND' },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
queryFormulas: [],
|
||||||
|
queryTraceOperator: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
graphType: PANEL_TYPES.LIST,
|
||||||
|
selectedTime: 'GLOBAL_TIME',
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = prepareQueryRangePayloadV5(props);
|
||||||
|
const builderQuery = result.queryPayload.compositeQuery.queries.find(
|
||||||
|
(q) => q.type === 'builder_query',
|
||||||
|
) as QueryEnvelope;
|
||||||
|
const logSpec = builderQuery.spec as LogBuilderQuery;
|
||||||
|
expect(logSpec.filter).toEqual({ expression: '' });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
/* eslint-disable sonarjs/cognitive-complexity */
|
/* eslint-disable sonarjs/cognitive-complexity */
|
||||||
/* eslint-disable sonarjs/no-identical-functions */
|
/* eslint-disable sonarjs/no-identical-functions */
|
||||||
|
import { convertFiltersToExpression } from 'components/QueryBuilderV2/utils';
|
||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||||
import getStartEndRangeTime from 'lib/getStartEndRangeTime';
|
import getStartEndRangeTime from 'lib/getStartEndRangeTime';
|
||||||
@ -14,6 +15,7 @@ import {
|
|||||||
BaseBuilderQuery,
|
BaseBuilderQuery,
|
||||||
FieldContext,
|
FieldContext,
|
||||||
FieldDataType,
|
FieldDataType,
|
||||||
|
Filter,
|
||||||
FunctionName,
|
FunctionName,
|
||||||
GroupByKey,
|
GroupByKey,
|
||||||
Having,
|
Having,
|
||||||
@ -111,6 +113,23 @@ function isDeprecatedField(fieldName: string): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getFilter(queryData: IBuilderQuery): Filter {
|
||||||
|
const { filter } = queryData;
|
||||||
|
if (filter?.expression) {
|
||||||
|
return {
|
||||||
|
expression: filter.expression,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryData.filters && queryData.filters?.items?.length > 0) {
|
||||||
|
return convertFiltersToExpression(queryData.filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
expression: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function createBaseSpec(
|
function createBaseSpec(
|
||||||
queryData: IBuilderQuery,
|
queryData: IBuilderQuery,
|
||||||
requestType: RequestType,
|
requestType: RequestType,
|
||||||
@ -124,7 +143,7 @@ function createBaseSpec(
|
|||||||
return {
|
return {
|
||||||
stepInterval: queryData?.stepInterval || null,
|
stepInterval: queryData?.stepInterval || null,
|
||||||
disabled: queryData.disabled,
|
disabled: queryData.disabled,
|
||||||
filter: queryData?.filter?.expression ? queryData.filter : undefined,
|
filter: getFilter(queryData),
|
||||||
groupBy:
|
groupBy:
|
||||||
queryData.groupBy?.length > 0
|
queryData.groupBy?.length > 0
|
||||||
? queryData.groupBy.map(
|
? queryData.groupBy.map(
|
||||||
|
|||||||
@ -42,18 +42,31 @@ export function useNavigateToExplorer(): (
|
|||||||
builder: {
|
builder: {
|
||||||
...widgetQuery.builder,
|
...widgetQuery.builder,
|
||||||
queryData: widgetQuery.builder.queryData
|
queryData: widgetQuery.builder.queryData
|
||||||
.map((item) => ({
|
.map((item) => {
|
||||||
|
// filter out filters with unique ids
|
||||||
|
const seen = new Set();
|
||||||
|
const filterItems = [
|
||||||
|
...(item.filters?.items || []),
|
||||||
|
...selectedFilters,
|
||||||
|
].filter((item) => {
|
||||||
|
if (seen.has(item.id)) return false;
|
||||||
|
seen.add(item.id);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
...item,
|
...item,
|
||||||
dataSource,
|
dataSource,
|
||||||
aggregateOperator: MetricAggregateOperator.NOOP,
|
aggregateOperator: MetricAggregateOperator.NOOP,
|
||||||
filters: {
|
filters: {
|
||||||
...item.filters,
|
...item.filters,
|
||||||
items: [...(item.filters?.items || []), ...selectedFilters],
|
items: filterItems,
|
||||||
op: item.filters?.op || 'AND',
|
op: item.filters?.op || 'AND',
|
||||||
},
|
},
|
||||||
groupBy: [],
|
groupBy: [],
|
||||||
disabled: false,
|
disabled: false,
|
||||||
}))
|
};
|
||||||
|
})
|
||||||
.slice(0, 1),
|
.slice(0, 1),
|
||||||
queryFormulas: [],
|
queryFormulas: [],
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user