Skip to content

Commit

Permalink
Add fuzzy search for log fields
Browse files Browse the repository at this point in the history
  • Loading branch information
karniv00l committed Sep 11, 2023
1 parent c79f8d0 commit 6268325
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 6 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@sentry/react": "^7.68.0",
"@sentry/tracing": "^7.68.0",
"antd": "^4.24.13",
"fuse.js": "^6.6.2",
"kbar": "^0.1.0-beta.43",
"lodash.debounce": "^4.0.8",
"mlg-converter": "^0.9.0",
Expand Down
67 changes: 61 additions & 6 deletions src/pages/Logs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import {
Badge,
Typography,
Grid,
Input,
} from 'antd';
import { FileTextOutlined, EditOutlined, GlobalOutlined } from '@ant-design/icons';
import { CheckboxValueType } from 'antd/es/checkbox/Group';
import { connect } from 'react-redux';
import { Result as ParserResult } from 'mlg-converter/dist/types';
import PerfectScrollbar from 'react-perfect-scrollbar';
import { OutputChannel, Logs as LogsType, DatalogEntry } from '@hyper-tuner/types';

import LogParserWorker from '../workers/logParserWorker?worker';
import LogCanvas, { SelectedField } from '../components/Logs/LogCanvas';
import store from '../store';
Expand All @@ -35,11 +35,29 @@ import { removeFilenameSuffix } from '../pocketbase';
import { isAbortedRequest } from '../utils/error';
import { WorkerOutput } from '../workers/logParserWorker';
import { collapsedSidebarWidth, sidebarWidth } from '../components/Tune/SideBar';
import Fuse from 'fuse.js';
import debounce from 'lodash.debounce';

const { Content } = Layout;
const edgeUnknown = 'Unknown';
const minCanvasHeightInner = 500;
const badgeStyle = { backgroundColor: Colors.TEXT };
const fieldsSectionStyle = { height: 'calc(50vh - 175px)' };
const searchInputStyle = {
width: 'auto',
position: 'sticky' as const,
top: 0,
marginBottom: 10,
};
const fuseOptions = {
shouldSort: true,
includeMatches: false,
includeScore: false,
ignoreLocation: false,
findAllMatches: false,
threshold: 0.4,
keys: ['label'], // TODO: handle expression
};

const mapStateToProps = (state: AppState) => ({
ui: state.ui,
Expand Down Expand Up @@ -153,6 +171,18 @@ const Logs = ({
},
[config?.datalog, findOutputChannel, isConfigReady],
);
const [foundFields1, setFoundFields1] = useState<DatalogEntry[]>([]);
const [foundFields2, setFoundFields2] = useState<DatalogEntry[]>([]);
const fuse = new Fuse<DatalogEntry>(fields, fuseOptions);

const debounceSearch1 = debounce(async (searchText: string) => {
const result = fuse.search(searchText);
setFoundFields1(result.length > 0 ? result.map((item) => item.item) : fields);
}, 300);
const debounceSearch2 = debounce(async (searchText: string) => {
const result = fuse.search(searchText);
setFoundFields2(result.length > 0 ? result.map((item) => item.item) : fields);
}, 300);

useEffect(() => {
const worker = new LogParserWorker();
Expand Down Expand Up @@ -263,7 +293,10 @@ const Logs = ({
}

if (config?.outputChannels) {
setFields(Object.values(config.datalog));
const fields = Object.values(config.datalog);
setFields(fields);
setFoundFields1(fields);
setFoundFields2(fields);
}

calculateCanvasSize();
Expand Down Expand Up @@ -302,11 +335,24 @@ const Logs = ({
key: 'fields',
children: (
<>
<div style={showSingleGraph ? {} : { height: '45%' }}>
<Input
onChange={({ target }) => debounceSearch1(target.value)}
style={searchInputStyle}
placeholder='Search fields...'
allowClear
/>
<div
style={
showSingleGraph ? { height: 'calc(100vh - 250px)' } : fieldsSectionStyle
}
>
<PerfectScrollbar options={{ suppressScrollX: true }}>
<Checkbox.Group onChange={setSelectedFields1} value={selectedFields1}>
{fields.map((field) => (
<Row key={field.name}>
<Row
key={field.name}
hidden={!foundFields1.find((f) => f.name === field.name)}
>
<Checkbox key={field.name} value={field.name}>
{isExpression(field.label)
? stripExpression(field.label)
Expand All @@ -320,11 +366,20 @@ const Logs = ({
{!showSingleGraph && (
<>
<Divider />
<div style={{ height: '45%' }}>
<Input
onChange={({ target }) => debounceSearch2(target.value)}
style={searchInputStyle}
placeholder='Search fields...'
allowClear
/>
<div style={fieldsSectionStyle}>
<PerfectScrollbar options={{ suppressScrollX: true }}>
<Checkbox.Group onChange={setSelectedFields2} value={selectedFields2}>
{fields.map((field) => (
<Row key={field.name}>
<Row
key={field.name}
hidden={!foundFields2.find((f) => f.name === field.name)}
>
<Checkbox key={field.name} value={field.name}>
{isExpression(field.label)
? stripExpression(field.label)
Expand Down

0 comments on commit 6268325

Please sign in to comment.