Load user logs (#809)
This commit is contained in:
parent
f195ad6d3a
commit
a77d1e790b
|
@ -148,6 +148,7 @@ const App = ({ ui, navigation, tuneData }: { ui: UIState, navigation: Navigation
|
|||
<Route path={Routes.TUNE_ROOT} element={<ContentFor element={<Info />} />} />
|
||||
<Route path={`${Routes.TUNE_TUNE}/*`} element={<ContentFor marginLeft={margin} element={<Tune />} />} />
|
||||
<Route path={Routes.TUNE_LOGS} element={<ContentFor marginLeft={margin} element={<Logs />} />} />
|
||||
<Route path={Routes.TUNE_LOGS_FILE} element={<ContentFor marginLeft={margin} element={<Logs />} />} />
|
||||
<Route path={Routes.TUNE_DIAGNOSE} element={<ContentFor marginLeft={margin} element={<Diagnose />} />} />
|
||||
<Route path={`${Routes.UPLOAD}/*`} element={<ContentFor element={<Upload />} />} />
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
|
|||
const hubPathMatch = useMatch(Routes.HUB);
|
||||
const tuneRootMatch = useMatch(`${Routes.TUNE_ROOT}/*`);
|
||||
const tuneTuneMatch = useMatch(`${Routes.TUNE_TUNE}/*`);
|
||||
const tuneLogMatch = useMatch(`${Routes.TUNE_LOGS}/*`);
|
||||
const tabMatch = useMatch(`${Routes.TUNE_TAB}/*`);
|
||||
const uploadMatch = useMatch(Routes.UPLOAD);
|
||||
const hubMatch = useMatch(Routes.HUB);
|
||||
|
@ -95,7 +96,7 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
|
|||
<Col span={16} md={16} sm={16}>
|
||||
<Radio.Group
|
||||
key={pathname}
|
||||
defaultValue={tuneTuneMatch?.pathnameBase || tabMatch?.pathname || tuneRootMatch?.pathname || hubPathMatch?.pathname}
|
||||
defaultValue={tuneLogMatch?.pathnameBase || tuneTuneMatch?.pathnameBase || tabMatch?.pathname || tuneRootMatch?.pathname || hubPathMatch?.pathname}
|
||||
optionType="button"
|
||||
buttonStyle="solid"
|
||||
onChange={(e) => navigate(e.target.value)}
|
||||
|
@ -132,7 +133,7 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
|
|||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Col>
|
||||
), [buildTuneUrl, lg, navigate, pathname, hubPathMatch?.pathname, tabMatch?.pathname, tuneRootMatch?.pathname, tuneTuneMatch?.pathnameBase]);
|
||||
), [pathname, tuneTuneMatch?.pathnameBase, tabMatch?.pathname, tuneRootMatch?.pathname, hubPathMatch?.pathname, tuneLogMatch?.pathnameBase, buildTuneUrl, lg, navigate]);
|
||||
|
||||
const rightMenuColProps = tuneId ? {
|
||||
span: 8,
|
||||
|
|
|
@ -23,12 +23,10 @@ import * as Sentry from '@sentry/browser';
|
|||
import useBreakpoint from 'antd/lib/grid/hooks/useBreakpoint';
|
||||
import { connect } from 'react-redux';
|
||||
import PerfectScrollbar from 'react-perfect-scrollbar';
|
||||
import {
|
||||
Config,
|
||||
Logs,
|
||||
} from '@hyper-tuner/types';
|
||||
import {
|
||||
AppState,
|
||||
ConfigState,
|
||||
LogsState,
|
||||
UIState,
|
||||
} from '../types/state';
|
||||
import {
|
||||
|
@ -64,7 +62,7 @@ const margin = 30;
|
|||
const sidebarWidth = 250;
|
||||
const minCanvasHeightInner = 600;
|
||||
|
||||
const Diagnose = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loadedLogs: Logs }) => {
|
||||
const Diagnose = ({ ui, config, loadedLogs }: { ui: UIState, config: ConfigState, loadedLogs: LogsState }) => {
|
||||
const { lg } = useBreakpoint();
|
||||
const { Sider } = Layout;
|
||||
const [progress, setProgress] = useState(0);
|
||||
|
@ -147,7 +145,7 @@ const Diagnose = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loa
|
|||
return (
|
||||
<>
|
||||
<Sider {...(siderProps as any)} className="app-sidebar">
|
||||
{!logs && !loadedLogs.length ?
|
||||
{!logs && !(loadedLogs.logs || []).length ?
|
||||
<Loader />
|
||||
:
|
||||
!ui.sidebarCollapsed &&
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
import {
|
||||
Link,
|
||||
generatePath,
|
||||
useMatch,
|
||||
useNavigate,
|
||||
} from 'react-router-dom';
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
|
@ -27,7 +33,6 @@ import { connect } from 'react-redux';
|
|||
import { Result as ParserResult } from 'mlg-converter/dist/types';
|
||||
import PerfectScrollbar from 'react-perfect-scrollbar';
|
||||
import {
|
||||
Config,
|
||||
OutputChannel,
|
||||
Logs as LogsType,
|
||||
DatalogEntry,
|
||||
|
@ -47,12 +52,15 @@ import {
|
|||
} from '../utils/tune/expression';
|
||||
import {
|
||||
AppState,
|
||||
ConfigState,
|
||||
LogsState,
|
||||
TuneDataState,
|
||||
UIState,
|
||||
} from '../types/state';
|
||||
import Loader from '../components/Loader';
|
||||
import { Colors } from '../utils/colors';
|
||||
import { TunesRecordFull } from '../types/dbData';
|
||||
import useServerStorage from '../hooks/useServerStorage';
|
||||
import { Routes } from '../routes';
|
||||
|
||||
const { Content } = Layout;
|
||||
const { Step } = Steps;
|
||||
|
@ -77,9 +85,9 @@ const Logs = ({
|
|||
tuneData,
|
||||
}: {
|
||||
ui: UIState,
|
||||
config: Config,
|
||||
loadedLogs: LogsType,
|
||||
tuneData: TunesRecordFull,
|
||||
config: ConfigState,
|
||||
loadedLogs: LogsState,
|
||||
tuneData: TuneDataState,
|
||||
}) => {
|
||||
const { lg } = useBreakpoint();
|
||||
const { Sider } = Layout;
|
||||
|
@ -95,6 +103,9 @@ const Logs = ({
|
|||
const [canvasWidth, setCanvasWidth] = useState(0);
|
||||
const [canvasHeight, setCanvasHeight] = useState(0);
|
||||
const { fetchLogFileWithProgress } = useServerStorage();
|
||||
const routeMatch = useMatch(Routes.TUNE_LOGS_FILE);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const calculateCanvasSize = useCallback(() => {
|
||||
setCanvasWidth((contentRef.current?.clientWidth || 0) - margin);
|
||||
|
||||
|
@ -157,15 +168,12 @@ const Logs = ({
|
|||
const worker = new MlgParserWorker();
|
||||
const controller = new AbortController();
|
||||
const { signal } = controller;
|
||||
const loadData = async () => {
|
||||
const firstLogFile = (tuneData.logFiles || [])[0];
|
||||
|
||||
if (!firstLogFile) {
|
||||
return;
|
||||
}
|
||||
const loadData = async () => {
|
||||
const logFileName = routeMatch?.params.fileName!;
|
||||
|
||||
try {
|
||||
const raw = await fetchLogFileWithProgress(tuneData.id, firstLogFile, (percent, total, edge) => {
|
||||
const raw = await fetchLogFileWithProgress(tuneData.id, logFileName, (percent, total, edge) => {
|
||||
setProgress(percent);
|
||||
setFileSize(formatBytes(total));
|
||||
setEdgeLocation(edge || edgeUnknown);
|
||||
|
@ -185,7 +193,12 @@ const Logs = ({
|
|||
break;
|
||||
case 'result':
|
||||
setLogs(data.result);
|
||||
store.dispatch({ type: 'logs/load', payload: data.result.records });
|
||||
store.dispatch({
|
||||
type: 'logs/load', payload: {
|
||||
fileName: logFileName,
|
||||
logs: data.result.records,
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'metrics':
|
||||
console.info(`Log parsed in ${data.elapsed}ms`);
|
||||
|
@ -202,11 +215,31 @@ const Logs = ({
|
|||
};
|
||||
} catch (error) {
|
||||
setFetchError(error as Error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
if (!loadedLogs.length) {
|
||||
// user navigated to logs root page
|
||||
if (!routeMatch?.params.fileName && tuneData.logFiles?.length) {
|
||||
// either redirect to the first log or to the latest selected
|
||||
if (loadedLogs.fileName) {
|
||||
navigate(generatePath(Routes.TUNE_LOGS_FILE, { tuneId: tuneData.tuneId, fileName: loadedLogs.fileName }));
|
||||
} else {
|
||||
const firstLogFile = (tuneData.logFiles || [])[0];
|
||||
navigate(generatePath(Routes.TUNE_LOGS_FILE, { tuneId: tuneData.tuneId, fileName: firstLogFile }));
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// first visit, logs are not loaded yet
|
||||
if (!(loadedLogs.logs || []).length && tuneData.tuneId) {
|
||||
loadData();
|
||||
}
|
||||
|
||||
// file changed, reload
|
||||
if ((loadedLogs.logs || []).length && loadedLogs.fileName !== routeMatch?.params.fileName) {
|
||||
setLogs(undefined);
|
||||
store.dispatch({ type: 'logs/load', payload: {} });
|
||||
loadData();
|
||||
}
|
||||
|
||||
|
@ -224,12 +257,12 @@ const Logs = ({
|
|||
window.removeEventListener('resize', calculateCanvasSize);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [calculateCanvasSize, config?.datalog, config?.outputChannels, loadedLogs, ui.sidebarCollapsed]);
|
||||
}, [calculateCanvasSize, config?.datalog, config?.outputChannels, loadedLogs, ui.sidebarCollapsed, routeMatch?.params.fileName]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Sider {...(siderProps as any)} className="app-sidebar">
|
||||
{!logs && !loadedLogs.length ?
|
||||
{!logs && !(loadedLogs.logs || []).length ?
|
||||
<Loader />
|
||||
:
|
||||
!ui.sidebarCollapsed &&
|
||||
|
@ -279,7 +312,15 @@ const Logs = ({
|
|||
<PerfectScrollbar options={{ suppressScrollX: true }}>
|
||||
{tuneData.logFiles?.map((fileName) => (
|
||||
<Typography.Paragraph key={fileName}>
|
||||
<Link
|
||||
to={generatePath(Routes.TUNE_LOGS_FILE, { tuneId: tuneData.tuneId, fileName })}
|
||||
style={
|
||||
routeMatch?.params.fileName === fileName ?
|
||||
{} : { color: 'inherit' }
|
||||
}
|
||||
>
|
||||
{fileName}
|
||||
</Link>
|
||||
</Typography.Paragraph>
|
||||
))}
|
||||
</PerfectScrollbar>
|
||||
|
@ -292,10 +333,10 @@ const Logs = ({
|
|||
<Layout style={{ width: '100%', textAlign: 'center', marginTop: 50 }}>
|
||||
<Content>
|
||||
<div ref={contentRef} style={{ width: '100%', marginRight: margin }}>
|
||||
{logs || !!loadedLogs.length
|
||||
{logs || !!(loadedLogs.logs || []).length
|
||||
?
|
||||
<LogCanvas
|
||||
data={loadedLogs || (logs!.records as LogsType)}
|
||||
data={loadedLogs.logs || (logs!.records as LogsType)}
|
||||
width={canvasWidth}
|
||||
height={canvasHeight}
|
||||
selectedFields1={prepareSelectedFields(selectedFields1)}
|
||||
|
|
|
@ -8,6 +8,7 @@ export enum Routes {
|
|||
TUNE_TUNE = '/t/:tuneId/tune',
|
||||
TUNE_DIALOG = '/t/:tuneId/tune/:category/:dialog',
|
||||
TUNE_LOGS = '/t/:tuneId/logs',
|
||||
TUNE_LOGS_FILE = '/t/:tuneId/logs/:fileName',
|
||||
TUNE_DIAGNOSE = '/t/:tuneId/diagnose',
|
||||
|
||||
UPLOAD = '/upload',
|
||||
|
|
|
@ -39,7 +39,7 @@ const initialState: AppState = {
|
|||
details: {} as any,
|
||||
},
|
||||
tuneData: {} as any,
|
||||
logs: [],
|
||||
logs: {} as any,
|
||||
config: {} as any,
|
||||
ui: {
|
||||
sidebarCollapsed: false,
|
||||
|
|
|
@ -11,7 +11,10 @@ export interface TuneState extends TuneWithDetails {}
|
|||
|
||||
export interface TuneDataState extends TunesRecordFull {}
|
||||
|
||||
export interface LogsState extends Logs {}
|
||||
export interface LogsState {
|
||||
fileName: string;
|
||||
logs: Logs;
|
||||
}
|
||||
|
||||
export interface UIState {
|
||||
sidebarCollapsed: boolean;
|
||||
|
|
Loading…
Reference in New Issue