mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 02:09:04 +08:00
feat: table view is updated for body field (#2465)
This commit is contained in:
parent
91c3abae37
commit
1ddda19c8e
@ -1,14 +1,18 @@
|
||||
import { blue, orange } from '@ant-design/colors';
|
||||
import { Input } from 'antd';
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
import Editor from 'components/Editor';
|
||||
import AddToQueryHOC from 'components/Logs/AddToQueryHOC';
|
||||
import CopyClipboardHOC from 'components/Logs/CopyClipboardHOC';
|
||||
import { ResizeTable } from 'components/ResizeTable';
|
||||
import flatten from 'flat';
|
||||
import { fieldSearchFilter } from 'lib/logs/fieldSearch';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { ILog } from 'types/api/logs/log';
|
||||
|
||||
import ActionItem from './ActionItem';
|
||||
import { recursiveParseJSON } from './utils';
|
||||
|
||||
// Fields which should be restricted from adding it to query
|
||||
const RESTRICTED_FIELDS = ['timestamp'];
|
||||
@ -41,10 +45,10 @@ function TableView({ logData }: TableViewProps): JSX.Element | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
const columns = [
|
||||
const columns: ColumnsType<DataType> = [
|
||||
{
|
||||
title: 'Action',
|
||||
width: 100,
|
||||
width: 15,
|
||||
render: (fieldData: Record<string, string>): JSX.Element | null => {
|
||||
const fieldKey = fieldData.field.split('.').slice(-1);
|
||||
if (!RESTRICTED_FIELDS.includes(fieldKey[0])) {
|
||||
@ -57,7 +61,8 @@ function TableView({ logData }: TableViewProps): JSX.Element | null {
|
||||
title: 'Field',
|
||||
dataIndex: 'field',
|
||||
key: 'field',
|
||||
width: 100,
|
||||
width: 30,
|
||||
ellipsis: true,
|
||||
render: (field: string): JSX.Element => {
|
||||
const fieldKey = field.split('.').slice(-1);
|
||||
const renderedField = <span style={{ color: blue[4] }}>{field}</span>;
|
||||
@ -78,16 +83,36 @@ function TableView({ logData }: TableViewProps): JSX.Element | null {
|
||||
key: 'value',
|
||||
width: 80,
|
||||
ellipsis: false,
|
||||
render: (field: never): JSX.Element => (
|
||||
<CopyClipboardHOC textToCopy={field}>
|
||||
<span style={{ color: orange[6] }}>{field}</span>
|
||||
</CopyClipboardHOC>
|
||||
),
|
||||
render: (field, record): JSX.Element => {
|
||||
if (record.field === 'body') {
|
||||
const parsedBody = recursiveParseJSON(field);
|
||||
if (!isEmpty(parsedBody)) {
|
||||
return (
|
||||
<Editor
|
||||
value={JSON.stringify(parsedBody, null, 2)}
|
||||
readOnly
|
||||
height="70vh"
|
||||
options={{
|
||||
minimap: {
|
||||
enabled: false,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<CopyClipboardHOC textToCopy={field}>
|
||||
<span style={{ color: orange[6] }}>{field}</span>
|
||||
</CopyClipboardHOC>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{ position: 'relative' }}>
|
||||
<>
|
||||
<Input
|
||||
placeholder="Search field names"
|
||||
size="large"
|
||||
@ -95,13 +120,19 @@ function TableView({ logData }: TableViewProps): JSX.Element | null {
|
||||
onChange={(e): void => setFieldSearchInput(e.target.value)}
|
||||
/>
|
||||
<ResizeTable
|
||||
columns={columns as never}
|
||||
columns={columns}
|
||||
tableLayout="fixed"
|
||||
dataSource={dataSource}
|
||||
pagination={false}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface DataType {
|
||||
key: string;
|
||||
field: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export default TableView;
|
||||
|
47
frontend/src/container/LogDetailedView/util.test.ts
Normal file
47
frontend/src/container/LogDetailedView/util.test.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { recursiveParseJSON } from './utils';
|
||||
|
||||
describe('recursiveParseJSON', () => {
|
||||
it('should return an empty object if the input is not valid JSON', () => {
|
||||
const result = recursiveParseJSON('not valid JSON');
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
it('should return the parsed JSON object for valid JSON input', () => {
|
||||
const jsonString = '{"name": "John", "age": 30}';
|
||||
const result = recursiveParseJSON(jsonString);
|
||||
expect(result).toEqual({ name: 'John', age: 30 });
|
||||
});
|
||||
|
||||
it('should recursively parse nested JSON objects', () => {
|
||||
const jsonString =
|
||||
'{"name": "John", "age": 30, "address": {"street": "123 Main St", "city": "Anytown", "state": "CA"}}';
|
||||
const result = recursiveParseJSON(jsonString);
|
||||
expect(result).toEqual({
|
||||
name: 'John',
|
||||
age: 30,
|
||||
address: {
|
||||
street: '123 Main St',
|
||||
city: 'Anytown',
|
||||
state: 'CA',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should recursively parse nested JSON arrays', () => {
|
||||
const jsonString = '[1, 2, [3, 4], {"foo": "bar"}]';
|
||||
const result = recursiveParseJSON(jsonString);
|
||||
expect(result).toEqual([1, 2, [3, 4], { foo: 'bar' }]);
|
||||
});
|
||||
|
||||
it('should recursively parse deeply nested JSON objects', () => {
|
||||
const jsonString = '{"foo": {"bar": {"baz": {"qux": {"value": 42}}}}}';
|
||||
const result = recursiveParseJSON(jsonString);
|
||||
expect(result).toEqual({ foo: { bar: { baz: { qux: { value: 42 } } } } });
|
||||
});
|
||||
|
||||
it('should handle JSON input that contains escaped characters', () => {
|
||||
const jsonString = '{"name": "John\\", \\"Doe", "age": 30}';
|
||||
const result = recursiveParseJSON(jsonString);
|
||||
expect(result).toEqual({ name: 'John", "Doe', age: 30 });
|
||||
});
|
||||
});
|
11
frontend/src/container/LogDetailedView/utils.ts
Normal file
11
frontend/src/container/LogDetailedView/utils.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export const recursiveParseJSON = (obj: string): Record<string, unknown> => {
|
||||
try {
|
||||
const value = JSON.parse(obj);
|
||||
if (typeof value === 'string') {
|
||||
return recursiveParseJSON(value);
|
||||
}
|
||||
return value;
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user