mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-13 02:19:02 +08:00
fix[logs][FE]: live tail is fixed (#1759)
* fix: live tail is fixed * fix: graph state is updated * chore: step size is updated * chore: xaxis config is updated * chore: isDisabled state is updated for top navigation * chore: selected interval is updated in the reducer * fix: build is fixed * chore: xAxis config is updated Co-authored-by: Pranay Prateek <pranay@signoz.io> Co-authored-by: Ankit Nayan <ankit@signoz.io>
This commit is contained in:
parent
d06d41af87
commit
6c9036fbf4
@ -4,9 +4,6 @@ import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
interface ITimeUnit {
|
||||
[key: string]: TimeUnit;
|
||||
}
|
||||
interface IAxisTimeUintConfig {
|
||||
unitName: TimeUnit;
|
||||
multiplier: number;
|
||||
@ -22,7 +19,7 @@ export interface ITimeRange {
|
||||
maxTime: number | null;
|
||||
}
|
||||
|
||||
export const TIME_UNITS: ITimeUnit = {
|
||||
export const TIME_UNITS: Record<TimeUnit, TimeUnit> = {
|
||||
millisecond: 'millisecond',
|
||||
second: 'second',
|
||||
minute: 'minute',
|
||||
@ -31,6 +28,7 @@ export const TIME_UNITS: ITimeUnit = {
|
||||
week: 'week',
|
||||
month: 'month',
|
||||
year: 'year',
|
||||
quarter: 'quarter',
|
||||
};
|
||||
|
||||
const TIME_UNITS_CONFIG: IAxisTimeUintConfig[] = [
|
||||
@ -93,6 +91,7 @@ export const convertTimeRange = (
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
return {
|
||||
unitName: relevantTimeUnit.unitName,
|
||||
stepSize: Math.floor(stepSize) || 1,
|
||||
|
@ -11,6 +11,7 @@ import { throttle } from 'lodash-es';
|
||||
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { UPDATE_AUTO_REFRESH_DISABLED } from 'types/actions/globalTime';
|
||||
import {
|
||||
FLUSH_LOGS,
|
||||
PUSH_LIVE_TAIL_EVENT,
|
||||
@ -19,6 +20,7 @@ import {
|
||||
} from 'types/actions/logs';
|
||||
import { TLogsLiveTailState } from 'types/api/logs/liveTail';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
import { ILogsReducer } from 'types/reducer/logs';
|
||||
|
||||
import { TIME_PICKER_OPTIONS } from './config';
|
||||
@ -34,12 +36,20 @@ function LogLiveTail(): JSX.Element {
|
||||
logs,
|
||||
} = useSelector<AppState, ILogsReducer>((state) => state.logs);
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const { selectedAutoRefreshInterval } = useSelector<AppState, GlobalReducer>(
|
||||
(state) => state.globalTime,
|
||||
);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const handleLiveTail = (toggleState: TLogsLiveTailState): void => {
|
||||
dispatch({
|
||||
type: TOGGLE_LIVE_TAIL,
|
||||
payload: toggleState,
|
||||
});
|
||||
dispatch({
|
||||
type: UPDATE_AUTO_REFRESH_DISABLED,
|
||||
payload: toggleState === 'PLAYING',
|
||||
});
|
||||
};
|
||||
|
||||
const batchedEventsRef = useRef<Record<string, unknown>[]>([]);
|
||||
@ -131,6 +141,10 @@ function LogLiveTail(): JSX.Element {
|
||||
[dispatch, liveTail, liveTailStartRange],
|
||||
);
|
||||
|
||||
const isDisabled = useMemo(() => selectedAutoRefreshInterval?.length > 0, [
|
||||
selectedAutoRefreshInterval,
|
||||
]);
|
||||
|
||||
return (
|
||||
<TimePickerCard>
|
||||
<Space size={0} align="center">
|
||||
@ -149,6 +163,7 @@ function LogLiveTail(): JSX.Element {
|
||||
type="primary"
|
||||
onClick={handleLiveTailStart}
|
||||
title="Start live tail"
|
||||
disabled={isDisabled}
|
||||
>
|
||||
Go Live <PlayCircleOutlined />
|
||||
</Button>
|
||||
|
@ -31,6 +31,7 @@ function LogsAggregate({ getLogsAggregate }: LogsAggregateProps): JSX.Element {
|
||||
);
|
||||
|
||||
const reFetchIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
switch (liveTail) {
|
||||
case 'STOPPED': {
|
||||
@ -38,18 +39,6 @@ function LogsAggregate({ getLogsAggregate }: LogsAggregateProps): JSX.Element {
|
||||
clearInterval(reFetchIntervalRef.current);
|
||||
}
|
||||
reFetchIntervalRef.current = null;
|
||||
// getLogsAggregate({
|
||||
// timestampStart: minTime,
|
||||
// timestampEnd: maxTime,
|
||||
// step: getStep({
|
||||
// start: minTime,
|
||||
// end: maxTime,
|
||||
// inputFormat: 'ns',
|
||||
// }),
|
||||
// q: queryString,
|
||||
// ...(idStart ? { idGt: idStart } : {}),
|
||||
// ...(idEnd ? { idLt: idEnd } : {}),
|
||||
// });
|
||||
break;
|
||||
}
|
||||
|
||||
@ -106,7 +95,7 @@ function LogsAggregate({ getLogsAggregate }: LogsAggregateProps): JSX.Element {
|
||||
}}
|
||||
type="bar"
|
||||
containerHeight="100%"
|
||||
animate={false}
|
||||
animate
|
||||
/>
|
||||
)}
|
||||
</Container>
|
||||
|
@ -21,7 +21,7 @@ import { v4 } from 'uuid';
|
||||
|
||||
import { SearchFieldsProps } from '..';
|
||||
import FieldKey from '../FieldKey';
|
||||
import { QueryConditionContainer, QueryFieldContainer } from '../styles';
|
||||
import { QueryFieldContainer } from '../styles';
|
||||
import { createParsedQueryStructure } from '../utils';
|
||||
import { Container, QueryWrapper } from './styles';
|
||||
import { hashCode, parseQuery } from './utils';
|
||||
@ -32,33 +32,27 @@ function QueryConditionField({
|
||||
query,
|
||||
queryIndex,
|
||||
onUpdate,
|
||||
style,
|
||||
}: QueryConditionFieldProps): JSX.Element {
|
||||
const allOptions = Object.values(ConditionalOperators);
|
||||
return (
|
||||
<QueryConditionContainer style={{ ...style }}>
|
||||
<Select
|
||||
defaultValue={
|
||||
(query as any).value &&
|
||||
(((query as any)?.value as any) as string).toUpperCase()
|
||||
}
|
||||
onChange={(e): void => {
|
||||
onUpdate({ ...query, value: e }, queryIndex);
|
||||
}}
|
||||
>
|
||||
{Object.values(ConditionalOperators).map((cond) => (
|
||||
<Option key={cond} value={cond} label={cond}>
|
||||
{cond}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</QueryConditionContainer>
|
||||
<Select
|
||||
defaultValue={
|
||||
(query as any).value &&
|
||||
(((query as any)?.value as any) as string).toUpperCase()
|
||||
}
|
||||
onChange={(e): void => {
|
||||
onUpdate({ ...query, value: e }, queryIndex);
|
||||
}}
|
||||
>
|
||||
{allOptions.map((cond) => (
|
||||
<Option key={cond} value={cond} label={cond}>
|
||||
{cond}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
|
||||
QueryConditionField.defaultProps = {
|
||||
style: undefined,
|
||||
};
|
||||
|
||||
interface QueryFieldProps {
|
||||
query: Query;
|
||||
queryIndex: number;
|
||||
@ -174,7 +168,6 @@ interface QueryConditionFieldProps {
|
||||
query: { value: string | string[]; type: string }[];
|
||||
queryIndex: number;
|
||||
onUpdate: (arg0: unknown, arg1: number) => void;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export type Query = { value: string | string[]; type: string }[];
|
||||
@ -233,12 +226,13 @@ function QueryBuilder({
|
||||
);
|
||||
|
||||
return (
|
||||
<QueryConditionField
|
||||
key={keyPrefix + idx}
|
||||
query={query}
|
||||
queryIndex={idx}
|
||||
onUpdate={handleUpdate as never}
|
||||
/>
|
||||
<div key={keyPrefix + idx}>
|
||||
<QueryConditionField
|
||||
query={query}
|
||||
queryIndex={idx}
|
||||
onUpdate={handleUpdate as never}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -14,8 +14,3 @@ export const QueryFieldContainer = styled.div`
|
||||
background: ${blue[6]};
|
||||
}
|
||||
`;
|
||||
|
||||
export const QueryConditionContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
`;
|
||||
|
@ -104,7 +104,8 @@ function SearchFilter({
|
||||
|
||||
useEffect(() => {
|
||||
handleSearch(urlQueryString || '');
|
||||
}, [handleSearch, urlQueryString]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [urlQueryString, maxTime, minTime]);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
|
@ -22,19 +22,28 @@ import { useInterval } from 'react-use';
|
||||
import { Dispatch } from 'redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppActions from 'types/actions';
|
||||
import { UPDATE_TIME_INTERVAL } from 'types/actions/globalTime';
|
||||
import {
|
||||
UPDATE_AUTO_REFRESH_INTERVAL,
|
||||
UPDATE_TIME_INTERVAL,
|
||||
} from 'types/actions/globalTime';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { options } from './config';
|
||||
import { ButtonContainer, Container } from './styles';
|
||||
|
||||
function AutoRefresh({ disabled = false }: AutoRefreshProps): JSX.Element {
|
||||
const { minTime: initialMinTime, selectedTime } = useSelector<
|
||||
AppState,
|
||||
GlobalReducer
|
||||
>((state) => state.globalTime);
|
||||
const {
|
||||
minTime: initialMinTime,
|
||||
selectedTime,
|
||||
isAutoRefreshDisabled,
|
||||
} = useSelector<AppState, GlobalReducer>((state) => state.globalTime);
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const isDisabled = useMemo(() => disabled || isAutoRefreshDisabled, [
|
||||
isAutoRefreshDisabled,
|
||||
disabled,
|
||||
]);
|
||||
|
||||
const localStorageData = JSON.parse(get(DASHBOARD_TIME_IN_DURATION) || '{}');
|
||||
|
||||
const localStorageValue = useMemo(() => localStorageData[pathname], [
|
||||
@ -46,13 +55,19 @@ function AutoRefresh({ disabled = false }: AutoRefreshProps): JSX.Element {
|
||||
Boolean(localStorageValue),
|
||||
);
|
||||
|
||||
const dispatch = useDispatch<Dispatch<AppActions>>();
|
||||
|
||||
useEffect(() => {
|
||||
setIsAutoRefreshfreshEnabled(Boolean(localStorageValue));
|
||||
}, [localStorageValue]);
|
||||
const isAutoRefreshEnabled = Boolean(localStorageValue);
|
||||
dispatch({
|
||||
type: UPDATE_AUTO_REFRESH_INTERVAL,
|
||||
payload: localStorageValue,
|
||||
});
|
||||
setIsAutoRefreshfreshEnabled(isAutoRefreshEnabled);
|
||||
}, [localStorageValue, dispatch]);
|
||||
|
||||
const params = useUrlQuery();
|
||||
|
||||
const dispatch = useDispatch<Dispatch<AppActions>>();
|
||||
const [selectedOption, setSelectedOption] = useState<string>(
|
||||
localStorageValue || options[0].key,
|
||||
);
|
||||
@ -69,7 +84,7 @@ function AutoRefresh({ disabled = false }: AutoRefreshProps): JSX.Element {
|
||||
useInterval(() => {
|
||||
const selectedValue = getOption?.value;
|
||||
|
||||
if (disabled || !isAutoRefreshEnabled) {
|
||||
if (isDisabled || !isAutoRefreshEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -125,21 +140,23 @@ function AutoRefresh({ disabled = false }: AutoRefreshProps): JSX.Element {
|
||||
<Checkbox
|
||||
onChange={onChangeAutoRefreshHandler}
|
||||
checked={isAutoRefreshEnabled}
|
||||
disabled={disabled}
|
||||
disabled={isDisabled}
|
||||
>
|
||||
Auto Refresh
|
||||
</Checkbox>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Typography.Paragraph>Refresh Interval</Typography.Paragraph>
|
||||
<Typography.Paragraph disabled={isDisabled}>
|
||||
Refresh Interval
|
||||
</Typography.Paragraph>
|
||||
|
||||
<Radio.Group onChange={onChangeHandler} value={selectedOption}>
|
||||
<Space direction="vertical">
|
||||
{options
|
||||
.filter((e) => e.label !== 'off')
|
||||
.map((option) => (
|
||||
<Radio key={option.key} value={option.key}>
|
||||
<Radio disabled={isDisabled} key={option.key} value={option.key}>
|
||||
{option.label}
|
||||
</Radio>
|
||||
))}
|
||||
|
@ -2,6 +2,8 @@ import { getDefaultOption } from 'container/TopNav/DateTimeSelection/config';
|
||||
import {
|
||||
GLOBAL_TIME_LOADING_START,
|
||||
GlobalTimeAction,
|
||||
UPDATE_AUTO_REFRESH_DISABLED,
|
||||
UPDATE_AUTO_REFRESH_INTERVAL,
|
||||
UPDATE_TIME_INTERVAL,
|
||||
} from 'types/actions/globalTime';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
@ -13,6 +15,8 @@ const intitalState: GlobalReducer = {
|
||||
selectedTime: getDefaultOption(
|
||||
typeof window !== 'undefined' ? window?.location?.pathname : '',
|
||||
),
|
||||
isAutoRefreshDisabled: false,
|
||||
selectedAutoRefreshInterval: '',
|
||||
};
|
||||
|
||||
const globalTimeReducer = (
|
||||
@ -35,6 +39,20 @@ const globalTimeReducer = (
|
||||
};
|
||||
}
|
||||
|
||||
case UPDATE_AUTO_REFRESH_DISABLED: {
|
||||
return {
|
||||
...state,
|
||||
isAutoRefreshDisabled: action.payload,
|
||||
};
|
||||
}
|
||||
|
||||
case UPDATE_AUTO_REFRESH_INTERVAL: {
|
||||
return {
|
||||
...state,
|
||||
selectedAutoRefreshInterval: action.payload,
|
||||
};
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
@ -106,7 +106,6 @@ export const LogsReducer = (
|
||||
}${action.payload}`;
|
||||
|
||||
const updatedParsedQuery = parseQuery(updatedQueryString);
|
||||
console.log({ updatedParsedQuery, updatedQueryString, action });
|
||||
return {
|
||||
...state,
|
||||
searchFilter: {
|
||||
|
@ -2,6 +2,8 @@ import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||
|
||||
export const UPDATE_TIME_INTERVAL = 'UPDATE_TIME_INTERVAL';
|
||||
export const GLOBAL_TIME_LOADING_START = 'GLOBAL_TIME_LOADING_START';
|
||||
export const UPDATE_AUTO_REFRESH_DISABLED = 'UPDATE_AUTO_REFRESH_DISABLED';
|
||||
export const UPDATE_AUTO_REFRESH_INTERVAL = 'UPDATE_AUTO_REFRESH_INTERVAL';
|
||||
|
||||
export type GlobalTime = {
|
||||
maxTime: number;
|
||||
@ -17,8 +19,22 @@ interface UpdateTimeInterval {
|
||||
payload: UpdateTime;
|
||||
}
|
||||
|
||||
interface UpdateAutoRefreshDisabled {
|
||||
type: typeof UPDATE_AUTO_REFRESH_DISABLED;
|
||||
payload: boolean;
|
||||
}
|
||||
|
||||
interface GlobalTimeLoading {
|
||||
type: typeof GLOBAL_TIME_LOADING_START;
|
||||
}
|
||||
|
||||
export type GlobalTimeAction = UpdateTimeInterval | GlobalTimeLoading;
|
||||
interface UpdateAutoRefreshInterval {
|
||||
type: typeof UPDATE_AUTO_REFRESH_INTERVAL;
|
||||
payload: string;
|
||||
}
|
||||
|
||||
export type GlobalTimeAction =
|
||||
| UpdateTimeInterval
|
||||
| GlobalTimeLoading
|
||||
| UpdateAutoRefreshDisabled
|
||||
| UpdateAutoRefreshInterval;
|
||||
|
@ -6,4 +6,6 @@ export interface GlobalReducer {
|
||||
minTime: GlobalTime['minTime'];
|
||||
loading: boolean;
|
||||
selectedTime: Time;
|
||||
isAutoRefreshDisabled: boolean;
|
||||
selectedAutoRefreshInterval: string;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user