Skip to content

Commit

Permalink
[Logs UI] Refactor log position to hooks (#53540)
Browse files Browse the repository at this point in the history
* Move URL state to hook

* Fix log filter URL state infinite loop

* Initial refactor of log position to hooks

* Simplify and reimplement controlsShouldDisplayTargetPosition

* Fix live streaming

* Flatten logposition destructuring

* Revert "Move URL state to hook"

This reverts commit 4e04aa0.

# Conflicts:
#	x-pack/legacy/plugins/infra/public/containers/logs/log_filter/use_log_filter_url_state.tsx
#	x-pack/legacy/plugins/infra/public/pages/logs/stream/page_providers.tsx

* Fix unused imports

* Fix link-to test

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
Zacqary and elasticmachine authored Jan 7, 2020
1 parent b7a534b commit f5448bd
Show file tree
Hide file tree
Showing 32 changed files with 391 additions and 781 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import React, { useContext } from 'react';
import { transparentize } from 'polished';

import euiStyled from '../../../../../../common/eui_styled_components';
Expand All @@ -21,28 +21,26 @@ import {
LogEntryColumnWidths,
} from './log_entry_column';
import { ASSUMED_SCROLLBAR_WIDTH } from './vertical_scroll_panel';
import { WithLogPosition } from '../../../containers/logs/with_log_position';
import { LogPositionState } from '../../../containers/logs/log_position';
import { localizedDate } from '../../../utils/formatters/datetime';

export const LogColumnHeaders: React.FunctionComponent<{
columnConfigurations: LogColumnConfiguration[];
columnWidths: LogEntryColumnWidths;
}> = ({ columnConfigurations, columnWidths }) => {
const { firstVisiblePosition } = useContext(LogPositionState.Context);
return (
<LogColumnHeadersWrapper>
{columnConfigurations.map(columnConfiguration => {
if (isTimestampLogColumnConfiguration(columnConfiguration)) {
return (
<WithLogPosition key={columnConfiguration.timestampColumn.id}>
{({ firstVisiblePosition }) => (
<LogColumnHeader
columnWidth={columnWidths[columnConfiguration.timestampColumn.id]}
data-test-subj="logColumnHeader timestampLogColumnHeader"
>
{firstVisiblePosition ? localizedDate(firstVisiblePosition.time) : 'Timestamp'}
</LogColumnHeader>
)}
</WithLogPosition>
<LogColumnHeader
key={columnConfiguration.timestampColumn.id}
columnWidth={columnWidths[columnConfiguration.timestampColumn.id]}
data-test-subj="logColumnHeader timestampLogColumnHeader"
>
{firstVisiblePosition ? localizedDate(firstVisiblePosition.time) : 'Timestamp'}
</LogColumnHeader>
);
} else if (isMessageLogColumnConfiguration(columnConfiguration)) {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,13 @@ interface ScrollableLogTextStreamViewProps {
setFlyoutVisibility: (visible: boolean) => void;
highlightedItem: string | null;
currentHighlightKey: UniqueTimeKey | null;
scrollLock: {
enable: () => void;
disable: () => void;
isEnabled: boolean;
};
}

interface ScrollableLogTextStreamViewState {
target: TimeKey | null;
targetId: string | null;
items: StreamItem[];
isScrollLocked: boolean;
}

export class ScrollableLogTextStreamView extends React.PureComponent<
Expand All @@ -81,8 +77,7 @@ export class ScrollableLogTextStreamView extends React.PureComponent<

// Prevent new entries from being appended and moving the stream forward when
// the user has scrolled up during live streaming
const nextItems =
hasItems && nextProps.scrollLock.isEnabled ? prevState.items : nextProps.items;
const nextItems = hasItems && prevState.isScrollLocked ? prevState.items : nextProps.items;

if (nextProps.isStreaming && hasItems) {
return {
Expand Down Expand Up @@ -121,6 +116,7 @@ export class ScrollableLogTextStreamView extends React.PureComponent<
target: null,
targetId: null,
items: props.items,
isScrollLocked: false,
};
}

Expand All @@ -137,9 +133,8 @@ export class ScrollableLogTextStreamView extends React.PureComponent<
lastLoadedTime,
scale,
wrap,
scrollLock,
} = this.props;
const { targetId, items } = this.state;
const { targetId, items, isScrollLocked } = this.state;
const hasItems = items.length > 0;
return (
<ScrollableLogTextStreamViewWrapper>
Expand Down Expand Up @@ -187,7 +182,7 @@ export class ScrollableLogTextStreamView extends React.PureComponent<
target={targetId}
hideScrollbar={true}
data-test-subj={'logStream'}
isLocked={scrollLock.isEnabled}
isLocked={isScrollLocked}
entriesCount={items.length}
>
{registerChild => (
Expand Down Expand Up @@ -248,7 +243,7 @@ export class ScrollableLogTextStreamView extends React.PureComponent<
lastStreamingUpdate={isStreaming ? lastLoadedTime : null}
onLoadMore={this.handleLoadNewerItems}
/>
{scrollLock.isEnabled && (
{isScrollLocked && (
<LogTextStreamJumpToTail
width={width}
onClickJump={this.handleJumpToTail}
Expand Down Expand Up @@ -308,7 +303,9 @@ export class ScrollableLogTextStreamView extends React.PureComponent<
fromScroll: boolean;
}) => {
if (fromScroll && this.props.isStreaming) {
this.props.scrollLock[pagesBelow === 0 ? 'disable' : 'enable']();
this.setState({
isScrollLocked: pagesBelow !== 0,
});
}
this.props.reportVisibleInterval({
endKey: parseStreamItemId(bottomChild),
Expand All @@ -322,11 +319,11 @@ export class ScrollableLogTextStreamView extends React.PureComponent<
);

private handleJumpToTail = () => {
const { items, scrollLock } = this.props;
scrollLock.disable();
const { items } = this.props;
const lastItemTarget = getStreamItemId(items[items.length - 1]);
this.setState({
targetId: lastItemTarget,
isScrollLocked: false,
});
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
import { useEffect, useState, useReducer, useCallback } from 'react';
import createContainer from 'constate';
import { pick, throttle } from 'lodash';
import { pick, throttle, omit } from 'lodash';
import { useGraphQLQueries } from './gql_queries';
import { TimeKey, timeKeyIsBetween } from '../../../../common/time';
import { InfraLogEntry } from './types';
Expand Down Expand Up @@ -45,6 +45,7 @@ interface LogEntriesProps {
pagesAfterEnd: number | null;
sourceId: string;
isAutoReloading: boolean;
jumpToTargetPosition: (position: TimeKey) => void;
}

type FetchEntriesParams = Omit<LogEntriesProps, 'isAutoReloading'>;
Expand All @@ -65,7 +66,7 @@ export type LogEntriesStateParams = {
} & LogEntriesResponse;

export interface LogEntriesCallbacks {
fetchNewerEntries: () => Promise<void>;
fetchNewerEntries: () => Promise<TimeKey | null | undefined>;
}
export const logEntriesInitialCallbacks = {
fetchNewerEntries: async () => {},
Expand Down Expand Up @@ -127,10 +128,13 @@ const useFetchEntriesEffect = (
const [prevParams, cachePrevParams] = useState(props);
const [startedStreaming, setStartedStreaming] = useState(false);

const runFetchNewEntriesRequest = async () => {
const runFetchNewEntriesRequest = async (override = {}) => {
dispatch({ type: Action.FetchingNewEntries });
try {
const payload = await getLogEntriesAround(props);
const payload = await getLogEntriesAround({
...omit(props, 'jumpToTargetPosition'),
...override,
});
dispatch({ type: Action.ReceiveNewEntries, payload });
} catch (e) {
dispatch({ type: Action.ErrorOnNewEntries });
Expand All @@ -150,6 +154,7 @@ const useFetchEntriesEffect = (
type: getEntriesBefore ? Action.ReceiveEntriesBefore : Action.ReceiveEntriesAfter,
payload,
});
return payload.entriesEnd;
} catch (e) {
dispatch({ type: Action.ErrorOnMoreEntries });
}
Expand Down Expand Up @@ -185,19 +190,37 @@ const useFetchEntriesEffect = (

const fetchNewerEntries = useCallback(
throttle(() => runFetchMoreEntriesRequest(ShouldFetchMoreEntries.After), 500),
[props]
[props, state.entriesEnd]
);

const streamEntriesEffectDependencies = [props.isAutoReloading, state.isLoadingMore];
const streamEntriesEffectDependencies = [
props.isAutoReloading,
state.isLoadingMore,
state.isReloading,
];
const streamEntriesEffect = () => {
(async () => {
if (props.isAutoReloading && !state.isLoadingMore) {
if (props.isAutoReloading && !state.isLoadingMore && !state.isReloading) {
if (startedStreaming) {
await new Promise(res => setTimeout(res, 5000));
} else {
const nowKey = {
tiebreaker: 0,
time: Date.now(),
};
props.jumpToTargetPosition(nowKey);
setStartedStreaming(true);
if (state.hasMoreAfterEnd) {
runFetchNewEntriesRequest({
timeKey: nowKey,
});
return;
}
}
const newEntriesEnd = await runFetchMoreEntriesRequest(ShouldFetchMoreEntries.After);
if (newEntriesEnd) {
props.jumpToTargetPosition(newEntriesEnd);
}
fetchNewerEntries();
} else if (!props.isAutoReloading) {
setStartedStreaming(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@
*/

export * from './log_highlights';
export * from './redux_bridges';
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { useState, useContext } from 'react';
import { useLogEntryHighlights } from './log_entry_highlights';
import { useLogSummaryHighlights } from './log_summary_highlights';
import { useNextAndPrevious } from './next_and_previous';
import { useReduxBridgeSetters } from './redux_bridge_setters';
import { useLogSummaryBufferInterval } from '../log_summary';
import { LogViewConfiguration } from '../log_view_configuration';
import { LogPositionState } from '../log_position';
import { TimeKey } from '../../../../common/time';

export const useLogHighlightsState = ({
Expand All @@ -28,14 +28,7 @@ export const useLogHighlightsState = ({
filterQuery: string | null;
}) => {
const [highlightTerms, setHighlightTerms] = useState<string[]>([]);
const {
visibleMidpoint,
setFilterQuery,
setVisibleMidpoint,
jumpToTarget,
setJumpToTarget,
} = useReduxBridgeSetters();

const { visibleMidpoint, jumpToTargetPosition } = useContext(LogPositionState.Context);
const { intervalSize: summaryIntervalSize } = useContext(LogViewConfiguration.Context);
const {
start: summaryStart,
Expand Down Expand Up @@ -79,25 +72,22 @@ export const useLogHighlightsState = ({
visibleMidpoint,
logEntryHighlights,
highlightTerms,
jumpToTarget,
jumpToTargetPosition,
});

return {
highlightTerms,
setHighlightTerms,
setFilterQuery,
logEntryHighlights,
logEntryHighlightsById,
logSummaryHighlights,
loadLogEntryHighlightsRequest,
loadLogSummaryHighlightsRequest,
setVisibleMidpoint,
currentHighlightKey,
hasPreviousHighlight,
hasNextHighlight,
goToPreviousHighlight,
goToNextHighlight,
setJumpToTarget,
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import { LogEntryHighlights } from './log_entry_highlights';

export const useNextAndPrevious = ({
highlightTerms,
jumpToTarget,
jumpToTargetPosition,
logEntryHighlights,
visibleMidpoint,
}: {
highlightTerms: string[];
jumpToTarget: (target: TimeKey) => void;
jumpToTargetPosition: (target: TimeKey) => void;
logEntryHighlights: LogEntryHighlights | undefined;
visibleMidpoint: TimeKey | null;
}) => {
Expand All @@ -41,9 +41,9 @@ export const useNextAndPrevious = ({

useEffect(() => {
if (currentTimeKey) {
jumpToTarget(currentTimeKey);
jumpToTargetPosition(currentTimeKey);
}
}, [currentTimeKey, jumpToTarget]);
}, [currentTimeKey, jumpToTargetPosition]);

useEffect(() => {
if (currentTimeKey === null && entries.length > 0) {
Expand Down

This file was deleted.

This file was deleted.

Loading

0 comments on commit f5448bd

Please sign in to comment.