mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-24 10:56:53 +00:00
feat: new qb selectedfields changes for logs and traces
This commit is contained in:
parent
dfccbe0314
commit
10b5283edd
@ -9,5 +9,9 @@ export const getKeySuggestions = (
|
||||
props: QueryKeyRequestProps,
|
||||
): Promise<AxiosResponse<QueryKeySuggestionsResponseProps>> =>
|
||||
axios.get(
|
||||
`/fields/keys?signal=${props.signal}&name=${props.name}&metricName=${props.metricName}`,
|
||||
`/fields/keys?signal=${props.signal}&searchText=${
|
||||
props.searchText
|
||||
}&metricName=${props.metricName ?? ''}&fieldContext=${
|
||||
props.fieldContext ?? ''
|
||||
}&fieldDataType=${props.fieldDataType ?? ''}`,
|
||||
);
|
||||
|
||||
@ -4,7 +4,6 @@ import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import getStartEndRangeTime from 'lib/getStartEndRangeTime';
|
||||
import { mapQueryDataToApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataToApi';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import {
|
||||
IBuilderQuery,
|
||||
QueryFunctionProps,
|
||||
@ -126,10 +125,12 @@ function createBaseSpec(
|
||||
selectFields: isEmpty(queryData.selectColumns)
|
||||
? undefined
|
||||
: queryData.selectColumns?.map(
|
||||
(column: BaseAutocompleteData): TelemetryFieldKey => ({
|
||||
name: column.key,
|
||||
fieldDataType: column?.dataType as FieldDataType,
|
||||
fieldContext: column?.type as FieldContext,
|
||||
(column: any): TelemetryFieldKey => ({
|
||||
name: column.name ?? column.key,
|
||||
fieldDataType:
|
||||
column?.fieldDataType ?? (column?.dataType as FieldDataType),
|
||||
fieldContext: column?.fieldContext ?? (column?.type as FieldContext),
|
||||
signal: column?.signal ?? undefined,
|
||||
}),
|
||||
),
|
||||
};
|
||||
|
||||
@ -410,18 +410,18 @@ export default function LogsFormatOptionsMenu({
|
||||
)}
|
||||
|
||||
<div className="column-format">
|
||||
{addColumn?.value?.map(({ key, id }) => (
|
||||
<div className="column-name" key={id}>
|
||||
{addColumn?.value?.map(({ name }) => (
|
||||
<div className="column-name" key={name}>
|
||||
<div className="name">
|
||||
<Tooltip placement="left" title={key}>
|
||||
{key}
|
||||
<Tooltip placement="left" title={name}>
|
||||
{name}
|
||||
</Tooltip>
|
||||
</div>
|
||||
{addColumn?.value?.length > 1 && (
|
||||
<X
|
||||
className="delete-btn"
|
||||
size={14}
|
||||
onClick={(): void => addColumn.onRemove(id as string)}
|
||||
onClick={(): void => addColumn.onRemove(name)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -143,7 +143,7 @@ function QuerySearch({
|
||||
const fetchKeySuggestions = async (searchText?: string): Promise<void> => {
|
||||
const response = await getKeySuggestions({
|
||||
signal: dataSource,
|
||||
name: searchText || '',
|
||||
searchText: searchText || '',
|
||||
metricName: queryData.aggregateAttribute.key ?? undefined,
|
||||
});
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ import {
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import axios from 'axios';
|
||||
import cx from 'classnames';
|
||||
import { getViewDetailsUsingViewKey } from 'components/ExplorerCard/utils';
|
||||
@ -58,7 +59,6 @@ import {
|
||||
} from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { ViewProps } from 'types/api/saveViews/types';
|
||||
import { DataSource, StringOperators } from 'types/common/queryBuilder';
|
||||
@ -253,7 +253,7 @@ function ExplorerOptions({
|
||||
|
||||
const getUpdatedExtraData = (
|
||||
extraData: string | undefined,
|
||||
newSelectedColumns: BaseAutocompleteData[],
|
||||
newSelectedColumns: TelemetryFieldKey[],
|
||||
formattingOptions?: FormattingOptions,
|
||||
): string => {
|
||||
let updatedExtraData;
|
||||
@ -337,7 +337,7 @@ function ExplorerOptions({
|
||||
const { handleExplorerTabChange } = useHandleExplorerTabChange();
|
||||
|
||||
type ExtraData = {
|
||||
selectColumns?: BaseAutocompleteData[];
|
||||
selectColumns?: TelemetryFieldKey[];
|
||||
version?: number;
|
||||
};
|
||||
|
||||
|
||||
@ -87,8 +87,9 @@ function TableView({
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
selectedOptions.selectColumns.forEach((val) => {
|
||||
const path = findKeyPath(logData, val.key, '');
|
||||
const path = findKeyPath(logData, val.name, '');
|
||||
if (path) {
|
||||
pinnedAttributes[path] = true;
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { IField } from 'types/api/logs/fields';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
export const convertKeysToColumnFields = (
|
||||
keys: BaseAutocompleteData[],
|
||||
keys: TelemetryFieldKey[],
|
||||
): IField[] =>
|
||||
keys.map((item) => ({
|
||||
dataType: item.dataType as string,
|
||||
name: item.key,
|
||||
type: item.type as string,
|
||||
dataType: item.fieldDataType ?? '',
|
||||
name: item.name,
|
||||
type: item.fieldContext ?? '',
|
||||
}));
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { defaultTraceSelectedColumns } from 'container/OptionsMenu/constants';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { LogsAggregatorOperator } from 'types/common/queryBuilder';
|
||||
|
||||
@ -43,48 +43,7 @@ export const listViewInitialTraceQuery = {
|
||||
orderBy: [{ columnName: 'timestamp', order: 'desc' }],
|
||||
offset: 0,
|
||||
pageSize: 10,
|
||||
selectColumns: [
|
||||
{
|
||||
key: 'serviceName',
|
||||
dataType: 'string',
|
||||
type: 'tag',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'serviceName--string--tag--true',
|
||||
},
|
||||
{
|
||||
key: 'name',
|
||||
dataType: 'string',
|
||||
type: 'tag',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'name--string--tag--true',
|
||||
},
|
||||
{
|
||||
key: 'durationNano',
|
||||
dataType: 'float64',
|
||||
type: 'tag',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'durationNano--float64--tag--true',
|
||||
},
|
||||
{
|
||||
key: 'httpMethod',
|
||||
dataType: 'string',
|
||||
type: 'tag',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'httpMethod--string--tag--true',
|
||||
},
|
||||
{
|
||||
key: 'responseStatusCode',
|
||||
dataType: 'string',
|
||||
type: 'tag',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'responseStatusCode--string--tag--true',
|
||||
},
|
||||
] as BaseAutocompleteData[],
|
||||
selectColumns: defaultTraceSelectedColumns,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@ -25,9 +25,11 @@ function ExplorerAttributeColumns({
|
||||
}
|
||||
|
||||
const filteredAttributeKeys =
|
||||
data?.payload?.attributeKeys?.filter((attributeKey: any) =>
|
||||
attributeKey.key.toLowerCase().includes(searchText.toLowerCase()),
|
||||
) || [];
|
||||
Object.values(data?.data?.data?.keys || {})
|
||||
?.flat()
|
||||
?.filter((attributeKey: any) =>
|
||||
attributeKey.name.toLowerCase().includes(searchText.toLowerCase()),
|
||||
) || [];
|
||||
if (filteredAttributeKeys.length === 0) {
|
||||
return (
|
||||
<div className="attribute-columns">
|
||||
@ -36,16 +38,17 @@ function ExplorerAttributeColumns({
|
||||
);
|
||||
}
|
||||
|
||||
console.log('filteredAttributeKeys', filteredAttributeKeys, data);
|
||||
return (
|
||||
<div className="attribute-columns">
|
||||
{filteredAttributeKeys.map((attributeKey: any) => (
|
||||
<Checkbox
|
||||
checked={isAttributeKeySelected(attributeKey.key)}
|
||||
onChange={(): void => handleCheckboxChange(attributeKey.key)}
|
||||
checked={isAttributeKeySelected(attributeKey.name)}
|
||||
onChange={(): void => handleCheckboxChange(attributeKey.name)}
|
||||
style={{ padding: 0 }}
|
||||
key={attributeKey.key}
|
||||
key={attributeKey.name}
|
||||
>
|
||||
{attributeKey.key}
|
||||
{attributeKey.name}
|
||||
</Checkbox>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable sonarjs/no-identical-functions */
|
||||
/* eslint-disable sonarjs/cognitive-complexity */
|
||||
/* eslint-disable react/jsx-props-no-spreading */
|
||||
import './ExplorerColumnsRenderer.styles.scss';
|
||||
@ -5,9 +6,10 @@ import './ExplorerColumnsRenderer.styles.scss';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Divider, Dropdown, Input, Tooltip, Typography } from 'antd';
|
||||
import { MenuProps } from 'antd/lib';
|
||||
import { FieldDataType } from 'api/v5/v5';
|
||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
||||
import { useGetAggregateKeys } from 'hooks/queryBuilder/useGetAggregateKeys';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { useGetQueryKeySuggestions } from 'hooks/querySuggestions/useGetQueryKeySuggestions';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import useDebouncedFn from 'hooks/useDebouncedFunction';
|
||||
import {
|
||||
@ -49,13 +51,27 @@ function ExplorerColumnsRenderer({
|
||||
|
||||
const initialDataSource = currentQuery.builder.queryData[0].dataSource;
|
||||
|
||||
const { data, isLoading, isError } = useGetAggregateKeys(
|
||||
// const { data, isLoading, isError } = useGetAggregateKeys(
|
||||
// {
|
||||
// aggregateAttribute: '',
|
||||
// dataSource: currentQuery.builder.queryData[0].dataSource,
|
||||
// aggregateOperator: currentQuery.builder.queryData[0].aggregateOperator,
|
||||
// searchText: querySearchText,
|
||||
// tagType: '',
|
||||
// },
|
||||
// {
|
||||
// queryKey: [
|
||||
// currentQuery.builder.queryData[0].dataSource,
|
||||
// currentQuery.builder.queryData[0].aggregateOperator,
|
||||
// querySearchText,
|
||||
// ],
|
||||
// },
|
||||
// );
|
||||
|
||||
const { data, isLoading, isError } = useGetQueryKeySuggestions(
|
||||
{
|
||||
aggregateAttribute: '',
|
||||
dataSource: currentQuery.builder.queryData[0].dataSource,
|
||||
aggregateOperator: currentQuery.builder.queryData[0].aggregateOperator,
|
||||
searchText: querySearchText,
|
||||
tagType: '',
|
||||
signal: currentQuery.builder.queryData[0].dataSource,
|
||||
},
|
||||
{
|
||||
queryKey: [
|
||||
@ -71,7 +87,7 @@ function ExplorerColumnsRenderer({
|
||||
return selectedLogFields.some((field) => field.name === key);
|
||||
}
|
||||
if (initialDataSource === DataSource.TRACES && selectedTracesFields) {
|
||||
return selectedTracesFields.some((field) => field.key === key);
|
||||
return selectedTracesFields.some((field) => field.name === key);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@ -99,18 +115,31 @@ function ExplorerColumnsRenderer({
|
||||
initialDataSource === DataSource.TRACES &&
|
||||
setSelectedTracesFields !== undefined
|
||||
) {
|
||||
const selectedField = data?.payload?.attributeKeys?.find(
|
||||
(attributeKey) => attributeKey.key === key,
|
||||
);
|
||||
const selectedField = Object.values(data?.data?.data?.keys || {})
|
||||
?.flat()
|
||||
?.find((attributeKey) => attributeKey.name === key);
|
||||
console.log('selectedField', selectedField);
|
||||
if (selectedTracesFields) {
|
||||
if (isAttributeKeySelected(key)) {
|
||||
setSelectedTracesFields(
|
||||
selectedTracesFields.filter((field) => field.key !== key),
|
||||
selectedTracesFields.filter((field) => field.name !== key),
|
||||
);
|
||||
} else if (selectedField) {
|
||||
setSelectedTracesFields([...selectedTracesFields, selectedField]);
|
||||
setSelectedTracesFields([
|
||||
...selectedTracesFields,
|
||||
{
|
||||
...selectedField,
|
||||
fieldDataType: selectedField.fieldDataType as FieldDataType,
|
||||
},
|
||||
]);
|
||||
}
|
||||
} else if (selectedField) setSelectedTracesFields([selectedField]);
|
||||
} else if (selectedField)
|
||||
setSelectedTracesFields([
|
||||
{
|
||||
...selectedField,
|
||||
fieldDataType: selectedField.fieldDataType as FieldDataType,
|
||||
},
|
||||
]);
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
@ -175,7 +204,7 @@ function ExplorerColumnsRenderer({
|
||||
selectedTracesFields
|
||||
) {
|
||||
setSelectedTracesFields(
|
||||
selectedTracesFields.filter((field) => field.key !== name),
|
||||
selectedTracesFields.filter((field) => field.name !== name),
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -218,6 +247,8 @@ function ExplorerColumnsRenderer({
|
||||
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
console.log('selectedTracesFields', selectedTracesFields, selectedLogFields);
|
||||
|
||||
return (
|
||||
<div className="explorer-columns-renderer">
|
||||
<div className="title">
|
||||
@ -279,12 +310,14 @@ function ExplorerColumnsRenderer({
|
||||
>
|
||||
<div className="explorer-column-title">
|
||||
<GripVertical size={12} color="#5A5A5A" />
|
||||
{field.key}
|
||||
{field?.name || (field as any)?.key}
|
||||
</div>
|
||||
<Trash2
|
||||
size={12}
|
||||
color="red"
|
||||
onClick={(): void => removeSelectedLogField(field.key)}
|
||||
onClick={(): void =>
|
||||
removeSelectedLogField(field?.name || (field as any)?.key)
|
||||
}
|
||||
data-testid="trash-icon"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -3,14 +3,12 @@
|
||||
/* eslint-disable react/jsx-props-no-spreading */
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { useGetAggregateKeys } from 'hooks/queryBuilder/useGetAggregateKeys';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import React from 'react';
|
||||
import { DropResult } from 'react-beautiful-dnd';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
DataTypes,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import ExplorerColumnsRenderer from '../ExplorerColumnsRenderer';
|
||||
@ -321,7 +319,11 @@ describe('ExplorerColumnsRenderer', () => {
|
||||
selectedLogFields={[]}
|
||||
setSelectedLogFields={mockSetSelectedLogFields}
|
||||
selectedTracesFields={[
|
||||
{ key: 'trace_attribute1', dataType: DataTypes.String, type: 'tag' },
|
||||
{
|
||||
name: 'trace_attribute1',
|
||||
fieldDataType: DataTypes.String,
|
||||
fieldContext: '',
|
||||
},
|
||||
]}
|
||||
setSelectedTracesFields={mockSetSelectedTracesFields}
|
||||
/>,
|
||||
@ -340,7 +342,11 @@ describe('ExplorerColumnsRenderer', () => {
|
||||
selectedLogFields={[]}
|
||||
setSelectedLogFields={mockSetSelectedLogFields}
|
||||
selectedTracesFields={[
|
||||
{ key: 'trace_attribute1', dataType: DataTypes.String, type: 'tag' },
|
||||
{
|
||||
name: 'trace_attribute1',
|
||||
fieldDataType: DataTypes.String,
|
||||
fieldContext: '',
|
||||
},
|
||||
]}
|
||||
setSelectedTracesFields={mockSetSelectedTracesFields}
|
||||
/>,
|
||||
@ -355,15 +361,15 @@ describe('ExplorerColumnsRenderer', () => {
|
||||
|
||||
it('reorders trace fields on drag and drop', () => {
|
||||
const initialSelectedFields = [
|
||||
{ key: 'trace_field1', dataType: 'string', type: 'tag' },
|
||||
{ key: 'trace_field2', dataType: 'string', type: 'tag' },
|
||||
{ name: 'trace_field1', fieldDataType: 'string', fieldContext: 'tag' },
|
||||
{ name: 'trace_field2', fieldDataType: 'string', fieldContext: 'tag' },
|
||||
];
|
||||
|
||||
render(
|
||||
<ExplorerColumnsRenderer
|
||||
selectedLogFields={[]}
|
||||
setSelectedLogFields={mockSetSelectedLogFields}
|
||||
selectedTracesFields={initialSelectedFields as BaseAutocompleteData[]}
|
||||
selectedTracesFields={initialSelectedFields as TelemetryFieldKey[]}
|
||||
setSelectedTracesFields={mockSetSelectedTracesFields}
|
||||
/>,
|
||||
);
|
||||
@ -383,8 +389,8 @@ describe('ExplorerColumnsRenderer', () => {
|
||||
});
|
||||
|
||||
expect(mockSetSelectedTracesFields).toHaveBeenCalledWith([
|
||||
{ key: 'trace_field2', dataType: 'string', type: 'tag' },
|
||||
{ key: 'trace_field1', dataType: 'string', type: 'tag' },
|
||||
{ name: 'trace_field2', fieldDataType: 'string', fieldContext: 'tag' },
|
||||
{ name: 'trace_field1', fieldDataType: 'string', fieldContext: 'tag' },
|
||||
]);
|
||||
} else {
|
||||
fail('DragDropContext or onDragEndMock not found');
|
||||
|
||||
@ -6,9 +6,12 @@ import {
|
||||
} from 'constants/queryBuilder';
|
||||
import {
|
||||
listViewInitialLogQuery,
|
||||
listViewInitialTraceQuery,
|
||||
PANEL_TYPES_INITIAL_QUERY,
|
||||
} from 'container/NewDashboard/ComponentsSlider/constants';
|
||||
import {
|
||||
defaultLogsSelectedColumns,
|
||||
defaultTraceSelectedColumns,
|
||||
} from 'container/OptionsMenu/constants';
|
||||
import { categoryToSupport } from 'container/QueryBuilder/filters/BuilderUnitsFilter/config';
|
||||
import { cloneDeep, defaultTo, isEmpty, isEqual, set, unset } from 'lodash-es';
|
||||
import { Layout } from 'react-grid-layout';
|
||||
@ -503,7 +506,6 @@ export function handleQueryChange(
|
||||
supersetQuery: Query,
|
||||
currentPanelType: PANEL_TYPES,
|
||||
): Query {
|
||||
console.log('supersetQuery', supersetQuery);
|
||||
return {
|
||||
...supersetQuery,
|
||||
builder: {
|
||||
@ -564,21 +566,12 @@ export const getDefaultWidgetData = (
|
||||
timePreferance: 'GLOBAL_TIME',
|
||||
softMax: null,
|
||||
softMin: null,
|
||||
selectedLogFields: [
|
||||
{
|
||||
dataType: 'string',
|
||||
type: '',
|
||||
name: 'body',
|
||||
},
|
||||
{
|
||||
dataType: 'string',
|
||||
type: '',
|
||||
name: 'timestamp',
|
||||
},
|
||||
],
|
||||
selectedTracesFields: [
|
||||
...listViewInitialTraceQuery.builder.queryData[0].selectColumns,
|
||||
],
|
||||
selectedLogFields: defaultLogsSelectedColumns.map((field) => ({
|
||||
...field,
|
||||
type: field.fieldContext ?? '',
|
||||
dataType: field.fieldDataType ?? '',
|
||||
})),
|
||||
selectedTracesFields: defaultTraceSelectedColumns,
|
||||
});
|
||||
|
||||
export const PANEL_TYPE_TO_QUERY_TYPES: Record<PANEL_TYPES, EQueryType[]> = {
|
||||
|
||||
@ -42,10 +42,10 @@ function AddColumnField({ config }: AddColumnFieldProps): JSX.Element | null {
|
||||
</SearchIconWrapper>
|
||||
</Input.Group>
|
||||
|
||||
{config.value?.map(({ key, id }) => (
|
||||
<AddColumnItem direction="horizontal" key={id}>
|
||||
<Typography>{key}</Typography>
|
||||
<DeleteOutlinedIcon onClick={(): void => config.onRemove(id as string)} />
|
||||
{config.value?.map(({ name }) => (
|
||||
<AddColumnItem direction="horizontal" key={name}>
|
||||
<Typography>{name}</Typography>
|
||||
<DeleteOutlinedIcon onClick={(): void => config.onRemove(name)} />
|
||||
</AddColumnItem>
|
||||
))}
|
||||
</AddColumnWrapper>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
|
||||
import { FontSize, OptionsQuery } from './types';
|
||||
|
||||
@ -11,71 +11,56 @@ export const defaultOptionsQuery: OptionsQuery = {
|
||||
fontSize: FontSize.SMALL,
|
||||
};
|
||||
|
||||
export const defaultLogsSelectedColumns = [
|
||||
export const defaultLogsSelectedColumns: TelemetryFieldKey[] = [
|
||||
{
|
||||
key: 'timestamp',
|
||||
dataType: DataTypes.String,
|
||||
type: 'tag',
|
||||
name: 'timestamp',
|
||||
signal: 'logs',
|
||||
fieldContext: 'log',
|
||||
fieldDataType: '',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'timestamp--string--tag--true',
|
||||
isIndexed: false,
|
||||
},
|
||||
{
|
||||
key: 'body',
|
||||
dataType: DataTypes.String,
|
||||
type: 'tag',
|
||||
name: 'body',
|
||||
signal: 'logs',
|
||||
fieldContext: 'log',
|
||||
fieldDataType: '',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'body--string--tag--true',
|
||||
isIndexed: false,
|
||||
},
|
||||
];
|
||||
|
||||
export const defaultTraceSelectedColumns = [
|
||||
export const defaultTraceSelectedColumns: TelemetryFieldKey[] = [
|
||||
{
|
||||
key: 'serviceName',
|
||||
dataType: DataTypes.String,
|
||||
type: 'tag',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'serviceName--string--tag--true',
|
||||
isIndexed: false,
|
||||
name: 'service.name',
|
||||
signal: 'traces',
|
||||
fieldContext: 'resource',
|
||||
fieldDataType: 'string',
|
||||
},
|
||||
{
|
||||
key: 'name',
|
||||
dataType: DataTypes.String,
|
||||
type: 'tag',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'name--string--tag--true',
|
||||
isIndexed: false,
|
||||
name: 'name',
|
||||
signal: 'traces',
|
||||
fieldContext: 'span',
|
||||
fieldDataType: 'string',
|
||||
},
|
||||
{
|
||||
key: 'durationNano',
|
||||
dataType: DataTypes.Float64,
|
||||
type: 'tag',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'durationNano--float64--tag--true',
|
||||
isIndexed: false,
|
||||
name: 'duration_nano',
|
||||
signal: 'traces',
|
||||
fieldContext: 'span',
|
||||
fieldDataType: '',
|
||||
},
|
||||
{
|
||||
key: 'httpMethod',
|
||||
dataType: DataTypes.String,
|
||||
type: 'tag',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'httpMethod--string--tag--true',
|
||||
isIndexed: false,
|
||||
name: 'http_method',
|
||||
signal: 'traces',
|
||||
fieldContext: 'span',
|
||||
fieldDataType: '',
|
||||
},
|
||||
{
|
||||
key: 'responseStatusCode',
|
||||
dataType: DataTypes.String,
|
||||
type: 'tag',
|
||||
isColumn: true,
|
||||
isJSON: false,
|
||||
id: 'responseStatusCode--string--tag--true',
|
||||
isIndexed: false,
|
||||
name: 'response_status_code',
|
||||
signal: 'traces',
|
||||
fieldContext: 'span',
|
||||
fieldDataType: '',
|
||||
},
|
||||
];
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { InputNumberProps, RadioProps, SelectProps } from 'antd';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { LogViewMode } from 'container/LogsTable';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
export enum FontSize {
|
||||
SMALL = 'small',
|
||||
@ -13,7 +13,7 @@ interface FontSizeProps {
|
||||
onChange: (val: FontSize) => void;
|
||||
}
|
||||
export interface OptionsQuery {
|
||||
selectColumns: BaseAutocompleteData[];
|
||||
selectColumns: TelemetryFieldKey[];
|
||||
maxLines: number;
|
||||
format: LogViewMode;
|
||||
fontSize: FontSize;
|
||||
@ -36,7 +36,7 @@ export type OptionsMenuConfig = {
|
||||
'options' | 'onSelect' | 'onFocus' | 'onSearch' | 'onBlur'
|
||||
> & {
|
||||
isFetching: boolean;
|
||||
value: BaseAutocompleteData[];
|
||||
value: TelemetryFieldKey[];
|
||||
onRemove: (key: string) => void;
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,21 +1,24 @@
|
||||
import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys';
|
||||
import { getKeySuggestions } from 'api/querySuggestions/getKeySuggestions';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { LogViewMode } from 'container/LogsTable';
|
||||
import { useGetAggregateKeys } from 'hooks/queryBuilder/useGetAggregateKeys';
|
||||
import { useGetQueryKeySuggestions } from 'hooks/querySuggestions/useGetQueryKeySuggestions';
|
||||
import useDebounce from 'hooks/useDebounce';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import useUrlQueryData from 'hooks/useUrlQueryData';
|
||||
import {
|
||||
AllTraceFilterKeys,
|
||||
AllTraceFilterKeyValue,
|
||||
} from 'pages/TracesExplorer/Filter/filterUtils';
|
||||
import { AllTraceFilterKeyValue } from 'pages/TracesExplorer/Filter/filterUtils';
|
||||
import { usePreferenceContext } from 'providers/preferences/context/PreferenceContextProvider';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useQueries } from 'react-query';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
IQueryAutocompleteResponse,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
QueryKeyRequestProps,
|
||||
QueryKeySuggestionsResponseProps,
|
||||
} from 'types/api/querySuggestions/types';
|
||||
import {
|
||||
FieldContext,
|
||||
FieldDataType,
|
||||
SignalType,
|
||||
} from 'types/api/v5/queryRange';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import {
|
||||
@ -47,7 +50,7 @@ interface UseOptionsMenu {
|
||||
|
||||
const useOptionsMenu = ({
|
||||
dataSource,
|
||||
aggregateOperator,
|
||||
// aggregateOperator,
|
||||
initialOptions = {},
|
||||
}: UseOptionsMenuProps): UseOptionsMenu => {
|
||||
const { notifications } = useNotifications();
|
||||
@ -61,15 +64,23 @@ const useOptionsMenu = ({
|
||||
const [isFocused, setIsFocused] = useState<boolean>(false);
|
||||
const debouncedSearchText = useDebounce(searchText, 300);
|
||||
|
||||
const initialQueryParams = useMemo(
|
||||
// const initialQueryParams = useMemo(
|
||||
// () => ({
|
||||
// searchText: '',
|
||||
// aggregateAttribute: '',
|
||||
// tagType: undefined,
|
||||
// dataSource,
|
||||
// aggregateOperator,
|
||||
// }),
|
||||
// [dataSource, aggregateOperator],
|
||||
// );
|
||||
|
||||
const initialQueryParamsV5: QueryKeyRequestProps = useMemo(
|
||||
() => ({
|
||||
signal: dataSource,
|
||||
searchText: '',
|
||||
aggregateAttribute: '',
|
||||
tagType: undefined,
|
||||
dataSource,
|
||||
aggregateOperator,
|
||||
}),
|
||||
[dataSource, aggregateOperator],
|
||||
[dataSource],
|
||||
);
|
||||
|
||||
const {
|
||||
@ -77,23 +88,37 @@ const useOptionsMenu = ({
|
||||
redirectWithQuery: redirectWithOptionsData,
|
||||
} = useUrlQueryData<OptionsQuery>(URL_OPTIONS, defaultOptionsQuery);
|
||||
|
||||
const initialQueries = useMemo(
|
||||
// const initialQueries = useMemo(
|
||||
// () =>
|
||||
// initialOptions?.selectColumns?.map((column) => ({
|
||||
// queryKey: column,
|
||||
// queryFn: (): Promise<
|
||||
// SuccessResponse<IQueryAutocompleteResponse> | ErrorResponse
|
||||
// > =>
|
||||
// getAggregateKeys({
|
||||
// ...initialQueryParams,
|
||||
// searchText: column,
|
||||
// }),
|
||||
// enabled: !!column && !optionsQuery,
|
||||
// })) || [],
|
||||
// [initialOptions?.selectColumns, initialQueryParams, optionsQuery],
|
||||
// );
|
||||
|
||||
const initialQueriesV5 = useMemo(
|
||||
() =>
|
||||
initialOptions?.selectColumns?.map((column) => ({
|
||||
queryKey: column,
|
||||
queryFn: (): Promise<
|
||||
SuccessResponse<IQueryAutocompleteResponse> | ErrorResponse
|
||||
> =>
|
||||
getAggregateKeys({
|
||||
...initialQueryParams,
|
||||
queryFn: (): Promise<AxiosResponse<QueryKeySuggestionsResponseProps>> =>
|
||||
getKeySuggestions({
|
||||
...initialQueryParamsV5,
|
||||
searchText: column,
|
||||
}),
|
||||
enabled: !!column && !optionsQuery,
|
||||
})) || [],
|
||||
[initialOptions?.selectColumns, initialQueryParams, optionsQuery],
|
||||
[initialOptions?.selectColumns, initialQueryParamsV5, optionsQuery],
|
||||
);
|
||||
|
||||
const initialAttributesResult = useQueries(initialQueries);
|
||||
const initialAttributesResult = useQueries(initialQueriesV5);
|
||||
|
||||
const isFetchedInitialAttributes = useMemo(
|
||||
() => initialAttributesResult.every((result) => result.isFetched),
|
||||
@ -106,42 +131,52 @@ const useOptionsMenu = ({
|
||||
}
|
||||
|
||||
const attributesData = initialAttributesResult?.reduce(
|
||||
(acc, attributeResponse) => {
|
||||
const data = attributeResponse?.data?.payload?.attributeKeys || [];
|
||||
(acc: TelemetryFieldKey[], attributeResponse): TelemetryFieldKey[] => {
|
||||
const suggestions =
|
||||
Object.values(attributeResponse?.data?.data?.data?.keys || {}).flat() ||
|
||||
[];
|
||||
|
||||
return [...acc, ...data];
|
||||
const mappedSuggestions: TelemetryFieldKey[] = suggestions.map(
|
||||
(suggestion) => ({
|
||||
name: suggestion.name,
|
||||
signal: suggestion.signal as SignalType,
|
||||
fieldDataType: suggestion.fieldDataType as FieldDataType,
|
||||
fieldContext: suggestion.fieldContext as FieldContext,
|
||||
}),
|
||||
);
|
||||
|
||||
return [...acc, ...mappedSuggestions];
|
||||
},
|
||||
[] as BaseAutocompleteData[],
|
||||
[],
|
||||
);
|
||||
|
||||
let initialSelected = initialOptions.selectColumns
|
||||
?.map((column) => attributesData.find(({ key }) => key === column))
|
||||
.filter(Boolean) as BaseAutocompleteData[];
|
||||
let initialSelected: TelemetryFieldKey[] | undefined =
|
||||
initialOptions.selectColumns
|
||||
?.map((column) => attributesData.find(({ name }) => name === column))
|
||||
.filter((e) => !!e) || [];
|
||||
|
||||
if (dataSource === DataSource.TRACES) {
|
||||
initialSelected = initialSelected
|
||||
?.map((col) => {
|
||||
if (col && Object.keys(AllTraceFilterKeyValue).includes(col?.key)) {
|
||||
if (col && Object.keys(AllTraceFilterKeyValue).includes(col?.name)) {
|
||||
const metaData = defaultTraceSelectedColumns.find(
|
||||
(coln) => coln.key === (col.key as AllTraceFilterKeys),
|
||||
(coln) => coln.name === col.name,
|
||||
);
|
||||
|
||||
return {
|
||||
...metaData,
|
||||
key: metaData?.key,
|
||||
dataType: metaData?.dataType,
|
||||
type: metaData?.type,
|
||||
isColumn: metaData?.isColumn,
|
||||
isJSON: metaData?.isJSON,
|
||||
id: metaData?.id,
|
||||
name: metaData?.name || '',
|
||||
};
|
||||
}
|
||||
return col;
|
||||
})
|
||||
.filter(Boolean) as BaseAutocompleteData[];
|
||||
.filter((e) => !!e);
|
||||
|
||||
if (!initialSelected || !initialSelected?.length) {
|
||||
initialSelected = defaultTraceSelectedColumns;
|
||||
initialSelected = defaultTraceSelectedColumns.map((e) => ({
|
||||
...e,
|
||||
name: e.name,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,41 +189,91 @@ const useOptionsMenu = ({
|
||||
]);
|
||||
|
||||
const {
|
||||
data: searchedAttributesData,
|
||||
isFetching: isSearchedAttributesFetching,
|
||||
} = useGetAggregateKeys(
|
||||
data: searchedAttributesDataV5,
|
||||
isFetching: isSearchedAttributesFetchingV5,
|
||||
} = useGetQueryKeySuggestions(
|
||||
{
|
||||
...initialQueryParams,
|
||||
...initialQueryParamsV5,
|
||||
searchText: debouncedSearchText,
|
||||
},
|
||||
{ queryKey: [debouncedSearchText, isFocused], enabled: isFocused },
|
||||
);
|
||||
|
||||
const searchedAttributeKeys = useMemo(() => {
|
||||
if (searchedAttributesData?.payload?.attributeKeys?.length) {
|
||||
// const {
|
||||
// data: searchedAttributesData,
|
||||
// isFetching: isSearchedAttributesFetching,
|
||||
// } = useGetAggregateKeys(
|
||||
// {
|
||||
// ...initialQueryParams,
|
||||
// searchText: debouncedSearchText,
|
||||
// },
|
||||
// { queryKey: [debouncedSearchText, isFocused], enabled: isFocused },
|
||||
// );
|
||||
|
||||
const searchedAttributeKeys: TelemetryFieldKey[] = useMemo(() => {
|
||||
const searchedAttributesDataList = Object.values(
|
||||
searchedAttributesDataV5?.data.data.keys || {},
|
||||
).flat();
|
||||
if (searchedAttributesDataList.length) {
|
||||
if (dataSource === DataSource.LOGS) {
|
||||
const logsSelectedColumns: TelemetryFieldKey[] = defaultLogsSelectedColumns.map(
|
||||
(e) => ({
|
||||
...e,
|
||||
name: e.name,
|
||||
signal: e.signal as SignalType,
|
||||
fieldContext: e.fieldContext as FieldContext,
|
||||
fieldDataType: e.fieldDataType as FieldDataType,
|
||||
}),
|
||||
);
|
||||
return [
|
||||
...defaultLogsSelectedColumns,
|
||||
...searchedAttributesData.payload.attributeKeys.filter(
|
||||
(attribute) => attribute.key !== 'body',
|
||||
),
|
||||
...logsSelectedColumns,
|
||||
...searchedAttributesDataList
|
||||
.filter((attribute) => attribute.name !== 'body')
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
.map((e) => ({
|
||||
...e,
|
||||
name: e.name,
|
||||
signal: e.signal as SignalType,
|
||||
fieldContext: e.fieldContext as FieldContext,
|
||||
fieldDataType: e.fieldDataType as FieldDataType,
|
||||
})),
|
||||
];
|
||||
}
|
||||
return searchedAttributesData.payload.attributeKeys;
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
return searchedAttributesDataList.map((e) => ({
|
||||
...e,
|
||||
name: e.name,
|
||||
signal: e.signal as SignalType,
|
||||
fieldContext: e.fieldContext as FieldContext,
|
||||
fieldDataType: e.fieldDataType as FieldDataType,
|
||||
}));
|
||||
}
|
||||
if (dataSource === DataSource.TRACES) {
|
||||
return defaultTraceSelectedColumns;
|
||||
return defaultTraceSelectedColumns.map((e) => ({
|
||||
...e,
|
||||
name: e.name,
|
||||
}));
|
||||
}
|
||||
|
||||
return [];
|
||||
}, [dataSource, searchedAttributesData?.payload?.attributeKeys]);
|
||||
}, [dataSource, searchedAttributesDataV5?.data.data.keys]);
|
||||
|
||||
const initialOptionsQuery: OptionsQuery = useMemo(() => {
|
||||
let defaultColumns = defaultOptionsQuery.selectColumns;
|
||||
let defaultColumns: TelemetryFieldKey[] = defaultOptionsQuery.selectColumns;
|
||||
if (dataSource === DataSource.TRACES) {
|
||||
defaultColumns = defaultTraceSelectedColumns;
|
||||
defaultColumns = defaultTraceSelectedColumns.map((e) => ({
|
||||
...e,
|
||||
name: e.name,
|
||||
}));
|
||||
} else if (dataSource === DataSource.LOGS) {
|
||||
defaultColumns = defaultLogsSelectedColumns;
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
defaultColumns = defaultLogsSelectedColumns.map((e) => ({
|
||||
...e,
|
||||
name: e.name,
|
||||
signal: e.signal as SignalType,
|
||||
fieldContext: e.fieldContext as FieldContext,
|
||||
fieldDataType: e.fieldDataType as FieldDataType,
|
||||
}));
|
||||
}
|
||||
|
||||
const finalSelectColumns = initialOptions?.selectColumns
|
||||
@ -203,14 +288,14 @@ const useOptionsMenu = ({
|
||||
}, [dataSource, initialOptions, initialSelectedColumns]);
|
||||
|
||||
const selectedColumnKeys = useMemo(
|
||||
() => preferences?.columns?.map(({ id }) => id) || [],
|
||||
() => preferences?.columns?.map(({ name }) => name) || [],
|
||||
[preferences?.columns],
|
||||
);
|
||||
|
||||
const optionsFromAttributeKeys = useMemo(() => {
|
||||
const filteredAttributeKeys = searchedAttributeKeys.filter((item) => {
|
||||
if (dataSource !== DataSource.LOGS) {
|
||||
return item.key !== 'body';
|
||||
return item.name !== 'body';
|
||||
}
|
||||
return true;
|
||||
});
|
||||
@ -232,11 +317,11 @@ const useOptionsMenu = ({
|
||||
const column = [
|
||||
...searchedAttributeKeys,
|
||||
...(preferences?.columns || []),
|
||||
].find(({ id }) => id === key);
|
||||
].find(({ name }) => name === key);
|
||||
|
||||
if (!column) return acc;
|
||||
return [...acc, column];
|
||||
}, [] as BaseAutocompleteData[]);
|
||||
}, [] as TelemetryFieldKey[]);
|
||||
|
||||
const optionsData: OptionsQuery = {
|
||||
...defaultOptionsQuery,
|
||||
@ -261,7 +346,7 @@ const useOptionsMenu = ({
|
||||
const handleRemoveSelectedColumn = useCallback(
|
||||
(columnKey: string) => {
|
||||
const newSelectedColumns = preferences?.columns?.filter(
|
||||
({ id }) => id !== columnKey,
|
||||
({ name }) => name !== columnKey,
|
||||
);
|
||||
|
||||
if (!newSelectedColumns?.length && dataSource !== DataSource.LOGS) {
|
||||
@ -367,7 +452,7 @@ const useOptionsMenu = ({
|
||||
const optionsMenuConfig: Required<OptionsMenuConfig> = useMemo(
|
||||
() => ({
|
||||
addColumn: {
|
||||
isFetching: isSearchedAttributesFetching,
|
||||
isFetching: isSearchedAttributesFetchingV5,
|
||||
value: preferences?.columns || defaultOptionsQuery.selectColumns,
|
||||
options: optionsFromAttributeKeys || [],
|
||||
onFocus: handleFocus,
|
||||
@ -390,7 +475,7 @@ const useOptionsMenu = ({
|
||||
},
|
||||
}),
|
||||
[
|
||||
isSearchedAttributesFetching,
|
||||
isSearchedAttributesFetchingV5,
|
||||
preferences,
|
||||
optionsFromAttributeKeys,
|
||||
handleSelectColumns,
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { SelectProps } from 'antd';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
|
||||
export const getOptionsFromKeys = (
|
||||
keys: BaseAutocompleteData[],
|
||||
keys: TelemetryFieldKey[],
|
||||
selectedKeys: (string | undefined)[],
|
||||
): SelectProps['options'] => {
|
||||
const options = keys.map(({ id, key }) => ({
|
||||
label: key,
|
||||
value: id,
|
||||
const options = keys.map(({ name }) => ({
|
||||
label: name,
|
||||
value: name,
|
||||
}));
|
||||
|
||||
return options.filter(
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { DEFAULT_PER_PAGE_OPTIONS } from 'hooks/queryPagination';
|
||||
|
||||
export const defaultSelectedColumns: string[] = [
|
||||
'serviceName',
|
||||
'service.name',
|
||||
'name',
|
||||
'durationNano',
|
||||
'httpMethod',
|
||||
'responseStatusCode',
|
||||
'duration_nano',
|
||||
'http_method',
|
||||
'response_status_code',
|
||||
'timestamp',
|
||||
];
|
||||
|
||||
export const PER_PAGE_OPTIONS: number[] = [10, ...DEFAULT_PER_PAGE_OPTIONS];
|
||||
|
||||
@ -65,6 +65,8 @@ function ListView({ isFilterApplied }: ListViewProps): JSX.Element {
|
||||
},
|
||||
});
|
||||
|
||||
console.log('options', options);
|
||||
|
||||
const { draggedColumns, onDragColumns } = useDragColumns<RowData>(
|
||||
LOCALSTORAGE.TRACES_LIST_COLUMNS,
|
||||
);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Tag, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { getMs } from 'container/Trace/Filters/Panel/PanelBody/Duration/util';
|
||||
@ -9,7 +10,6 @@ import { RowData } from 'lib/query/createTableColumnsFromQuery';
|
||||
import LineClampedText from 'periscope/components/LineClampedText/LineClampedText';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ILog } from 'types/api/logs/log';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { QueryDataV3 } from 'types/api/widgets/getQuery';
|
||||
|
||||
export function BlockLink({
|
||||
@ -47,7 +47,7 @@ export const getTraceLink = (record: RowData): string =>
|
||||
})}`;
|
||||
|
||||
export const getListColumns = (
|
||||
selectedColumns: BaseAutocompleteData[],
|
||||
selectedColumns: TelemetryFieldKey[],
|
||||
formatTimezoneAdjustedTimestamp: (
|
||||
input: TimestampInput,
|
||||
format?: string,
|
||||
@ -80,48 +80,58 @@ export const getListColumns = (
|
||||
];
|
||||
|
||||
const columns: ColumnsType<RowData> =
|
||||
selectedColumns.map(({ dataType, key, type }) => ({
|
||||
title: key,
|
||||
dataIndex: key,
|
||||
key: `${key}-${dataType}-${type}`,
|
||||
width: 145,
|
||||
render: (value, item): JSX.Element => {
|
||||
if (value === '') {
|
||||
selectedColumns.map((props) => {
|
||||
const name = props?.name || (props as any)?.key;
|
||||
const fieldDataType = props?.fieldDataType || (props as any)?.dataType;
|
||||
const fieldContext = props?.fieldContext || (props as any)?.type;
|
||||
return {
|
||||
title: name,
|
||||
dataIndex: name,
|
||||
key: `${name}-${fieldDataType}-${fieldContext}`,
|
||||
width: 145,
|
||||
render: (value, item): JSX.Element => {
|
||||
if (value === '') {
|
||||
return (
|
||||
<BlockLink to={getTraceLink(item)} openInNewTab={false}>
|
||||
<Typography data-testid={name}>N/A</Typography>
|
||||
</BlockLink>
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
name === 'httpMethod' ||
|
||||
name === 'responseStatusCode' ||
|
||||
name === 'response_status_code' ||
|
||||
name === 'http_method'
|
||||
) {
|
||||
return (
|
||||
<BlockLink to={getTraceLink(item)} openInNewTab={false}>
|
||||
<Tag data-testid={name} color="magenta">
|
||||
{value}
|
||||
</Tag>
|
||||
</BlockLink>
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'durationNano' || name === 'duration_nano') {
|
||||
return (
|
||||
<BlockLink to={getTraceLink(item)} openInNewTab={false}>
|
||||
<Typography data-testid={name}>{getMs(value)}ms</Typography>
|
||||
</BlockLink>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<BlockLink to={getTraceLink(item)} openInNewTab={false}>
|
||||
<Typography data-testid={key}>N/A</Typography>
|
||||
<Typography data-testid={name}>
|
||||
<LineClampedText text={value} lines={3} />
|
||||
</Typography>
|
||||
</BlockLink>
|
||||
);
|
||||
}
|
||||
|
||||
if (key === 'httpMethod' || key === 'responseStatusCode') {
|
||||
return (
|
||||
<BlockLink to={getTraceLink(item)} openInNewTab={false}>
|
||||
<Tag data-testid={key} color="magenta">
|
||||
{value}
|
||||
</Tag>
|
||||
</BlockLink>
|
||||
);
|
||||
}
|
||||
|
||||
if (key === 'durationNano' || key === 'duration_nano') {
|
||||
return (
|
||||
<BlockLink to={getTraceLink(item)} openInNewTab={false}>
|
||||
<Typography data-testid={key}>{getMs(value)}ms</Typography>
|
||||
</BlockLink>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<BlockLink to={getTraceLink(item)} openInNewTab={false}>
|
||||
<Typography data-testid={key}>
|
||||
<LineClampedText text={value} lines={3} />
|
||||
</Typography>
|
||||
</BlockLink>
|
||||
);
|
||||
},
|
||||
responsive: ['md'],
|
||||
})) || [];
|
||||
},
|
||||
responsive: ['md'],
|
||||
};
|
||||
}) || [];
|
||||
|
||||
return [...initialColumns, ...columns];
|
||||
};
|
||||
|
||||
@ -42,6 +42,8 @@ function TracesTableComponent({
|
||||
});
|
||||
const { safeNavigate } = useSafeNavigate();
|
||||
|
||||
console.log('widget.selectedTracesFields', widget.selectedTracesFields);
|
||||
|
||||
useEffect(() => {
|
||||
setRequestData((prev) => ({
|
||||
...prev,
|
||||
@ -79,6 +81,7 @@ function TracesTableComponent({
|
||||
[queryTableData],
|
||||
);
|
||||
|
||||
console.log('transformedQueryTableData', transformedQueryTableData, columns);
|
||||
const handleRow = useCallback(
|
||||
(record: RowData): HTMLAttributes<RowData> => ({
|
||||
onClick: (event): void => {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { convertKeysToColumnFields } from 'container/LogsExplorerList/utils';
|
||||
import { placeWidgetAtBottom } from 'container/NewWidget/utils';
|
||||
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
|
||||
const baseLogsSelectedColumns = {
|
||||
@ -16,7 +16,7 @@ export const addEmptyWidgetInDashboardJSONWithQuery = (
|
||||
query: Query,
|
||||
widgetId: string,
|
||||
panelType?: PANEL_TYPES,
|
||||
selectedColumns?: BaseAutocompleteData[] | null,
|
||||
selectedColumns?: TelemetryFieldKey[] | null,
|
||||
): Dashboard => {
|
||||
const logsSelectedColumns = [
|
||||
baseLogsSelectedColumns,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ENTITY_VERSION_V5 } from 'constants/app';
|
||||
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
@ -58,7 +59,8 @@ export const useGetExplorerQueryRange = (
|
||||
query: requestData || initialQueriesMap.metrics,
|
||||
params,
|
||||
},
|
||||
version,
|
||||
// version,
|
||||
ENTITY_VERSION_V5,
|
||||
{
|
||||
...options,
|
||||
retry: false,
|
||||
|
||||
@ -1,21 +1,66 @@
|
||||
import { getKeySuggestions } from 'api/querySuggestions/getKeySuggestions';
|
||||
import { AxiosError, AxiosResponse } from 'axios';
|
||||
import { useQuery, UseQueryResult } from 'react-query';
|
||||
import { QueryKeySuggestionsResponseProps } from 'types/api/querySuggestions/types';
|
||||
import { useMemo } from 'react';
|
||||
import { useQuery, UseQueryOptions, UseQueryResult } from 'react-query';
|
||||
import {
|
||||
QueryKeyRequestProps,
|
||||
QueryKeySuggestionsResponseProps,
|
||||
} from 'types/api/querySuggestions/types';
|
||||
|
||||
export const useGetQueryKeySuggestions = ({
|
||||
signal,
|
||||
name,
|
||||
metricName,
|
||||
}: {
|
||||
signal: string;
|
||||
name: string;
|
||||
metricName?: string;
|
||||
}): UseQueryResult<
|
||||
type UseGetQueryKeySuggestions = (
|
||||
requestData: QueryKeyRequestProps,
|
||||
options?: UseQueryOptions<
|
||||
AxiosResponse<QueryKeySuggestionsResponseProps>,
|
||||
AxiosError
|
||||
>,
|
||||
) => UseQueryResult<
|
||||
AxiosResponse<QueryKeySuggestionsResponseProps>,
|
||||
AxiosError
|
||||
> =>
|
||||
useQuery<AxiosResponse<QueryKeySuggestionsResponseProps>, AxiosError>({
|
||||
queryKey: ['queryKeySuggestions', signal, name, metricName],
|
||||
queryFn: () => getKeySuggestions({ signal, name, metricName }),
|
||||
>;
|
||||
|
||||
export const useGetQueryKeySuggestions: UseGetQueryKeySuggestions = (
|
||||
{
|
||||
signal,
|
||||
searchText,
|
||||
fieldContext,
|
||||
fieldDataType,
|
||||
metricName,
|
||||
}: QueryKeyRequestProps,
|
||||
options?: UseQueryOptions<
|
||||
AxiosResponse<QueryKeySuggestionsResponseProps>,
|
||||
AxiosError
|
||||
>,
|
||||
) => {
|
||||
const queryKey = useMemo(() => {
|
||||
if (options?.queryKey && Array.isArray(options.queryKey)) {
|
||||
return ['queryKeySuggestions', ...options.queryKey];
|
||||
}
|
||||
return [
|
||||
'queryKeySuggestions',
|
||||
signal,
|
||||
searchText,
|
||||
metricName,
|
||||
fieldContext,
|
||||
fieldDataType,
|
||||
];
|
||||
}, [
|
||||
options?.queryKey,
|
||||
signal,
|
||||
searchText,
|
||||
metricName,
|
||||
fieldContext,
|
||||
fieldDataType,
|
||||
]);
|
||||
return useQuery<AxiosResponse<QueryKeySuggestionsResponseProps>, AxiosError>({
|
||||
queryKey,
|
||||
queryFn: () =>
|
||||
getKeySuggestions({
|
||||
signal,
|
||||
searchText,
|
||||
metricName,
|
||||
fieldContext,
|
||||
fieldDataType,
|
||||
}),
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
@ -3,6 +3,7 @@ import './LogsExplorer.styles.scss';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
import setLocalStorageApi from 'api/browser/localstorage/set';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import cx from 'classnames';
|
||||
import ExplorerCard from 'components/ExplorerCard/ExplorerCard';
|
||||
import QuickFilters from 'components/QuickFilters/QuickFilters';
|
||||
@ -31,7 +32,6 @@ import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFall
|
||||
import { usePreferenceContext } from 'providers/preferences/context/PreferenceContextProvider';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom-v5-compat';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import {
|
||||
@ -200,11 +200,11 @@ function LogsExplorer(): JSX.Element {
|
||||
|
||||
// Check if the columns have the required columns (timestamp, body)
|
||||
const hasRequiredColumns = useCallback(
|
||||
(columns?: Array<{ key: string }> | null): boolean => {
|
||||
(columns?: TelemetryFieldKey[] | null): boolean => {
|
||||
if (!columns?.length) return false;
|
||||
|
||||
const hasTimestamp = columns.some((col) => col.key === 'timestamp');
|
||||
const hasBody = columns.some((col) => col.key === 'body');
|
||||
const hasTimestamp = columns.some((col) => col.name === 'timestamp');
|
||||
const hasBody = columns.some((col) => col.name === 'body');
|
||||
|
||||
return hasTimestamp && hasBody;
|
||||
},
|
||||
@ -213,7 +213,7 @@ function LogsExplorer(): JSX.Element {
|
||||
|
||||
// Merge the columns with the required columns (timestamp, body) if missing
|
||||
const mergeWithRequiredColumns = useCallback(
|
||||
(columns: BaseAutocompleteData[]): BaseAutocompleteData[] => [
|
||||
(columns: TelemetryFieldKey[]): TelemetryFieldKey[] => [
|
||||
// Add required columns (timestamp, body) if missing
|
||||
...(!hasRequiredColumns(columns) ? defaultLogsSelectedColumns : []),
|
||||
...columns,
|
||||
|
||||
@ -12,18 +12,28 @@ import { DataSource } from 'types/common/queryBuilder';
|
||||
export const AllTraceFilterKeyValue: Record<string, string> = {
|
||||
durationNanoMin: 'Duration',
|
||||
durationNano: 'Duration',
|
||||
duration_nano: 'Duration',
|
||||
durationNanoMax: 'Duration',
|
||||
'deployment.environment': 'Environment',
|
||||
hasError: 'Status',
|
||||
has_error: 'Status',
|
||||
serviceName: 'Service Name',
|
||||
'service.name': 'service.name',
|
||||
name: 'Operation / Name',
|
||||
rpcMethod: 'RPC Method',
|
||||
'rpc.method': 'RPC Method',
|
||||
responseStatusCode: 'Status Code',
|
||||
response_status_code: 'Status Code',
|
||||
httpHost: 'HTTP Host',
|
||||
http_host: 'HTTP Host',
|
||||
httpMethod: 'HTTP Method',
|
||||
http_method: 'HTTP Method',
|
||||
httpRoute: 'HTTP Route',
|
||||
'http.route': 'HTTP Route',
|
||||
httpUrl: 'HTTP URL',
|
||||
'http.url': 'HTTP URL',
|
||||
traceID: 'Trace ID',
|
||||
trace_id: 'Trace ID',
|
||||
} as const;
|
||||
|
||||
export type AllTraceFilterKeys = keyof typeof AllTraceFilterKeyValue;
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
/* eslint-disable sonarjs/no-identical-functions */
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import {
|
||||
FormattingOptions,
|
||||
PreferenceMode,
|
||||
Preferences,
|
||||
} from 'providers/preferences/types';
|
||||
import { MemoryRouter, Route, Switch } from 'react-router-dom';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
import {
|
||||
PreferenceContextProvider,
|
||||
@ -17,7 +17,7 @@ import {
|
||||
jest.mock('../sync/usePreferenceSync', () => ({
|
||||
usePreferenceSync: jest.fn().mockReturnValue({
|
||||
preferences: {
|
||||
columns: [] as BaseAutocompleteData[],
|
||||
columns: [] as TelemetryFieldKey[],
|
||||
formatting: {
|
||||
maxLines: 2,
|
||||
format: 'table',
|
||||
|
||||
@ -150,7 +150,7 @@ describe('logsLoaderConfig', () => {
|
||||
const result = await logsLoaderConfig.default();
|
||||
|
||||
expect(result).toEqual({
|
||||
columns: defaultLogsSelectedColumns as BaseAutocompleteData[],
|
||||
columns: defaultLogsSelectedColumns,
|
||||
formatting: {
|
||||
maxLines: 2,
|
||||
format: 'table' as LogViewMode,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { LogViewMode } from 'container/LogsTable';
|
||||
import { defaultOptionsQuery } from 'container/OptionsMenu/constants';
|
||||
@ -7,10 +8,7 @@ import {
|
||||
PreferenceMode,
|
||||
Preferences,
|
||||
} from 'providers/preferences/types';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
DataTypes,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
import getLogsUpdaterConfig from '../configs/logsUpdaterConfig';
|
||||
|
||||
@ -65,11 +63,11 @@ describe('logsUpdaterConfig', () => {
|
||||
setSavedViewPreferences,
|
||||
);
|
||||
|
||||
const newColumns: BaseAutocompleteData[] = [
|
||||
const newColumns: TelemetryFieldKey[] = [
|
||||
{
|
||||
key: 'new-column',
|
||||
type: 'tag',
|
||||
dataType: DataTypes.String,
|
||||
name: 'new-column',
|
||||
fieldContext: '',
|
||||
fieldDataType: DataTypes.String,
|
||||
isColumn: true,
|
||||
},
|
||||
];
|
||||
@ -114,11 +112,11 @@ describe('logsUpdaterConfig', () => {
|
||||
setSavedViewPreferences,
|
||||
);
|
||||
|
||||
const newColumns: BaseAutocompleteData[] = [
|
||||
const newColumns: TelemetryFieldKey[] = [
|
||||
{
|
||||
key: 'new-column',
|
||||
type: 'tag',
|
||||
dataType: DataTypes.String,
|
||||
name: 'new-column',
|
||||
fieldContext: '',
|
||||
fieldDataType: DataTypes.String,
|
||||
isColumn: true,
|
||||
},
|
||||
];
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
BaseAutocompleteData,
|
||||
DataTypes,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { TelemetryFieldKey } from 'types/api/v5/queryRange';
|
||||
|
||||
import tracesLoaderConfig from '../configs/tracesLoaderConfig';
|
||||
|
||||
@ -125,7 +126,7 @@ describe('tracesLoaderConfig', () => {
|
||||
const result = await tracesLoaderConfig.default();
|
||||
|
||||
expect(result).toEqual({
|
||||
columns: defaultTraceSelectedColumns as BaseAutocompleteData[],
|
||||
columns: defaultTraceSelectedColumns as TelemetryFieldKey[],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { defaultOptionsQuery } from 'container/OptionsMenu/constants';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
DataTypes,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
import getTracesUpdaterConfig from '../configs/tracesUpdaterConfig';
|
||||
import { PreferenceMode } from '../types';
|
||||
@ -34,11 +32,11 @@ describe('tracesUpdaterConfig', () => {
|
||||
const mockSetSavedViewPreferences = jest.fn();
|
||||
|
||||
// Test data
|
||||
const mockColumns: BaseAutocompleteData[] = [
|
||||
const mockColumns: TelemetryFieldKey[] = [
|
||||
{
|
||||
key: 'test-trace-column',
|
||||
type: 'tag',
|
||||
dataType: DataTypes.String,
|
||||
name: 'test-trace-column',
|
||||
fieldContext: '',
|
||||
fieldDataType: DataTypes.String,
|
||||
isColumn: true,
|
||||
},
|
||||
];
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* eslint-disable sonarjs/no-identical-functions */
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { LogViewMode } from 'container/LogsTable';
|
||||
import { FontSize } from 'container/OptionsMenu/types';
|
||||
import {
|
||||
@ -8,10 +9,7 @@ import {
|
||||
Preferences,
|
||||
} from 'providers/preferences/types';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
DataTypes,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import { usePreferenceUpdater } from '../updater/usePreferenceUpdater';
|
||||
@ -81,11 +79,11 @@ describe('usePreferenceUpdater', () => {
|
||||
it('should call the logs updater for updateColumns with logs dataSource', () => {
|
||||
const setReSync = jest.fn();
|
||||
const setSavedViewPreferences = jest.fn();
|
||||
const newColumns: BaseAutocompleteData[] = [
|
||||
const newColumns: TelemetryFieldKey[] = [
|
||||
{
|
||||
key: 'new-column',
|
||||
type: 'tag',
|
||||
dataType: DataTypes.String,
|
||||
name: 'new-column',
|
||||
fieldContext: '',
|
||||
fieldDataType: DataTypes.String,
|
||||
isColumn: true,
|
||||
},
|
||||
];
|
||||
@ -147,11 +145,11 @@ describe('usePreferenceUpdater', () => {
|
||||
it('should call the traces updater for updateColumns with traces dataSource', () => {
|
||||
const setReSync = jest.fn();
|
||||
const setSavedViewPreferences = jest.fn();
|
||||
const newColumns: BaseAutocompleteData[] = [
|
||||
const newColumns: TelemetryFieldKey[] = [
|
||||
{
|
||||
key: 'new-trace-column',
|
||||
type: 'tag',
|
||||
dataType: DataTypes.String,
|
||||
name: 'new-trace-column',
|
||||
fieldContext: '',
|
||||
fieldDataType: DataTypes.String,
|
||||
isColumn: true,
|
||||
},
|
||||
];
|
||||
@ -227,9 +225,9 @@ describe('usePreferenceUpdater', () => {
|
||||
act(() => {
|
||||
result.current.updateColumns([
|
||||
{
|
||||
key: 'column',
|
||||
type: 'tag',
|
||||
dataType: DataTypes.String,
|
||||
name: 'column',
|
||||
fieldContext: '',
|
||||
fieldDataType: DataTypes.String,
|
||||
isColumn: true,
|
||||
},
|
||||
]);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* eslint-disable no-empty */
|
||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { defaultLogsSelectedColumns } from 'container/OptionsMenu/constants';
|
||||
import { FontSize } from 'container/OptionsMenu/types';
|
||||
@ -50,10 +51,10 @@ const logsLoaders = {
|
||||
return { columns: [], formatting: undefined } as any;
|
||||
},
|
||||
default: async (): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
columns: TelemetryFieldKey[];
|
||||
formatting: FormattingOptions;
|
||||
}> => ({
|
||||
columns: defaultLogsSelectedColumns as BaseAutocompleteData[],
|
||||
columns: defaultLogsSelectedColumns,
|
||||
formatting: {
|
||||
maxLines: 2,
|
||||
format: 'table',
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import setLocalStorageKey from 'api/browser/localstorage/set';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { defaultOptionsQuery } from 'container/OptionsMenu/constants';
|
||||
import { FontSize, OptionsQuery } from 'container/OptionsMenu/types';
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
import { FormattingOptions, PreferenceMode, Preferences } from '../types';
|
||||
|
||||
@ -13,10 +13,10 @@ const getLogsUpdaterConfig = (
|
||||
redirectWithOptionsData: (options: OptionsQuery) => void,
|
||||
setSavedViewPreferences: Dispatch<SetStateAction<Preferences | null>>,
|
||||
): {
|
||||
updateColumns: (newColumns: BaseAutocompleteData[], mode: string) => void;
|
||||
updateColumns: (newColumns: TelemetryFieldKey[], mode: string) => void;
|
||||
updateFormatting: (newFormatting: FormattingOptions, mode: string) => void;
|
||||
} => ({
|
||||
updateColumns: (newColumns: BaseAutocompleteData[], mode: string): void => {
|
||||
updateColumns: (newColumns: TelemetryFieldKey[], mode: string): void => {
|
||||
if (mode === PreferenceMode.SAVED_VIEW) {
|
||||
setSavedViewPreferences((prev) => {
|
||||
if (!prev) {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* eslint-disable no-empty */
|
||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { defaultTraceSelectedColumns } from 'container/OptionsMenu/constants';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
@ -33,9 +34,9 @@ const tracesLoaders = {
|
||||
return { columns: [] };
|
||||
},
|
||||
default: async (): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
columns: TelemetryFieldKey[];
|
||||
}> => ({
|
||||
columns: defaultTraceSelectedColumns as BaseAutocompleteData[],
|
||||
columns: defaultTraceSelectedColumns,
|
||||
}),
|
||||
priority: ['local', 'url', 'default'] as const,
|
||||
};
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import setLocalStorageKey from 'api/browser/localstorage/set';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { defaultOptionsQuery } from 'container/OptionsMenu/constants';
|
||||
import { FontSize, OptionsQuery } from 'container/OptionsMenu/types';
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
import { PreferenceMode, Preferences } from '../types';
|
||||
|
||||
@ -12,10 +12,10 @@ const getTracesUpdaterConfig = (
|
||||
redirectWithOptionsData: (options: OptionsQuery) => void,
|
||||
setSavedViewPreferences: Dispatch<SetStateAction<Preferences | null>>,
|
||||
): {
|
||||
updateColumns: (newColumns: BaseAutocompleteData[], mode: string) => void;
|
||||
updateColumns: (newColumns: TelemetryFieldKey[], mode: string) => void;
|
||||
updateFormatting: () => void;
|
||||
} => ({
|
||||
updateColumns: (newColumns: BaseAutocompleteData[], mode: string): void => {
|
||||
updateColumns: (newColumns: TelemetryFieldKey[], mode: string): void => {
|
||||
// remove the formatting props
|
||||
if (mode === PreferenceMode.SAVED_VIEW) {
|
||||
setSavedViewPreferences({
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/* eslint-disable sonarjs/cognitive-complexity */
|
||||
/* eslint-disable no-empty */
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import logsLoaderConfig from '../configs/logsLoaderConfig';
|
||||
@ -43,14 +43,14 @@ async function preferencesLoader<T>(config: {
|
||||
|
||||
// Use the generic loader with specific configs
|
||||
async function logsPreferencesLoader(): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
columns: TelemetryFieldKey[];
|
||||
formatting: FormattingOptions;
|
||||
}> {
|
||||
return preferencesLoader(logsLoaderConfig);
|
||||
}
|
||||
|
||||
async function tracesPreferencesLoader(): Promise<{
|
||||
columns: BaseAutocompleteData[];
|
||||
columns: TelemetryFieldKey[];
|
||||
}> {
|
||||
return preferencesLoader(tracesLoaderConfig);
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { defaultLogsSelectedColumns } from 'container/OptionsMenu/constants';
|
||||
import { defaultSelectedColumns as defaultTracesSelectedColumns } from 'container/TracesExplorer/ListView/configs';
|
||||
import { useGetAllViews } from 'hooks/saveViews/useGetAllViews';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import { usePreferenceLoader } from '../loader/usePreferenceLoader';
|
||||
@ -21,7 +21,7 @@ export function usePreferenceSync({
|
||||
preferences: Preferences | null;
|
||||
loading: boolean;
|
||||
error: Error | null;
|
||||
updateColumns: (newColumns: BaseAutocompleteData[]) => void;
|
||||
updateColumns: (newColumns: TelemetryFieldKey[]) => void;
|
||||
updateFormatting: (newFormatting: FormattingOptions) => void;
|
||||
} {
|
||||
const { data: viewsData } = useGetAllViews(dataSource);
|
||||
@ -37,7 +37,7 @@ export function usePreferenceSync({
|
||||
)?.extraData;
|
||||
|
||||
const parsedExtraData = JSON.parse(extraData || '{}');
|
||||
let columns: BaseAutocompleteData[] = [];
|
||||
let columns: TelemetryFieldKey[] = [];
|
||||
let formatting: FormattingOptions | undefined;
|
||||
if (dataSource === DataSource.LOGS) {
|
||||
columns = parsedExtraData?.selectColumns || defaultLogsSelectedColumns;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { LogViewMode } from 'container/LogsTable';
|
||||
import { FontSize } from 'container/OptionsMenu/types';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
export enum PreferenceMode {
|
||||
@ -15,7 +15,7 @@ export interface PreferenceContextValue {
|
||||
mode: PreferenceMode;
|
||||
savedViewId?: string;
|
||||
dataSource: DataSource;
|
||||
updateColumns: (newColumns: BaseAutocompleteData[]) => void;
|
||||
updateColumns: (newColumns: TelemetryFieldKey[]) => void;
|
||||
updateFormatting: (newFormatting: FormattingOptions) => void;
|
||||
}
|
||||
|
||||
@ -27,6 +27,6 @@ export interface FormattingOptions {
|
||||
}
|
||||
|
||||
export interface Preferences {
|
||||
columns: BaseAutocompleteData[];
|
||||
columns: TelemetryFieldKey[];
|
||||
formatting?: FormattingOptions;
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import {
|
||||
defaultOptionsQuery,
|
||||
URL_OPTIONS,
|
||||
@ -5,7 +6,6 @@ import {
|
||||
import { OptionsQuery } from 'container/OptionsMenu/types';
|
||||
import useUrlQueryData from 'hooks/useUrlQueryData';
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import getLogsUpdaterConfig from '../configs/logsUpdaterConfig';
|
||||
@ -24,7 +24,7 @@ const getUpdaterConfig = (
|
||||
): Record<
|
||||
DataSource,
|
||||
{
|
||||
updateColumns: (newColumns: BaseAutocompleteData[], mode: string) => void;
|
||||
updateColumns: (newColumns: TelemetryFieldKey[], mode: string) => void;
|
||||
updateFormatting: (newFormatting: FormattingOptions, mode: string) => void;
|
||||
}
|
||||
> => ({
|
||||
@ -53,7 +53,7 @@ export function usePreferenceUpdater({
|
||||
setReSync: Dispatch<SetStateAction<boolean>>;
|
||||
setSavedViewPreferences: Dispatch<SetStateAction<Preferences | null>>;
|
||||
}): {
|
||||
updateColumns: (newColumns: BaseAutocompleteData[]) => void;
|
||||
updateColumns: (newColumns: TelemetryFieldKey[]) => void;
|
||||
updateFormatting: (newFormatting: FormattingOptions) => void;
|
||||
} {
|
||||
const {
|
||||
@ -66,7 +66,7 @@ export function usePreferenceUpdater({
|
||||
)[dataSource];
|
||||
|
||||
return {
|
||||
updateColumns: (newColumns: BaseAutocompleteData[]): void => {
|
||||
updateColumns: (newColumns: TelemetryFieldKey[]): void => {
|
||||
updater.updateColumns(newColumns, mode);
|
||||
setReSync(true);
|
||||
},
|
||||
|
||||
@ -7,7 +7,7 @@ import { Layout } from 'react-grid-layout';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
|
||||
import { IField } from '../logs/fields';
|
||||
import { BaseAutocompleteData } from '../queryBuilder/queryAutocompleteResponse';
|
||||
import { TelemetryFieldKey } from '../v5/queryRange';
|
||||
|
||||
export const VariableQueryTypeArr = ['QUERY', 'TEXTBOX', 'CUSTOM'] as const;
|
||||
export type TVariableQueryType = typeof VariableQueryTypeArr[number];
|
||||
@ -115,7 +115,7 @@ export interface IBaseWidget {
|
||||
fillSpans?: boolean;
|
||||
columnUnits?: ColumnUnit;
|
||||
selectedLogFields: IField[] | null;
|
||||
selectedTracesFields: BaseAutocompleteData[] | null;
|
||||
selectedTracesFields: TelemetryFieldKey[] | null;
|
||||
isLogScale?: boolean;
|
||||
columnWidths?: Record<string, number>;
|
||||
legendPosition?: LegendPosition;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { Format } from 'container/NewWidget/RightContainer/types';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import {
|
||||
@ -85,7 +86,7 @@ export type IBuilderQuery = {
|
||||
legend: string;
|
||||
pageSize?: number;
|
||||
offset?: number;
|
||||
selectColumns?: BaseAutocompleteData[];
|
||||
selectColumns?: BaseAutocompleteData[] | TelemetryFieldKey[];
|
||||
};
|
||||
|
||||
export interface IClickHouseQuery {
|
||||
|
||||
@ -4,10 +4,10 @@ export interface QueryKeyDataSuggestionsProps {
|
||||
info?: string;
|
||||
apply?: string;
|
||||
detail?: string;
|
||||
fieldContext: string;
|
||||
fieldDataType: string;
|
||||
fieldContext?: 'resource' | 'scope' | 'attribute' | 'span';
|
||||
fieldDataType?: 'string' | 'number' | 'boolean';
|
||||
name: string;
|
||||
signal: string;
|
||||
signal: 'traces' | 'logs' | 'metrics';
|
||||
}
|
||||
|
||||
export interface QueryKeySuggestionsResponseProps {
|
||||
@ -21,8 +21,10 @@ export interface QueryKeySuggestionsResponseProps {
|
||||
}
|
||||
|
||||
export interface QueryKeyRequestProps {
|
||||
signal: string;
|
||||
name: string;
|
||||
signal: 'traces' | 'logs' | 'metrics';
|
||||
searchText: string;
|
||||
fieldContext?: 'resource' | 'scope' | 'attribute' | 'span';
|
||||
fieldDataType?: 'string' | 'number' | 'boolean';
|
||||
metricName?: string;
|
||||
}
|
||||
|
||||
|
||||
@ -130,6 +130,9 @@ export interface TelemetryFieldKey {
|
||||
fieldContext?: FieldContext;
|
||||
fieldDataType?: FieldDataType;
|
||||
materialized?: boolean;
|
||||
isColumn?: boolean;
|
||||
isJSON?: boolean;
|
||||
isIndexed?: boolean;
|
||||
}
|
||||
|
||||
export interface Filter {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user