Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lens] Add lens editor performance metrics #163089

Merged
merged 14 commits into from
Aug 7, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,10 @@ export const GaugeComponent: FC<GaugeRenderProps> = memo(
const onRenderChange = useCallback(
(isRendered: boolean = true) => {
if (isRendered) {
renderComplete();
// this requestAnimationFrame call is a temporary fix for https://github.com/elastic/elastic-charts/issues/2124
window.requestAnimationFrame(() => {
renderComplete();
});
}
},
[renderComplete]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,10 @@ export const HeatmapComponent: FC<HeatmapRenderProps> = memo(
const onRenderChange = useCallback(
(isRendered: boolean = true) => {
if (isRendered) {
renderComplete();
// this requestAnimationFrame call is a temporary fix for https://github.com/elastic/elastic-charts/issues/2124
window.requestAnimationFrame(() => {
renderComplete();
});
}
},
[renderComplete]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,11 @@ describe('MetricVisComponent', function () {
});

it('should report render complete', () => {
jest.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => {
cb(0);
return 0;
});

const renderCompleteSpy = jest.fn();
const component = shallow(
<MetricVis
Expand All @@ -995,6 +1000,8 @@ describe('MetricVisComponent', function () {
component.find(Settings).props().onRenderChange!(true);

expect(renderCompleteSpy).toHaveBeenCalledTimes(1);

(window.requestAnimationFrame as jest.Mock).mockRestore();
});

it('should convert null values to NaN', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@ export const MetricVis = ({
const onRenderChange = useCallback<RenderChangeListener>(
(isRendered) => {
if (isRendered) {
renderComplete();
// this requestAnimationFrame call is a temporary fix for https://github.com/elastic/elastic-charts/issues/2124
window.requestAnimationFrame(() => {
renderComplete();
});
}
},
[renderComplete]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,11 @@ const PartitionVisComponent = (props: PartitionVisComponentProps) => {
const onRenderChange = useCallback(
(isRendered: boolean = true) => {
if (isRendered) {
props.renderComplete();
setChartIsLoaded(true);
// this requestAnimationFrame call is a temporary fix for https://github.com/elastic/elastic-charts/issues/2124
window.requestAnimationFrame(() => {
props.renderComplete();
setChartIsLoaded(true);
});
}
},
[props]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,10 @@ export const TagCloudChart = ({
const onRenderChange = useCallback<RenderChangeListener>(
(isRendered) => {
if (isRendered) {
renderComplete();
// this requestAnimationFrame call is a temporary fix for https://github.com/elastic/elastic-charts/issues/2124
window.requestAnimationFrame(() => {
renderComplete();
});
}
},
[renderComplete]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,10 @@ export function XYChart({
const onRenderChange = useCallback(
(isRendered: boolean = true) => {
if (isRendered) {
renderComplete();
// this requestAnimationFrame call is a temporary fix for https://github.com/elastic/elastic-charts/issues/2124
window.requestAnimationFrame(() => {
renderComplete();
});
}
},
[renderComplete]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,4 @@
flex-direction: column;
align-items: center;
justify-content: center;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ import {
selectFrameDatasourceAPI,
} from '../../state_management';
import { filterAndSortUserMessages } from '../../app_plugin/get_application_user_messages';

const MAX_SUGGESTIONS_DISPLAYED = 5;
const LOCAL_STORAGE_SUGGESTIONS_PANEL = 'LENS_SUGGESTIONS_PANEL_HIDDEN';

Expand Down Expand Up @@ -108,11 +107,13 @@ const PreviewRenderer = ({
ExpressionRendererComponent,
expression,
hasError,
onRender,
}: {
withLabel: boolean;
expression: string | null | undefined;
ExpressionRendererComponent: ReactExpressionRendererType;
hasError: boolean;
onRender: () => void;
}) => {
const onErrorMessage = (
<div className="lnsSuggestionPanel__suggestionIcon">
Expand Down Expand Up @@ -143,6 +144,7 @@ const PreviewRenderer = ({
padding="s"
renderMode="preview"
expression={expression}
onRender$={onRender}
debounce={2000}
renderError={() => {
return onErrorMessage;
Expand All @@ -159,6 +161,7 @@ const SuggestionPreview = ({
selected,
onSelect,
showTitleAsLabel,
onRender,
}: {
onSelect: () => void;
preview: {
Expand All @@ -170,6 +173,7 @@ const SuggestionPreview = ({
ExpressionRenderer: ReactExpressionRendererType;
selected: boolean;
showTitleAsLabel?: boolean;
onRender: () => void;
}) => {
return (
<EuiToolTip content={preview.title}>
Expand All @@ -194,6 +198,7 @@ const SuggestionPreview = ({
expression={preview.expression && toExpression(preview.expression)}
withLabel={Boolean(showTitleAsLabel)}
hasError={Boolean(preview.error)}
onRender={onRender}
/>
) : (
<span className="lnsSuggestionPanel__suggestionIcon">
Expand Down Expand Up @@ -358,20 +363,36 @@ export function SuggestionPanel({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [existsStagedPreview]);

if (!activeDatasourceId) {
return null;
}

if (suggestions.length === 0) {
return null;
}
const startTime = useRef<number>(0);
const initialRenderComplete = useRef<boolean>(false);
const suggestionsRendered = useRef<boolean[]>([]);
const totalSuggestions = suggestions.length + 1;

const onSuggestionRender = useCallback((suggestionIndex: number) => {
suggestionsRendered.current[suggestionIndex] = true;
if (initialRenderComplete.current === false && suggestionsRendered.current.every(Boolean)) {
initialRenderComplete.current = true;
// console.log(
// 'time to fetch data and perform initial render for all suggestions',
// performance.now() - startTime.current
// );
Comment on lines +375 to +378
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uncomment for review

}
}, []);

function rollbackToCurrentVisualization() {
const rollbackToCurrentVisualization = useCallback(() => {
if (lastSelectedSuggestion !== -1) {
setLastSelectedSuggestion(-1);
dispatchLens(rollbackSuggestion());
dispatchLens(applyChanges());
}
}, [dispatchLens, lastSelectedSuggestion]);

if (!activeDatasourceId) {
return null;
}

if (suggestions.length === 0) {
return null;
}

const renderApplyChangesPrompt = () => (
Expand Down Expand Up @@ -400,52 +421,58 @@ export function SuggestionPanel({
</EuiPanel>
);

const renderSuggestionsUI = () => (
<>
{currentVisualization.activeId && !hideSuggestions && (
<SuggestionPreview
preview={{
error: currentStateError,
expression: currentStateExpression,
icon:
visualizationMap[currentVisualization.activeId].getDescription(
currentVisualization.state
).icon || 'empty',
title: i18n.translate('xpack.lens.suggestions.currentVisLabel', {
defaultMessage: 'Current visualization',
}),
}}
ExpressionRenderer={AutoRefreshExpressionRenderer}
onSelect={rollbackToCurrentVisualization}
selected={lastSelectedSuggestion === -1}
showTitleAsLabel
/>
)}
{!hideSuggestions &&
suggestions.map((suggestion, index) => {
return (
<SuggestionPreview
preview={{
expression: suggestion.previewExpression,
icon: suggestion.previewIcon,
title: suggestion.title,
}}
ExpressionRenderer={AutoRefreshExpressionRenderer}
key={index}
onSelect={() => {
if (lastSelectedSuggestion === index) {
rollbackToCurrentVisualization();
} else {
setLastSelectedSuggestion(index);
switchToSuggestion(dispatchLens, suggestion, { applyImmediately: true });
}
}}
selected={index === lastSelectedSuggestion}
/>
);
})}
</>
);
const renderSuggestionsUI = () => {
suggestionsRendered.current = new Array(totalSuggestions).fill(false);
startTime.current = performance.now();
return (
<>
{currentVisualization.activeId && !hideSuggestions && (
<SuggestionPreview
preview={{
error: currentStateError,
expression: currentStateExpression,
icon:
visualizationMap[currentVisualization.activeId].getDescription(
currentVisualization.state
).icon || 'empty',
title: i18n.translate('xpack.lens.suggestions.currentVisLabel', {
defaultMessage: 'Current visualization',
}),
}}
ExpressionRenderer={AutoRefreshExpressionRenderer}
onSelect={rollbackToCurrentVisualization}
selected={lastSelectedSuggestion === -1}
showTitleAsLabel
onRender={() => onSuggestionRender(0)}
/>
)}
{!hideSuggestions &&
suggestions.map((suggestion, index) => {
return (
<SuggestionPreview
preview={{
expression: suggestion.previewExpression,
icon: suggestion.previewIcon,
title: suggestion.title,
}}
ExpressionRenderer={AutoRefreshExpressionRenderer}
key={index}
onSelect={() => {
if (lastSelectedSuggestion === index) {
rollbackToCurrentVisualization();
} else {
setLastSelectedSuggestion(index);
switchToSuggestion(dispatchLens, suggestion, { applyImmediately: true });
}
}}
selected={index === lastSelectedSuggestion}
onRender={() => onSuggestionRender(index + 1)}
/>
);
})}
</>
);
};

return (
<div className="lnsSuggestionPanel">
Expand Down
Loading