mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-17 15:36:48 +00:00
fix: added attribute check for log details filtering (#8427)
* fix: added attribute check for log details filtering * chore: added unit tests * chore: add the missing args to onClickHandler to fix the failing build --------- Co-authored-by: ahmadshaheer <ashaheerki@gmail.com>
This commit is contained in:
parent
b053ce23cd
commit
fe95ee716a
@ -58,6 +58,7 @@ export interface ActionItemProps {
|
||||
operator: string,
|
||||
isJSON?: boolean,
|
||||
dataType?: DataTypes,
|
||||
fieldType?: string,
|
||||
) => void;
|
||||
}
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ import { ResizeTable } from 'components/ResizeTable';
|
||||
import { OPERATORS } from 'constants/queryBuilder';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { RESTRICTED_SELECTED_FIELDS } from 'container/LogsFilters/config';
|
||||
import { MetricsType } from 'container/MetricsApplication/constant';
|
||||
import { FontSize, OptionsQuery } from 'container/OptionsMenu/types';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import history from 'lib/history';
|
||||
@ -113,6 +114,7 @@ function TableView({
|
||||
fieldKey: string,
|
||||
fieldValue: string,
|
||||
dataType: string | undefined,
|
||||
fieldType: string | undefined,
|
||||
): void => {
|
||||
const validatedFieldValue = removeJSONStringifyQuotes(fieldValue);
|
||||
if (onClickActionItem) {
|
||||
@ -122,6 +124,7 @@ function TableView({
|
||||
operator,
|
||||
undefined,
|
||||
dataType as DataTypes,
|
||||
fieldType,
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -131,8 +134,9 @@ function TableView({
|
||||
fieldKey: string,
|
||||
fieldValue: string,
|
||||
dataType: string | undefined,
|
||||
fieldType: MetricsType | undefined,
|
||||
) => (): void => {
|
||||
handleClick(operator, fieldKey, fieldValue, dataType);
|
||||
handleClick(operator, fieldKey, fieldValue, dataType, fieldType);
|
||||
if (operator === OPERATORS['=']) {
|
||||
setIsFilterInLoading(true);
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import { OPERATORS } from 'constants/queryBuilder';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { RESTRICTED_SELECTED_FIELDS } from 'container/LogsFilters/config';
|
||||
import { MetricsType } from 'container/MetricsApplication/constant';
|
||||
import dompurify from 'dompurify';
|
||||
import { ArrowDownToDot, ArrowUpFromDot, Ellipsis } from 'lucide-react';
|
||||
import { useTimezone } from 'providers/Timezone';
|
||||
@ -46,6 +47,7 @@ interface ITableViewActionsProps {
|
||||
fieldKey: string,
|
||||
fieldValue: string,
|
||||
dataType: string | undefined,
|
||||
logType: MetricsType | undefined,
|
||||
) => () => void;
|
||||
}
|
||||
|
||||
@ -127,7 +129,7 @@ export default function TableViewActions(
|
||||
} = props;
|
||||
|
||||
const { pathname } = useLocation();
|
||||
const { dataType } = getFieldAttributes(record.field);
|
||||
const { dataType, logType: fieldType } = getFieldAttributes(record.field);
|
||||
|
||||
// there is no option for where clause in old logs explorer and live logs page
|
||||
const isOldLogsExplorerOrLiveLogsPage = useMemo(
|
||||
@ -234,6 +236,7 @@ export default function TableViewActions(
|
||||
fieldFilterKey,
|
||||
parseFieldValue(fieldData.value),
|
||||
dataType,
|
||||
fieldType,
|
||||
)}
|
||||
/>
|
||||
</Tooltip>
|
||||
@ -252,6 +255,7 @@ export default function TableViewActions(
|
||||
fieldFilterKey,
|
||||
parseFieldValue(fieldData.value),
|
||||
dataType,
|
||||
fieldType,
|
||||
)}
|
||||
/>
|
||||
</Tooltip>
|
||||
@ -312,6 +316,7 @@ export default function TableViewActions(
|
||||
fieldFilterKey,
|
||||
parseFieldValue(fieldData.value),
|
||||
dataType,
|
||||
fieldType,
|
||||
)}
|
||||
/>
|
||||
</Tooltip>
|
||||
@ -330,6 +335,7 @@ export default function TableViewActions(
|
||||
fieldFilterKey,
|
||||
parseFieldValue(fieldData.value),
|
||||
dataType,
|
||||
fieldType,
|
||||
)}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
@ -2,6 +2,7 @@ import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys';
|
||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
||||
import { OPERATORS, QueryBuilderKeys } from 'constants/queryBuilder';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { MetricsType } from 'container/MetricsApplication/constant';
|
||||
import { getOperatorValue } from 'container/QueryBuilder/filters/QueryBuilderSearch/utils';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
@ -82,6 +83,7 @@ export const useActiveLog = (): UseActiveLog => {
|
||||
operator: string,
|
||||
isJSON?: boolean,
|
||||
dataType?: DataTypes,
|
||||
fieldType?: MetricsType | undefined,
|
||||
): Promise<void> => {
|
||||
try {
|
||||
const keysAutocompleteResponse = await queryClient.fetchQuery(
|
||||
@ -104,6 +106,7 @@ export const useActiveLog = (): UseActiveLog => {
|
||||
fieldKey,
|
||||
isJSON,
|
||||
dataType,
|
||||
fieldType,
|
||||
);
|
||||
|
||||
const currentOperator = getOperatorValue(operator);
|
||||
|
||||
@ -1,9 +1,14 @@
|
||||
import { initialAutocompleteData } from 'constants/queryBuilder';
|
||||
import {
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
initialAutocompleteData,
|
||||
} from 'constants/queryBuilder';
|
||||
import { MetricsType } from 'container/MetricsApplication/constant';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
DataTypes,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
import { createIdFromObjectFields } from '../createIdFromObjectFields';
|
||||
import { chooseAutocompleteFromCustomValue } from '../newQueryBuilder/chooseAutocompleteFromCustomValue';
|
||||
|
||||
describe('chooseAutocompleteFromCustomValue', () => {
|
||||
@ -13,36 +18,108 @@ describe('chooseAutocompleteFromCustomValue', () => {
|
||||
key: 'string_key',
|
||||
dataType: DataTypes.String,
|
||||
isJSON: false,
|
||||
isColumn: false,
|
||||
type: '',
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
key: 'string_key',
|
||||
isColumn: false,
|
||||
type: '',
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'number_key',
|
||||
dataType: DataTypes.Float64,
|
||||
isJSON: false,
|
||||
isColumn: false,
|
||||
type: '',
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.Float64,
|
||||
key: 'number_key',
|
||||
isColumn: false,
|
||||
type: '',
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'bool_key',
|
||||
dataType: DataTypes.bool,
|
||||
isJSON: false,
|
||||
isColumn: false,
|
||||
type: '',
|
||||
id: createIdFromObjectFields(
|
||||
{ dataType: DataTypes.bool, key: 'bool_key', isColumn: false, type: '' },
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'float_key',
|
||||
dataType: DataTypes.Float64,
|
||||
isJSON: false,
|
||||
isColumn: false,
|
||||
type: '',
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.Float64,
|
||||
key: 'float_key',
|
||||
isColumn: false,
|
||||
type: '',
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'unknown_key',
|
||||
dataType: DataTypes.EMPTY,
|
||||
isJSON: false,
|
||||
isColumn: false,
|
||||
type: '',
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.EMPTY,
|
||||
key: 'unknown_key',
|
||||
isColumn: false,
|
||||
type: '',
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'duplicate_key',
|
||||
dataType: DataTypes.String,
|
||||
isJSON: false,
|
||||
isColumn: false,
|
||||
type: '',
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
key: 'duplicate_key',
|
||||
isColumn: false,
|
||||
type: '',
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'duplicate_key',
|
||||
dataType: DataTypes.Float64,
|
||||
isJSON: false,
|
||||
isColumn: false,
|
||||
type: '',
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.Float64,
|
||||
key: 'duplicate_key',
|
||||
isColumn: false,
|
||||
type: '',
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
] as BaseAutocompleteData[];
|
||||
|
||||
@ -115,7 +192,23 @@ describe('chooseAutocompleteFromCustomValue', () => {
|
||||
// Test case: Perfect match with isJSON true in sourceList
|
||||
it('should return matching element with isJSON true', () => {
|
||||
const jsonSourceList = [
|
||||
{ key: 'json_key', dataType: DataTypes.String, isJSON: true },
|
||||
{
|
||||
key: 'json_key',
|
||||
dataType: DataTypes.String,
|
||||
isJSON: true,
|
||||
isColumn: false,
|
||||
type: '',
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
key: 'json_key',
|
||||
isColumn: false,
|
||||
type: '',
|
||||
isJSON: true,
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
];
|
||||
const result = chooseAutocompleteFromCustomValue(
|
||||
jsonSourceList as BaseAutocompleteData[],
|
||||
@ -293,4 +386,258 @@ describe('chooseAutocompleteFromCustomValue', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when element with same value, same data type, and same fieldType found in sourceList', () => {
|
||||
const fieldTypeMockSourceList = [
|
||||
{
|
||||
key: 'tag_key',
|
||||
dataType: DataTypes.String,
|
||||
isJSON: false,
|
||||
type: MetricsType.Tag,
|
||||
isColumn: false,
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
key: 'tag_key',
|
||||
isColumn: false,
|
||||
type: MetricsType.Tag,
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'resource_key',
|
||||
dataType: DataTypes.Float64,
|
||||
isJSON: false,
|
||||
type: MetricsType.Resource,
|
||||
isColumn: false,
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.Float64,
|
||||
key: 'resource_key',
|
||||
isColumn: false,
|
||||
type: MetricsType.Resource,
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'scope_key',
|
||||
dataType: DataTypes.bool,
|
||||
isJSON: false,
|
||||
type: MetricsType.Scope,
|
||||
isColumn: false,
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.bool,
|
||||
key: 'scope_key',
|
||||
isColumn: false,
|
||||
type: MetricsType.Scope,
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'tag_key_duplicate',
|
||||
dataType: DataTypes.String,
|
||||
isJSON: false,
|
||||
type: MetricsType.Tag,
|
||||
isColumn: false,
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
key: 'tag_key_duplicate',
|
||||
isColumn: false,
|
||||
type: MetricsType.Tag,
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'tag_key_duplicate',
|
||||
dataType: DataTypes.String,
|
||||
isJSON: false,
|
||||
type: MetricsType.Resource,
|
||||
isColumn: false,
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
key: 'tag_key_duplicate',
|
||||
isColumn: false,
|
||||
type: MetricsType.Resource,
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
] as BaseAutocompleteData[];
|
||||
|
||||
it('should return matching element for Tag fieldType', () => {
|
||||
const result = chooseAutocompleteFromCustomValue(
|
||||
fieldTypeMockSourceList,
|
||||
'tag_key',
|
||||
false,
|
||||
'string' as DataTypes,
|
||||
MetricsType.Tag,
|
||||
);
|
||||
expect(result).toEqual(fieldTypeMockSourceList[0]);
|
||||
});
|
||||
|
||||
it('should return matching element for Resource fieldType', () => {
|
||||
const result = chooseAutocompleteFromCustomValue(
|
||||
fieldTypeMockSourceList,
|
||||
'resource_key',
|
||||
false,
|
||||
'number' as DataTypes,
|
||||
MetricsType.Resource,
|
||||
);
|
||||
expect(result).toEqual(fieldTypeMockSourceList[1]);
|
||||
});
|
||||
|
||||
it('should return matching element for Scope fieldType', () => {
|
||||
const result = chooseAutocompleteFromCustomValue(
|
||||
fieldTypeMockSourceList,
|
||||
'scope_key',
|
||||
false,
|
||||
'bool' as DataTypes,
|
||||
MetricsType.Scope,
|
||||
);
|
||||
expect(result).toEqual(fieldTypeMockSourceList[2]);
|
||||
});
|
||||
|
||||
it('should return the correct duplicate with matching fieldType', () => {
|
||||
const result = chooseAutocompleteFromCustomValue(
|
||||
fieldTypeMockSourceList,
|
||||
'tag_key_duplicate',
|
||||
false,
|
||||
'string' as DataTypes,
|
||||
MetricsType.Resource,
|
||||
);
|
||||
expect(result).toEqual(fieldTypeMockSourceList[4]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when element with same value and data type but different fieldType found in sourceList', () => {
|
||||
const fieldTypeMockSourceList = [
|
||||
{
|
||||
key: 'test_key',
|
||||
dataType: DataTypes.String,
|
||||
isJSON: false,
|
||||
type: MetricsType.Tag,
|
||||
isColumn: false,
|
||||
id: createIdFromObjectFields(
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
key: 'test_key',
|
||||
isColumn: false,
|
||||
type: MetricsType.Tag,
|
||||
},
|
||||
baseAutoCompleteIdKeysOrder,
|
||||
),
|
||||
},
|
||||
] as BaseAutocompleteData[];
|
||||
|
||||
it('should return new object with updated fieldType when existing element has different fieldType', () => {
|
||||
const result = chooseAutocompleteFromCustomValue(
|
||||
fieldTypeMockSourceList,
|
||||
'test_key',
|
||||
false,
|
||||
'string' as DataTypes,
|
||||
MetricsType.Resource,
|
||||
);
|
||||
expect(result).toEqual({
|
||||
...initialAutocompleteData,
|
||||
key: 'test_key',
|
||||
dataType: DataTypes.String,
|
||||
isJSON: false,
|
||||
type: MetricsType.Resource,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when element not found in sourceList but fieldType is provided', () => {
|
||||
it('should return new object with Tag fieldType', () => {
|
||||
const result = chooseAutocompleteFromCustomValue(
|
||||
mockSourceList,
|
||||
'new_key_with_tag_type',
|
||||
false,
|
||||
'string' as DataTypes,
|
||||
MetricsType.Tag,
|
||||
);
|
||||
expect(result).toEqual({
|
||||
...initialAutocompleteData,
|
||||
key: 'new_key_with_tag_type',
|
||||
dataType: DataTypes.String,
|
||||
isJSON: false,
|
||||
type: MetricsType.Tag,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return new object with Resource fieldType', () => {
|
||||
const result = chooseAutocompleteFromCustomValue(
|
||||
mockSourceList,
|
||||
'new_key_with_resource_type',
|
||||
false,
|
||||
'number' as DataTypes,
|
||||
MetricsType.Resource,
|
||||
);
|
||||
expect(result).toEqual({
|
||||
...initialAutocompleteData,
|
||||
key: 'new_key_with_resource_type',
|
||||
dataType: DataTypes.Float64,
|
||||
isJSON: false,
|
||||
type: MetricsType.Resource,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return new object with Scope fieldType', () => {
|
||||
const result = chooseAutocompleteFromCustomValue(
|
||||
mockSourceList,
|
||||
'new_key_with_scope_type',
|
||||
false,
|
||||
'bool' as DataTypes,
|
||||
MetricsType.Scope,
|
||||
);
|
||||
expect(result).toEqual({
|
||||
...initialAutocompleteData,
|
||||
key: 'new_key_with_scope_type',
|
||||
dataType: DataTypes.bool,
|
||||
isJSON: false,
|
||||
type: MetricsType.Scope,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return new object with empty fieldType when undefined is passed', () => {
|
||||
const result = chooseAutocompleteFromCustomValue(
|
||||
mockSourceList,
|
||||
'new_key_with_undefined_type',
|
||||
false,
|
||||
'string' as DataTypes,
|
||||
undefined,
|
||||
);
|
||||
expect(result).toEqual({
|
||||
...initialAutocompleteData,
|
||||
key: 'new_key_with_undefined_type',
|
||||
dataType: DataTypes.String,
|
||||
isJSON: false,
|
||||
type: '',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return new object with isJSON true and fieldType when not found', () => {
|
||||
const result = chooseAutocompleteFromCustomValue(
|
||||
mockSourceList,
|
||||
'json_not_found_with_type',
|
||||
true,
|
||||
'string' as DataTypes,
|
||||
MetricsType.Tag,
|
||||
);
|
||||
expect(result).toEqual({
|
||||
...initialAutocompleteData,
|
||||
key: 'json_not_found_with_type',
|
||||
dataType: DataTypes.String,
|
||||
isJSON: true,
|
||||
type: MetricsType.Tag,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { initialAutocompleteData } from 'constants/queryBuilder';
|
||||
import { MetricsType } from 'container/MetricsApplication/constant';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
DataTypes,
|
||||
@ -25,12 +26,15 @@ export const chooseAutocompleteFromCustomValue = (
|
||||
value: string,
|
||||
isJSON?: boolean,
|
||||
dataType?: DataTypes | 'number',
|
||||
fieldType?: MetricsType | undefined,
|
||||
): BaseAutocompleteData => {
|
||||
const dataTypeToUse = getDataTypeForCustomValue(dataType);
|
||||
const firstBaseAutoCompleteValue = sourceList.find(
|
||||
(sourceAutoComplete) =>
|
||||
value === sourceAutoComplete.key &&
|
||||
(dataType === undefined || dataTypeToUse === sourceAutoComplete.dataType),
|
||||
(dataType === undefined || dataTypeToUse === sourceAutoComplete.dataType) &&
|
||||
((fieldType === undefined && sourceAutoComplete.type === '') ||
|
||||
(fieldType !== undefined && fieldType === sourceAutoComplete.type)),
|
||||
);
|
||||
|
||||
if (!firstBaseAutoCompleteValue) {
|
||||
@ -38,6 +42,7 @@ export const chooseAutocompleteFromCustomValue = (
|
||||
...initialAutocompleteData,
|
||||
key: value,
|
||||
dataType: dataTypeToUse,
|
||||
type: fieldType || '',
|
||||
isJSON,
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user