217 lines
5.0 KiB
TypeScript
Raw Normal View History

import { orange } from '@ant-design/colors';
import { LinkOutlined } from '@ant-design/icons';
feat: tree is updated to show different node values instead of editor (#2696) * feat: tree is updated to show different node values instead of editor * chore: table view is updated * [Refactoring]: Seperate title and menu to another component (#3531) * refactor: separated the title renderer * refactor: separated styles * refactor: seperate types * refactor: instead of key showing value if array (#3532) * refactor: instead of key showing value if array * feat: added filter for array and also nodekey * refactor: made common check for value is array * refactor: changed the key to value for arrays * chore: getData types is updated * chore: getDataTypes function types is updated * refactor: connection to querybuilder (#3535) Co-authored-by: Palash Gupta <palashgdev@gmail.com> * chore: operator is updated * fix: build is fixed * fix: build is fixed * chore: operator is updated * chore: operator is updated * chore: parsing is updated * chore: key is updated * Refactor: Log parsing updates (#3542) * refactor: updated nodekey * refactor: removed pasred data * refactor: parentIsArray check * chore: added the support for the bool * [Refactor]: handle nested object case (#3545) * refactor: updated nodekey * refactor: removed pasred data * refactor: parentIsArray check * refactor: handled nested array inside object case * fix: float issue parsing * chore: operator is updated * chore: title is updated * chore: title is updated * fix: update tagRegexp * fix: maintain single source of DataTypes * chore: operator is updated * fix: fixed due to merge conflicts --------- Co-authored-by: Rajat Dabade <rajat@signoz.io> Co-authored-by: Yunus A M <myounis.ar@live.com>
2023-09-15 10:21:42 +05:30
import { Input, Space, Tooltip, Tree } from 'antd';
import { ColumnsType } from 'antd/es/table';
import AddToQueryHOC, {
AddToQueryHOCProps,
} from 'components/Logs/AddToQueryHOC';
import CopyClipboardHOC from 'components/Logs/CopyClipboardHOC';
import { ResizeTable } from 'components/ResizeTable';
import ROUTES from 'constants/routes';
import history from 'lib/history';
import { fieldSearchFilter } from 'lib/logs/fieldSearch';
import { isEmpty } from 'lodash-es';
import { useMemo, useState } from 'react';
import { useDispatch } from 'react-redux';
import { generatePath } from 'react-router-dom';
import { Dispatch } from 'redux';
import AppActions from 'types/actions';
import { SET_DETAILED_LOG_DATA } from 'types/actions/logs';
import { ILog } from 'types/api/logs/log';
import ActionItem, { ActionItemProps } from './ActionItem';
import FieldRenderer from './FieldRenderer';
import {
flattenObject,
jsonToDataNodes,
recursiveParseJSON,
removeEscapeCharacters,
} from './utils';
// Fields which should be restricted from adding it to query
const RESTRICTED_FIELDS = ['timestamp'];
interface TableViewProps {
logData: ILog;
}
type Props = TableViewProps &
Pick<AddToQueryHOCProps, 'onAddToQuery'> &
Pick<ActionItemProps, 'onClickActionItem'>;
function TableView({
logData,
onAddToQuery,
onClickActionItem,
}: Props): JSX.Element | null {
const [fieldSearchInput, setFieldSearchInput] = useState<string>('');
const dispatch = useDispatch<Dispatch<AppActions>>();
const flattenLogData: Record<string, string> | null = useMemo(
() => (logData ? flattenObject(logData) : null),
[logData],
);
if (logData === null) {
return null;
}
const dataSource =
flattenLogData !== null &&
Object.keys(flattenLogData)
.filter((field) => fieldSearchFilter(field, fieldSearchInput))
.map((key) => ({
key,
field: key,
2023-10-13 11:35:50 +05:30
value: JSON.stringify(flattenLogData[key]),
}));
const onTraceHandler = (record: DataType) => (): void => {
if (flattenLogData === null) return;
const traceId = flattenLogData[record.field];
const spanId = flattenLogData?.span_id;
if (traceId) {
dispatch({
type: SET_DETAILED_LOG_DATA,
payload: null,
});
const basePath = generatePath(ROUTES.TRACE_DETAIL, {
id: traceId,
});
const route = spanId ? `${basePath}?spanId=${spanId}` : basePath;
history.push(route);
}
};
if (!dataSource) {
return null;
}
const columns: ColumnsType<DataType> = [
{
title: 'Action',
width: 11,
render: (fieldData: Record<string, string>): JSX.Element | null => {
const fieldKey = fieldData.field.split('.').slice(-1);
if (!RESTRICTED_FIELDS.includes(fieldKey[0])) {
return (
<ActionItem
fieldKey={fieldKey[0]}
fieldValue={fieldData.value}
onClickActionItem={onClickActionItem}
/>
);
}
return null;
},
},
{
title: 'Field',
dataIndex: 'field',
key: 'field',
width: 50,
align: 'left',
ellipsis: true,
render: (field: string, record): JSX.Element => {
const fieldKey = field.split('.').slice(-1);
const renderedField = <FieldRenderer field={field} />;
if (record.field === 'trace_id') {
const traceId = flattenLogData[record.field];
return (
<Space size="middle">
{renderedField}
{traceId && (
<Tooltip title="Inspect in Trace">
<div
style={{ cursor: 'pointer' }}
role="presentation"
onClick={onTraceHandler(record)}
>
<LinkOutlined
style={{
width: '15px',
}}
/>
</div>
</Tooltip>
)}
</Space>
);
}
if (!RESTRICTED_FIELDS.includes(fieldKey[0])) {
return (
<AddToQueryHOC
fieldKey={fieldKey[0]}
fieldValue={flattenLogData[field]}
onAddToQuery={onAddToQuery}
>
{renderedField}
</AddToQueryHOC>
);
}
return renderedField;
},
},
{
title: 'Value',
dataIndex: 'value',
key: 'value',
width: 70,
ellipsis: false,
render: (field, record): JSX.Element => {
const textToCopy = field.slice(1, -1);
if (record.field === 'body') {
const parsedBody = recursiveParseJSON(field);
if (!isEmpty(parsedBody)) {
return (
<Tree defaultExpandAll showLine treeData={jsonToDataNodes(parsedBody)} />
);
}
}
return (
<CopyClipboardHOC textToCopy={textToCopy}>
2023-10-13 11:35:50 +05:30
<span style={{ color: orange[6] }}>{removeEscapeCharacters(field)}</span>
</CopyClipboardHOC>
);
},
},
];
return (
<>
<Input
placeholder="Search field names"
size="large"
value={fieldSearchInput}
onChange={(e): void => setFieldSearchInput(e.target.value)}
/>
<ResizeTable
columns={columns}
tableLayout="fixed"
dataSource={dataSource}
pagination={false}
/>
</>
);
}
interface DataType {
key: string;
field: string;
value: string;
}
export default TableView;