// Copyright 2022 The Parca Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import {useCallback, useEffect, useMemo, useState} from 'react'; import {QueryServiceClient} from '@parca/client'; import {Query} from '@parca/parser'; import {TEST_IDS, testId} from '@parca/test-utils'; import {ProfileDiffSource, ProfileViewWithData} from '..'; import ProfileSelector from '../ProfileSelector'; import {useCompareModeMeta} from '../hooks/useCompareModeMeta'; import {useQueryState} from '../hooks/useQueryState'; interface ProfileExplorerCompareProps { queryClient: QueryServiceClient; } const ProfileExplorerCompare = ({queryClient}: ProfileExplorerCompareProps): JSX.Element => { const [showMetricsGraph, setShowMetricsGraph] = useState(true); const {closeCompareMode, isCompareMode, isCompareAbsolute} = useCompareModeMeta(); // Read ProfileSource states from URL for both sides const {profileSource: profileSourceA, querySelection: querySelectionA} = useQueryState({ suffix: '_a', comparing: true, }); const { profileSource: profileSourceB, querySelection: querySelectionB, commitDraft: commitDraftB, setDraftExpression: setDraftExpressionB, setDraftTimeRange: setDraftTimeRangeB, } = useQueryState({suffix: '_b', comparing: true}); // Derive enforced profile name from side A's expression const enforcedProfileNameA = useMemo(() => { return querySelectionA.expression !== '' ? Query.parse(querySelectionA.expression).profileName() : ''; }, [querySelectionA.expression]); // Initialize side B with side A's values if side B is empty useEffect(() => { // If not in compare mode, don't initialize if (!isCompareMode) { return; } if (querySelectionB.expression === '' && querySelectionA.expression !== '') { setDraftExpressionB(querySelectionA.expression); setDraftTimeRangeB(querySelectionA.from, querySelectionA.to, querySelectionA.timeSelection); // Commit with explicit values since draft useState hasn't applied yet commitDraftB( { from: querySelectionA.from, to: querySelectionA.to, timeSelection: querySelectionA.timeSelection, }, querySelectionA.expression ); } }, [ isCompareMode, querySelectionA.expression, querySelectionA.from, querySelectionA.to, querySelectionA.timeSelection, querySelectionB.expression, setDraftExpressionB, setDraftTimeRangeB, commitDraftB, ]); const closeProfileA = useCallback((): void => { closeCompareMode('A'); }, [closeCompareMode]); const closeProfileB = useCallback((): void => { closeCompareMode('B'); }, [closeCompareMode]); return (
{profileSourceA != null && profileSourceB != null ? (
) : (

Select a profile on both sides.

)}
); }; export default ProfileExplorerCompare;