From 46aedd58a8be2490ffce3cb713328b52ea61ebb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Hironimuz=20Marcondes?= Date: Wed, 28 Jun 2023 09:42:30 +0100 Subject: [PATCH 01/15] Adding grid --- .../mock_profiling_dependencies_storybook.tsx | 51 ++- .../public/components/topn_functions/grid.tsx | 419 ++++++++++++++++++ .../topn_functions/mock/top_n_functions.ts | 115 +++++ .../topn_functions/topn_functions.stories.tsx | 37 ++ .../public/views/functions/topn/index.tsx | 22 +- 5 files changed, 635 insertions(+), 9 deletions(-) create mode 100644 x-pack/plugins/profiling/public/components/topn_functions/grid.tsx create mode 100644 x-pack/plugins/profiling/public/components/topn_functions/mock/top_n_functions.ts create mode 100644 x-pack/plugins/profiling/public/components/topn_functions/topn_functions.stories.tsx diff --git a/x-pack/plugins/profiling/public/components/contexts/profiling_dependencies/mock_profiling_dependencies_storybook.tsx b/x-pack/plugins/profiling/public/components/contexts/profiling_dependencies/mock_profiling_dependencies_storybook.tsx index 67a28c6839979..9e4ebc0afeae8 100644 --- a/x-pack/plugins/profiling/public/components/contexts/profiling_dependencies/mock_profiling_dependencies_storybook.tsx +++ b/x-pack/plugins/profiling/public/components/contexts/profiling_dependencies/mock_profiling_dependencies_storybook.tsx @@ -9,9 +9,18 @@ import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; import { MlLocatorDefinition } from '@kbn/ml-plugin/public'; import { UrlService } from '@kbn/share-plugin/common/url_service'; +import { createMemoryHistory } from 'history'; +import { merge } from 'lodash'; import React, { ReactNode } from 'react'; import { Observable } from 'rxjs'; -import { ProfilingDependenciesContextProvider } from './profiling_dependencies_context'; +import { RouterProvider } from '@kbn/typed-react-router-config'; +import { + ProfilingDependencies, + ProfilingDependenciesContextProvider, +} from './profiling_dependencies_context'; +import { profilingRouter } from '../../../routing'; +import { TimeRangeContextProvider } from '../time_range_context'; +import { getServices } from '../../../services'; const urlService = new UrlService({ navigate: async () => {}, @@ -73,20 +82,46 @@ const mockProfilingDependenciesContext = { plugins: mockPlugin, } as any; -export function MockProfilingDependenciesStorybook({ children }: { children?: ReactNode }) { +export function MockProfilingDependenciesStorybook({ + children, + profilingContext, + routePath, + mockServices = {}, +}: { + children?: ReactNode; + profilingContext?: Partial; + mockServices?: Partial; + routePath?: string; +}) { + const contextMock = merge({}, mockProfilingDependenciesContext, profilingContext); + const KibanaReactContext = createKibanaReactContext( mockProfilingDependenciesContext.core as unknown as Partial ); + const history = createMemoryHistory({ + initialEntries: [routePath || '/stacktraces'], + }); + + const services = getServices(); + return ( - - {children} - + + + + {children} + + + ); diff --git a/x-pack/plugins/profiling/public/components/topn_functions/grid.tsx b/x-pack/plugins/profiling/public/components/topn_functions/grid.tsx new file mode 100644 index 0000000000000..94521156a1726 --- /dev/null +++ b/x-pack/plugins/profiling/public/components/topn_functions/grid.tsx @@ -0,0 +1,419 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + EuiBadge, + EuiButtonIcon, + EuiDataGrid, + EuiDataGridCellValueElementProps, + EuiDataGridColumn, + EuiDataGridControlColumn, + EuiDataGridSorting, + EuiFlexGroup, + EuiFlexItem, + EuiScreenReaderOnly, + EuiText, + EuiToolTip, + useEuiTheme, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { keyBy } from 'lodash'; +import React, { useMemo, useState } from 'react'; +import { TopNFunctions, TopNFunctionSortField } from '../../../common/functions'; +import { StackFrameMetadata } from '../../../common/profiling'; +import { calculateImpactEstimates } from '../../utils/calculate_impact_estimates'; +import { asCost } from '../../utils/formatters/as_cost'; +import { asWeight } from '../../utils/formatters/as_weight'; +import { CPULabelWithHint } from '../cpu_label_with_hint'; +import { FrameInformationTooltip } from '../frame_information_window/frame_information_tooltip'; +import { StackFrameSummary } from '../stack_frame_summary'; +import { GetLabel } from './get_label'; + +interface Props { + sortDirection: 'asc' | 'desc'; + sortField: TopNFunctionSortField; + onSortChange: (options: { + sortDirection: 'asc' | 'desc'; + sortField: TopNFunctionSortField; + }) => void; + topNFunctions?: TopNFunctions; + comparisonTopNFunctions?: TopNFunctions; + totalSeconds: number; + isDifferentialView: boolean; + baselineScaleFactor?: number; + comparisonScaleFactor?: number; +} + +interface Row { + rank: number; + frame: StackFrameMetadata; + samples: number; + exclusiveCPU: number; + inclusiveCPU: number; + impactEstimates?: ReturnType; + diff?: { + rank: number; + samples: number; + exclusiveCPU: number; + inclusiveCPU: number; + }; +} + +function scaleValue({ value, scaleFactor = 1 }: { value: number; scaleFactor?: number }) { + return value * scaleFactor; +} +function SampleStat({ + samples, + diffSamples, + totalSamples, + isSampled, +}: { + samples: number; + diffSamples?: number; + totalSamples: number; + isSampled: boolean; +}) { + const samplesLabel = `${isSampled ? '~ ' : ''}${samples.toLocaleString()}`; + + if (diffSamples === undefined || diffSamples === 0 || totalSamples === 0) { + return <>{samplesLabel}; + } + + const percentDelta = (diffSamples / (samples - diffSamples)) * 100; + const totalPercentDelta = (diffSamples / totalSamples) * 100; + + return ( + + {samplesLabel} + + + + + + + + ); +} + +function CPUStat({ cpu, diffCPU }: { cpu: number; diffCPU?: number; isSampled?: boolean }) { + const cpuLabel = `${cpu.toFixed(2)}%`; + + if (diffCPU === undefined || diffCPU === 0) { + return <>{cpuLabel}; + } + + return ( + + {cpuLabel} + + + + + ); +} + +export function Grid({ + sortDirection, + sortField, + onSortChange, + topNFunctions, + comparisonTopNFunctions, + totalSeconds, + isDifferentialView, + baselineScaleFactor, + comparisonScaleFactor, +}: Props) { + const theme = useEuiTheme(); + const [selectedRow, setSelectedRow] = useState(); + const isEstimatedA = (topNFunctions?.SamplingRate ?? 1.0) !== 1.0; + const totalCount: number = useMemo(() => { + if (!topNFunctions || !topNFunctions.TotalCount) { + return 0; + } + + return topNFunctions.TotalCount; + }, [topNFunctions]); + + const rows: Row[] = useMemo(() => { + if (!topNFunctions || !topNFunctions.TotalCount || topNFunctions.TotalCount === 0) { + return []; + } + + const comparisonDataById = comparisonTopNFunctions + ? keyBy(comparisonTopNFunctions.TopN, 'Id') + : {}; + + return topNFunctions.TopN.filter((topN) => topN.CountExclusive > 0).map((topN, i) => { + const comparisonRow = comparisonDataById?.[topN.Id]; + + const topNCountExclusiveScaled = scaleValue({ + value: topN.CountExclusive, + scaleFactor: baselineScaleFactor, + }); + + const inclusiveCPU = (topN.CountInclusive / topNFunctions.TotalCount) * 100; + const exclusiveCPU = (topN.CountExclusive / topNFunctions.TotalCount) * 100; + const totalSamples = topN.CountExclusive; + + const impactEstimates = + totalSeconds > 0 + ? calculateImpactEstimates({ + countExclusive: exclusiveCPU, + countInclusive: inclusiveCPU, + totalSamples, + totalSeconds, + }) + : undefined; + + function calculateDiff() { + if (comparisonTopNFunctions && comparisonRow) { + const comparisonCountExclusiveScaled = scaleValue({ + value: comparisonRow.CountExclusive, + scaleFactor: comparisonScaleFactor, + }); + + return { + rank: topN.Rank - comparisonRow.Rank, + samples: topNCountExclusiveScaled - comparisonCountExclusiveScaled, + exclusiveCPU: + exclusiveCPU - + (comparisonRow.CountExclusive / comparisonTopNFunctions.TotalCount) * 100, + inclusiveCPU: + inclusiveCPU - + (comparisonRow.CountInclusive / comparisonTopNFunctions.TotalCount) * 100, + }; + } + } + + return { + rank: topN.Rank, + frame: topN.Frame, + samples: topNCountExclusiveScaled, + exclusiveCPU, + inclusiveCPU, + impactEstimates, + diff: calculateDiff(), + }; + }); + }, [ + topNFunctions, + comparisonTopNFunctions, + totalSeconds, + comparisonScaleFactor, + baselineScaleFactor, + ]); + + const columns: EuiDataGridColumn[] = [ + { + id: 'rank', + initialWidth: 70, + displayAsText: i18n.translate('xpack.profiling.functionsView.rankColumnLabel', { + defaultMessage: 'Rank', + }), + }, + { + id: 'function', + displayAsText: i18n.translate('xpack.profiling.functionsView.functionColumnLabel', { + defaultMessage: 'Function', + }), + }, + { + id: 'samples', + initialWidth: 200, + displayAsText: i18n.translate('xpack.profiling.functionsView.samplesColumnLabel', { + defaultMessage: 'Samples (estd.)', + }), + }, + { + id: 'selfCPU', + initialWidth: 200, + display: ( + + ), + }, + { + id: 'totalCPU', + initialWidth: 200, + display: ( + + ), + }, + ]; + const leadingControlColumns: EuiDataGridControlColumn[] = []; + if (!isDifferentialView) { + columns.push( + { + id: 'annualizedCo2', + initialWidth: 200, + displayAsText: i18n.translate('xpack.profiling.functionsView.annualizedCo2', { + defaultMessage: 'Annualized CO2', + }), + }, + { + id: 'annualizedDollarCost', + initialWidth: 200, + displayAsText: i18n.translate('xpack.profiling.functionsView.annualizedDollarCost', { + defaultMessage: `Annualized dollar cost`, + }), + } + ); + + leadingControlColumns.push({ + id: 'actions', + width: 40, + headerCellRender() { + return ( + + Controls + + ); + }, + rowCellRender: function RowCellRender({ rowIndex }) { + function handleOnClick() { + setSelectedRow(rows[rowIndex]); + } + return ( + + + + ); + }, + }); + } + + if (comparisonTopNFunctions) { + columns.push({ + id: 'diff', + displayAsText: i18n.translate('xpack.profiling.functionsView.diffColumnLabel', { + defaultMessage: 'Diff', + }), + }); + } + const [visibleColumns, setVisibleColumns] = useState(columns.map(({ id }) => id)); + + const [sortingColumns, setSortingColumns] = useState([]); + function onSort(newSortingColumns: EuiDataGridSorting['columns']) { + setSortingColumns(newSortingColumns); + } + + function RenderCellValue({ rowIndex, columnId }: EuiDataGridCellValueElementProps) { + const data = rows[rowIndex]; + if (data) { + if (columnId === 'rank') { + return
{data.rank}
; + } + + if (columnId === 'function') { + return ; + } + + if (columnId === 'samples') { + return ( + + ); + } + + if (columnId === 'selfCPU') { + return ; + } + + if (columnId === 'totalCPU') { + return ; + } + + if (columnId === 'annualizedCo2' && data.impactEstimates?.annualizedCo2) { + return
{asWeight(data.impactEstimates.annualizedCo2)}
; + } + + if (columnId === 'annualizedDollarCost' && data.impactEstimates?.annualizedDollarCost) { + return
{asCost(data.impactEstimates.annualizedDollarCost)}
; + } + + if (columnId === 'diff') { + if (!data.diff) { + return ( + + {i18n.translate('xpack.profiling.functionsView.newLabel', { + defaultMessage: 'New', + })} + + ); + } + + if (data.diff.rank === 0) { + return null; + } + + return ( + 0 ? 'success' : 'danger'} + iconType={data.diff.rank > 0 ? 'sortDown' : 'sortUp'} + iconSide="right" + style={{ minWidth: '100%', textAlign: 'right' }} + > + {data.diff.rank} + + ); + } + } + return null; + } + + return ( + <> + + {selectedRow && ( + { + setSelectedRow(undefined); + }} + frame={{ + addressOrLine: selectedRow.frame.AddressOrLine, + countExclusive: selectedRow.exclusiveCPU, + countInclusive: selectedRow.inclusiveCPU, + exeFileName: selectedRow.frame.ExeFileName, + fileID: selectedRow.frame.FileID, + frameType: selectedRow.frame.FrameType, + functionName: selectedRow.frame.FunctionName, + sourceFileName: selectedRow.frame.SourceFilename, + sourceLine: selectedRow.frame.SourceLine, + }} + totalSeconds={totalSeconds ?? 0} + totalSamples={selectedRow.samples} + samplingRate={topNFunctions?.SamplingRate ?? 1.0} + /> + )} + + ); +} diff --git a/x-pack/plugins/profiling/public/components/topn_functions/mock/top_n_functions.ts b/x-pack/plugins/profiling/public/components/topn_functions/mock/top_n_functions.ts new file mode 100644 index 0000000000000..d9c8530ea2eef --- /dev/null +++ b/x-pack/plugins/profiling/public/components/topn_functions/mock/top_n_functions.ts @@ -0,0 +1,115 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { TopNFunctions } from '../../../../common/functions'; + +export const data = { + TotalCount: 4, + TopN: [ + { + Rank: 1, + Frame: { + FrameID: 'VZbhUAtQEfdUptXfb8HvNgAAAAAAsbAE', + FileID: 'VZbhUAtQEfdUptXfb8HvNg', + FrameType: 4, + Inline: false, + AddressOrLine: 11644932, + FunctionName: '_raw_spin_unlock_irq', + FunctionOffset: 0, + SourceID: '', + SourceLine: 0, + ExeFileName: 'vmlinux', + CommitHash: '', + SourceCodeURL: '', + SourceFilename: '', + SourcePackageHash: '', + SourcePackageURL: '', + SamplingRate: 1, + FunctionSourceLine: 0, + }, + CountExclusive: 1535, + CountInclusive: 1550, + Id: 'full;vmlinux;_raw_spin_unlock_irq;', + }, + { + Rank: 2, + Frame: { + FrameID: 'VZbhUAtQEfdUptXfb8HvNgAAAAAAsRk2', + FileID: 'VZbhUAtQEfdUptXfb8HvNg', + FrameType: 4, + Inline: false, + AddressOrLine: 11606326, + FunctionName: 'syscall_enter_from_user_mode', + FunctionOffset: 0, + SourceID: '', + SourceLine: 0, + ExeFileName: 'vmlinux', + CommitHash: '', + SourceCodeURL: '', + SourceFilename: '', + SourcePackageHash: '', + SourcePackageURL: '', + SamplingRate: 1, + FunctionSourceLine: 0, + }, + CountExclusive: 1320, + CountInclusive: 1610, + Id: 'full;vmlinux;syscall_enter_from_user_mode;', + }, + { + Rank: 3, + Frame: { + FrameID: 'VZbhUAtQEfdUptXfb8HvNgAAAAAAsa_W', + FileID: 'VZbhUAtQEfdUptXfb8HvNg', + FrameType: 4, + Inline: false, + AddressOrLine: 11644886, + FunctionName: '_raw_spin_unlock_irqrestore', + FunctionOffset: 0, + SourceID: '', + SourceLine: 0, + ExeFileName: 'vmlinux', + CommitHash: '', + SourceCodeURL: '', + SourceFilename: '', + SourcePackageHash: '', + SourcePackageURL: '', + SamplingRate: 1, + FunctionSourceLine: 0, + }, + CountExclusive: 1215, + CountInclusive: 1220, + Id: 'full;vmlinux;_raw_spin_unlock_irqrestore;', + }, + { + Rank: 4, + Frame: { + FrameID: 'VZbhUAtQEfdUptXfb8HvNgAAAAAAF_dD', + FileID: 'VZbhUAtQEfdUptXfb8HvNg', + FrameType: 4, + Inline: false, + AddressOrLine: 1570627, + FunctionName: 'audit_filter_syscall', + FunctionOffset: 0, + SourceID: '', + SourceLine: 0, + ExeFileName: 'vmlinux', + CommitHash: '', + SourceCodeURL: '', + SourceFilename: '', + SourcePackageHash: '', + SourcePackageURL: '', + SamplingRate: 1, + FunctionSourceLine: 0, + }, + CountExclusive: 920, + CountInclusive: 1560, + Id: 'full;vmlinux;audit_filter_syscall;', + }, + ], + SamplingRate: 0.2, +} as TopNFunctions; diff --git a/x-pack/plugins/profiling/public/components/topn_functions/topn_functions.stories.tsx b/x-pack/plugins/profiling/public/components/topn_functions/topn_functions.stories.tsx new file mode 100644 index 0000000000000..dd530f049d13c --- /dev/null +++ b/x-pack/plugins/profiling/public/components/topn_functions/topn_functions.stories.tsx @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Meta } from '@storybook/react'; +import React from 'react'; +import { TopNFunctionsView } from '../../views/functions/topn'; +import { MockProfilingDependenciesStorybook } from '../contexts/profiling_dependencies/mock_profiling_dependencies_storybook'; +import { data } from './mock/top_n_functions'; + +const stories: Meta<{}> = { + title: 'Views/TopN functions', + component: TopNFunctionsView, + decorators: [ + (StoryComponent, { globals }) => { + return ( + data, + }} + > + + + ); + }, + ], +}; + +export default stories; + +export function Examples() { + return ; +} diff --git a/x-pack/plugins/profiling/public/views/functions/topn/index.tsx b/x-pack/plugins/profiling/public/views/functions/topn/index.tsx index 768f5256fe3c3..311cab393acfd 100644 --- a/x-pack/plugins/profiling/public/views/functions/topn/index.tsx +++ b/x-pack/plugins/profiling/public/views/functions/topn/index.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { AsyncComponent } from '../../../components/async_component'; import { useProfilingDependencies } from '../../../components/contexts/profiling_dependencies/use_profiling_dependencies'; import { TopNFunctionsTable } from '../../../components/topn_functions'; +import { Grid } from '../../../components/topn_functions/grid'; import { useProfilingParams } from '../../../hooks/use_profiling_params'; import { useProfilingRouter } from '../../../hooks/use_profiling_router'; import { useProfilingRoutePath } from '../../../hooks/use_profiling_route_path'; @@ -57,7 +58,26 @@ export function TopNFunctionsView() { <> - + + + { + profilingRouter.push(routePath, { + path, + query: { + ...query, + sortField: nextSort.sortField, + sortDirection: nextSort.sortDirection, + }, + }); + }} + totalSeconds={timeRange.inSeconds.end - timeRange.inSeconds.start} + isDifferentialView={false} + /> + Date: Wed, 28 Jun 2023 13:59:51 +0100 Subject: [PATCH 02/15] Grid --- .../components/topn_functions/cpu_stat.tsx | 27 ++ .../topn_functions/function_row.tsx | 89 ++++++ .../public/components/topn_functions/grid.tsx | 282 ++++-------------- .../components/topn_functions/index.tsx | 10 +- .../{get_label.tsx => label.tsx} | 2 +- .../components/topn_functions/sample_stat.tsx | 43 +++ .../public/components/topn_functions/utils.ts | 99 ++++++ .../public/views/functions/topn/index.tsx | 12 - 8 files changed, 317 insertions(+), 247 deletions(-) create mode 100644 x-pack/plugins/profiling/public/components/topn_functions/cpu_stat.tsx create mode 100644 x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx rename x-pack/plugins/profiling/public/components/topn_functions/{get_label.tsx => label.tsx} (91%) create mode 100644 x-pack/plugins/profiling/public/components/topn_functions/sample_stat.tsx diff --git a/x-pack/plugins/profiling/public/components/topn_functions/cpu_stat.tsx b/x-pack/plugins/profiling/public/components/topn_functions/cpu_stat.tsx new file mode 100644 index 0000000000000..ef8fcd9ba5d95 --- /dev/null +++ b/x-pack/plugins/profiling/public/components/topn_functions/cpu_stat.tsx @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import React from 'react'; +import { Label } from './label'; + +export function CPUStat({ cpu, diffCPU }: { cpu: number; diffCPU?: number; isSampled?: boolean }) { + const cpuLabel = `${cpu.toFixed(2)}%`; + + if (diffCPU === undefined || diffCPU === 0) { + return <>{cpuLabel}; + } + + return ( + + {cpuLabel} + + + + ); +} diff --git a/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx b/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx new file mode 100644 index 0000000000000..39512f20d76fb --- /dev/null +++ b/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiBadge, EuiText, useEuiTheme } from '@elastic/eui'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { asCost } from '../../utils/formatters/as_cost'; +import { asWeight } from '../../utils/formatters/as_weight'; +import { StackFrameSummary } from '../stack_frame_summary'; +import { CPUStat } from './cpu_stat'; +import { SampleStat } from './sample_stat'; +import { IFunctionRow } from './utils'; + +interface Props { + functionRow: IFunctionRow; + columnId: string; + totalCount: number; + isEstimatedA: boolean; +} + +export function FunctionRow({ functionRow, columnId, totalCount, isEstimatedA }: Props) { + const theme = useEuiTheme(); + if (columnId === 'rank') { + return
{functionRow.rank}
; + } + + if (columnId === 'function') { + return ; + } + + if (columnId === 'samples') { + return ( + + ); + } + + if (columnId === 'selfCPU') { + return ; + } + + if (columnId === 'totalCPU') { + return ; + } + + if (columnId === 'annualizedCo2' && functionRow.impactEstimates?.annualizedCo2) { + return
{asWeight(functionRow.impactEstimates.annualizedCo2)}
; + } + + if (columnId === 'annualizedDollarCost' && functionRow.impactEstimates?.annualizedDollarCost) { + return
{asCost(functionRow.impactEstimates.annualizedDollarCost)}
; + } + + if (columnId === 'diff') { + if (!functionRow.diff) { + return ( + + {i18n.translate('xpack.profiling.functionsView.newLabel', { + defaultMessage: 'New', + })} + + ); + } + + if (functionRow.diff.rank === 0) { + return null; + } + + return ( + 0 ? 'success' : 'danger'} + iconType={functionRow.diff.rank > 0 ? 'sortDown' : 'sortUp'} + iconSide="right" + style={{ minWidth: '100%', textAlign: 'right' }} + > + {functionRow.diff.rank} + + ); + } + return null; +} diff --git a/x-pack/plugins/profiling/public/components/topn_functions/grid.tsx b/x-pack/plugins/profiling/public/components/topn_functions/grid.tsx index 94521156a1726..fce93440419f2 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/grid.tsx +++ b/x-pack/plugins/profiling/public/components/topn_functions/grid.tsx @@ -6,40 +6,24 @@ */ import { - EuiBadge, EuiButtonIcon, EuiDataGrid, EuiDataGridCellValueElementProps, EuiDataGridColumn, EuiDataGridControlColumn, EuiDataGridSorting, - EuiFlexGroup, - EuiFlexItem, EuiScreenReaderOnly, - EuiText, EuiToolTip, - useEuiTheme, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { keyBy } from 'lodash'; import React, { useMemo, useState } from 'react'; -import { TopNFunctions, TopNFunctionSortField } from '../../../common/functions'; -import { StackFrameMetadata } from '../../../common/profiling'; -import { calculateImpactEstimates } from '../../utils/calculate_impact_estimates'; -import { asCost } from '../../utils/formatters/as_cost'; -import { asWeight } from '../../utils/formatters/as_weight'; +import { TopNFunctions } from '../../../common/functions'; import { CPULabelWithHint } from '../cpu_label_with_hint'; import { FrameInformationTooltip } from '../frame_information_window/frame_information_tooltip'; -import { StackFrameSummary } from '../stack_frame_summary'; -import { GetLabel } from './get_label'; +import { FunctionRow } from './function_row'; +import { getFunctionsRows, IFunctionRow } from './utils'; interface Props { - sortDirection: 'asc' | 'desc'; - sortField: TopNFunctionSortField; - onSortChange: (options: { - sortDirection: 'asc' | 'desc'; - sortField: TopNFunctionSortField; - }) => void; topNFunctions?: TopNFunctions; comparisonTopNFunctions?: TopNFunctions; totalSeconds: number; @@ -48,78 +32,7 @@ interface Props { comparisonScaleFactor?: number; } -interface Row { - rank: number; - frame: StackFrameMetadata; - samples: number; - exclusiveCPU: number; - inclusiveCPU: number; - impactEstimates?: ReturnType; - diff?: { - rank: number; - samples: number; - exclusiveCPU: number; - inclusiveCPU: number; - }; -} - -function scaleValue({ value, scaleFactor = 1 }: { value: number; scaleFactor?: number }) { - return value * scaleFactor; -} -function SampleStat({ - samples, - diffSamples, - totalSamples, - isSampled, -}: { - samples: number; - diffSamples?: number; - totalSamples: number; - isSampled: boolean; -}) { - const samplesLabel = `${isSampled ? '~ ' : ''}${samples.toLocaleString()}`; - - if (diffSamples === undefined || diffSamples === 0 || totalSamples === 0) { - return <>{samplesLabel}; - } - - const percentDelta = (diffSamples / (samples - diffSamples)) * 100; - const totalPercentDelta = (diffSamples / totalSamples) * 100; - - return ( - - {samplesLabel} - - - - - - - - ); -} - -function CPUStat({ cpu, diffCPU }: { cpu: number; diffCPU?: number; isSampled?: boolean }) { - const cpuLabel = `${cpu.toFixed(2)}%`; - - if (diffCPU === undefined || diffCPU === 0) { - return <>{cpuLabel}; - } - - return ( - - {cpuLabel} - - - - - ); -} - export function Grid({ - sortDirection, - sortField, - onSortChange, topNFunctions, comparisonTopNFunctions, totalSeconds, @@ -127,10 +40,24 @@ export function Grid({ baselineScaleFactor, comparisonScaleFactor, }: Props) { - const theme = useEuiTheme(); - const [selectedRow, setSelectedRow] = useState(); + const [selectedRow, setSelectedRow] = useState(); + const [sortingColumns, setSortingColumns] = useState([ + { id: 'rank', direction: 'asc' }, + ]); + function onSort(newSortingColumns: EuiDataGridSorting['columns']) { + setSortingColumns(newSortingColumns); + } + + const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 100 }); + function onChangeItemsPerPage(pageSize: number) { + setPagination((state) => ({ ...state, pageSize, pageIndex: 0 })); + } + function onChangePage(pageIndex: number) { + setPagination((state) => ({ ...state, pageIndex })); + } + const isEstimatedA = (topNFunctions?.SamplingRate ?? 1.0) !== 1.0; - const totalCount: number = useMemo(() => { + const totalCount = useMemo(() => { if (!topNFunctions || !topNFunctions.TotalCount) { return 0; } @@ -138,66 +65,13 @@ export function Grid({ return topNFunctions.TotalCount; }, [topNFunctions]); - const rows: Row[] = useMemo(() => { - if (!topNFunctions || !topNFunctions.TotalCount || topNFunctions.TotalCount === 0) { - return []; - } - - const comparisonDataById = comparisonTopNFunctions - ? keyBy(comparisonTopNFunctions.TopN, 'Id') - : {}; - - return topNFunctions.TopN.filter((topN) => topN.CountExclusive > 0).map((topN, i) => { - const comparisonRow = comparisonDataById?.[topN.Id]; - - const topNCountExclusiveScaled = scaleValue({ - value: topN.CountExclusive, - scaleFactor: baselineScaleFactor, - }); - - const inclusiveCPU = (topN.CountInclusive / topNFunctions.TotalCount) * 100; - const exclusiveCPU = (topN.CountExclusive / topNFunctions.TotalCount) * 100; - const totalSamples = topN.CountExclusive; - - const impactEstimates = - totalSeconds > 0 - ? calculateImpactEstimates({ - countExclusive: exclusiveCPU, - countInclusive: inclusiveCPU, - totalSamples, - totalSeconds, - }) - : undefined; - - function calculateDiff() { - if (comparisonTopNFunctions && comparisonRow) { - const comparisonCountExclusiveScaled = scaleValue({ - value: comparisonRow.CountExclusive, - scaleFactor: comparisonScaleFactor, - }); - - return { - rank: topN.Rank - comparisonRow.Rank, - samples: topNCountExclusiveScaled - comparisonCountExclusiveScaled, - exclusiveCPU: - exclusiveCPU - - (comparisonRow.CountExclusive / comparisonTopNFunctions.TotalCount) * 100, - inclusiveCPU: - inclusiveCPU - - (comparisonRow.CountInclusive / comparisonTopNFunctions.TotalCount) * 100, - }; - } - } - - return { - rank: topN.Rank, - frame: topN.Frame, - samples: topNCountExclusiveScaled, - exclusiveCPU, - inclusiveCPU, - impactEstimates, - diff: calculateDiff(), - }; + const rows = useMemo(() => { + return getFunctionsRows({ + baselineScaleFactor, + comparisonScaleFactor, + comparisonTopNFunctions, + topNFunctions, + totalSeconds, }); }, [ topNFunctions, @@ -210,7 +84,7 @@ export function Grid({ const columns: EuiDataGridColumn[] = [ { id: 'rank', - initialWidth: 70, + initialWidth: 90, displayAsText: i18n.translate('xpack.profiling.functionsView.rankColumnLabel', { defaultMessage: 'Rank', }), @@ -248,8 +122,16 @@ export function Grid({ ), }, ]; + const leadingControlColumns: EuiDataGridControlColumn[] = []; - if (!isDifferentialView) { + if (isDifferentialView) { + columns.push({ + id: 'diff', + displayAsText: i18n.translate('xpack.profiling.functionsView.diffColumnLabel', { + defaultMessage: 'Diff', + }), + }); + } else { columns.push( { id: 'annualizedCo2', @@ -299,85 +181,19 @@ export function Grid({ }); } - if (comparisonTopNFunctions) { - columns.push({ - id: 'diff', - displayAsText: i18n.translate('xpack.profiling.functionsView.diffColumnLabel', { - defaultMessage: 'Diff', - }), - }); - } const [visibleColumns, setVisibleColumns] = useState(columns.map(({ id }) => id)); - const [sortingColumns, setSortingColumns] = useState([]); - function onSort(newSortingColumns: EuiDataGridSorting['columns']) { - setSortingColumns(newSortingColumns); - } - function RenderCellValue({ rowIndex, columnId }: EuiDataGridCellValueElementProps) { const data = rows[rowIndex]; if (data) { - if (columnId === 'rank') { - return
{data.rank}
; - } - - if (columnId === 'function') { - return ; - } - - if (columnId === 'samples') { - return ( - - ); - } - - if (columnId === 'selfCPU') { - return ; - } - - if (columnId === 'totalCPU') { - return ; - } - - if (columnId === 'annualizedCo2' && data.impactEstimates?.annualizedCo2) { - return
{asWeight(data.impactEstimates.annualizedCo2)}
; - } - - if (columnId === 'annualizedDollarCost' && data.impactEstimates?.annualizedDollarCost) { - return
{asCost(data.impactEstimates.annualizedDollarCost)}
; - } - - if (columnId === 'diff') { - if (!data.diff) { - return ( - - {i18n.translate('xpack.profiling.functionsView.newLabel', { - defaultMessage: 'New', - })} - - ); - } - - if (data.diff.rank === 0) { - return null; - } - - return ( - 0 ? 'success' : 'danger'} - iconType={data.diff.rank > 0 ? 'sortDown' : 'sortUp'} - iconSide="right" - style={{ minWidth: '100%', textAlign: 'right' }} - > - {data.diff.rank} - - ); - } + return ( + + ); } return null; } @@ -390,8 +206,16 @@ export function Grid({ columnVisibility={{ visibleColumns, setVisibleColumns }} rowCount={totalCount} renderCellValue={RenderCellValue} + inMemory={{ level: 'sorting' }} sorting={{ columns: sortingColumns, onSort }} leadingControlColumns={leadingControlColumns} + pagination={{ + ...pagination, + onChangeItemsPerPage, + onChangePage, + }} + rowHeightsOptions={{ defaultHeight: 'auto' }} + toolbarVisibility={{ showColumnSelector: false }} /> {selectedRow && ( {value} - +
From bf219db81e9f3fc0cfa92b36774bea288e31edee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Hironimuz=20Marcondes?= Date: Tue, 4 Jul 2023 11:55:58 -0300 Subject: [PATCH 07/15] changing page size --- .../profiling/public/components/topn_functions/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/profiling/public/components/topn_functions/index.tsx b/x-pack/plugins/profiling/public/components/topn_functions/index.tsx index e3e58e5522163..857bfb923d6c6 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/index.tsx +++ b/x-pack/plugins/profiling/public/components/topn_functions/index.tsx @@ -240,7 +240,7 @@ export const TopNFunctionsGrid = forwardRef( aria-label="TopN functions" columns={columns} columnVisibility={{ visibleColumns, setVisibleColumns }} - rowCount={1000} + rowCount={500} renderCellValue={RenderCellValue} inMemory={{ level: 'sorting' }} sorting={{ columns: [{ id: sortField, direction: sortDirection }], onSort }} From 20293b3f0ea8af97c16c70475bbae5ea02dacee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Hironimuz=20Marcondes?= Date: Tue, 4 Jul 2023 12:03:32 -0300 Subject: [PATCH 08/15] change page size --- .../profiling/public/components/topn_functions/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/profiling/public/components/topn_functions/index.tsx b/x-pack/plugins/profiling/public/components/topn_functions/index.tsx index 857bfb923d6c6..6d2fe69575abc 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/index.tsx +++ b/x-pack/plugins/profiling/public/components/topn_functions/index.tsx @@ -240,7 +240,7 @@ export const TopNFunctionsGrid = forwardRef( aria-label="TopN functions" columns={columns} columnVisibility={{ visibleColumns, setVisibleColumns }} - rowCount={500} + rowCount={100} renderCellValue={RenderCellValue} inMemory={{ level: 'sorting' }} sorting={{ columns: [{ id: sortField, direction: sortDirection }], onSort }} From 76cc33ad1e02b7280f8e82afa31ab4172383cd99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Hironimuz=20Marcondes?= Date: Tue, 4 Jul 2023 12:04:25 -0300 Subject: [PATCH 09/15] changing size --- .../profiling/public/components/topn_functions/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/profiling/public/components/topn_functions/index.tsx b/x-pack/plugins/profiling/public/components/topn_functions/index.tsx index 6d2fe69575abc..857bfb923d6c6 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/index.tsx +++ b/x-pack/plugins/profiling/public/components/topn_functions/index.tsx @@ -240,7 +240,7 @@ export const TopNFunctionsGrid = forwardRef( aria-label="TopN functions" columns={columns} columnVisibility={{ visibleColumns, setVisibleColumns }} - rowCount={100} + rowCount={500} renderCellValue={RenderCellValue} inMemory={{ level: 'sorting' }} sorting={{ columns: [{ id: sortField, direction: sortDirection }], onSort }} From 6bdbe827fe2e30455260a5812ebd0d0bfeaa0585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Hironimuz=20Marcondes?= Date: Tue, 4 Jul 2023 12:08:13 -0300 Subject: [PATCH 10/15] refactoring --- .../public/components/topn_functions/function_row.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx b/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx index a2fc4db39b2d6..cb9bccb5bd5a0 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx +++ b/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx @@ -45,10 +45,6 @@ export function FunctionRow({ const successColor = useEuiBackgroundColor('success'); const dangerColor = useEuiBackgroundColor('danger'); - function getColor(value: number) { - return value > 0 ? 'success' : 'danger'; - } - if (columnId === TopNFunctionSortField.Diff) { if (!functionRow.diff) { return ( @@ -64,7 +60,7 @@ export function FunctionRow({ return null; } - const color = getColor(functionRow.diff.rank); + const color = functionRow.diff.rank > 0 ? 'success' : 'danger'; setCellProps({ style: { backgroundColor: color === 'success' ? successColor : dangerColor } }); return ( From 03bffce5d8a4664d8a8125aa34215539403e52fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Hironimuz=20Marcondes?= Date: Tue, 4 Jul 2023 13:05:31 -0300 Subject: [PATCH 11/15] i18n --- x-pack/plugins/translations/translations/fr-FR.json | 1 - x-pack/plugins/translations/translations/ja-JP.json | 1 - x-pack/plugins/translations/translations/zh-CN.json | 1 - 3 files changed, 3 deletions(-) diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 1f9d308c783fb..0f4040b9ee30b 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -27296,7 +27296,6 @@ "xpack.profiling.functionsView.newLabel": "Nouveauté", "xpack.profiling.functionsView.rankColumnLabel": "Rang", "xpack.profiling.functionsView.samplesColumnLabel": "Échantillons (établ.)", - "xpack.profiling.functionsView.showMoreButton": "Afficher des informations supplémentaires", "xpack.profiling.functionsView.totalSampleCountLabel": " Total estimation d'échantillons : ", "xpack.profiling.header.betaBadgeTooltip": "Ce module n'est pas disponible. Nous vous remercions de bien vouloir nous aider en nous signalant tout bug.", "xpack.profiling.header.giveFeedbackLink": "Donner un retour", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 602616c9ffacc..7410dba80e9bd 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -27282,7 +27282,6 @@ "xpack.profiling.functionsView.newLabel": "新規", "xpack.profiling.functionsView.rankColumnLabel": "ランク", "xpack.profiling.functionsView.samplesColumnLabel": "サンプル(推定)", - "xpack.profiling.functionsView.showMoreButton": "詳細を表示", "xpack.profiling.functionsView.totalSampleCountLabel": " 合計サンプル推定:", "xpack.profiling.header.betaBadgeTooltip": "このモジュールはGAではありません。不具合が発生したら報告してください。", "xpack.profiling.header.giveFeedbackLink": "フィードバックを作成する", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 9c38c99996e8f..d727dd64958a5 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -27280,7 +27280,6 @@ "xpack.profiling.functionsView.newLabel": "新建", "xpack.profiling.functionsView.rankColumnLabel": "排名", "xpack.profiling.functionsView.samplesColumnLabel": "样例(估计)", - "xpack.profiling.functionsView.showMoreButton": "显示更多信息", "xpack.profiling.functionsView.totalSampleCountLabel": " 总样例数估值:", "xpack.profiling.header.betaBadgeTooltip": "此模块不是 GA 版。请通过报告错误来帮助我们。", "xpack.profiling.header.giveFeedbackLink": "反馈", From f195633a5242e41f821293fcff5bb0f0a03a83a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Hironimuz=20Marcondes?= Date: Wed, 5 Jul 2023 09:58:49 -0300 Subject: [PATCH 12/15] removing ~ --- .../public/components/topn_functions/function_row.tsx | 3 --- .../profiling/public/components/topn_functions/index.tsx | 2 -- .../public/components/topn_functions/sample_stat.tsx | 4 +--- .../components/topn_functions/topn_functions.stories.tsx | 2 +- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx b/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx index cb9bccb5bd5a0..65940f18e3437 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx +++ b/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx @@ -28,7 +28,6 @@ interface Props { functionRow: IFunctionRow; columnId: string; totalCount: number; - isEstimatedA: boolean; onFrameClick?: (functionName: string) => void; setCellProps: EuiDataGridCellValueElementProps['setCellProps']; } @@ -37,7 +36,6 @@ export function FunctionRow({ functionRow, columnId, totalCount, - isEstimatedA, onFrameClick, setCellProps, }: Props) { @@ -89,7 +87,6 @@ export function FunctionRow({ samples={functionRow.samples} diffSamples={functionRow.diff?.samples} totalSamples={totalCount} - isSampled={isEstimatedA} /> ); } diff --git a/x-pack/plugins/profiling/public/components/topn_functions/index.tsx b/x-pack/plugins/profiling/public/components/topn_functions/index.tsx index 857bfb923d6c6..32c83ae0fc9ea 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/index.tsx +++ b/x-pack/plugins/profiling/public/components/topn_functions/index.tsx @@ -73,7 +73,6 @@ export const TopNFunctionsGrid = forwardRef( } } - const isEstimatedA = (topNFunctions?.SamplingRate ?? 1.0) !== 1.0; const totalCount = useMemo(() => { if (!topNFunctions || !topNFunctions.TotalCount) { return 0; @@ -216,7 +215,6 @@ export const TopNFunctionsGrid = forwardRef( {samplesLabel}; diff --git a/x-pack/plugins/profiling/public/components/topn_functions/topn_functions.stories.tsx b/x-pack/plugins/profiling/public/components/topn_functions/topn_functions.stories.tsx index dd530f049d13c..2ece778600a63 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/topn_functions.stories.tsx +++ b/x-pack/plugins/profiling/public/components/topn_functions/topn_functions.stories.tsx @@ -18,7 +18,7 @@ const stories: Meta<{}> = { (StoryComponent, { globals }) => { return ( data, }} From 6f25d4fa9a8d35d23afcbffe4356dfbbe96eb668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Hironimuz=20Marcondes?= Date: Thu, 13 Jul 2023 13:47:30 -0300 Subject: [PATCH 13/15] fixing calc impact estimates --- .../topn_functions/function_row.tsx | 4 +-- .../components/topn_functions/index.tsx | 8 ++--- .../public/components/topn_functions/utils.ts | 34 ++++++++++++------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx b/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx index 65940f18e3437..f374fa501725d 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx +++ b/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx @@ -92,11 +92,11 @@ export function FunctionRow({ } if (columnId === TopNFunctionSortField.SelfCPU) { - return ; + return ; } if (columnId === TopNFunctionSortField.TotalCPU) { - return ; + return ; } if ( diff --git a/x-pack/plugins/profiling/public/components/topn_functions/index.tsx b/x-pack/plugins/profiling/public/components/topn_functions/index.tsx index 32c83ae0fc9ea..e26422cd2a499 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/index.tsx +++ b/x-pack/plugins/profiling/public/components/topn_functions/index.tsx @@ -238,14 +238,14 @@ export const TopNFunctionsGrid = forwardRef( aria-label="TopN functions" columns={columns} columnVisibility={{ visibleColumns, setVisibleColumns }} - rowCount={500} + rowCount={100} renderCellValue={RenderCellValue} inMemory={{ level: 'sorting' }} sorting={{ columns: [{ id: sortField, direction: sortDirection }], onSort }} leadingControlColumns={leadingControlColumns} pagination={{ pageIndex, - pageSize: 100, + pageSize: 50, // Left it empty on purpose as it is a required property on the pagination onChangeItemsPerPage: () => {}, onChangePage, @@ -278,8 +278,8 @@ export const TopNFunctionsGrid = forwardRef( sourceFileName: selectedRow.frame.SourceFilename, sourceLine: selectedRow.frame.SourceLine, }} - totalSeconds={totalSeconds ?? 0} - totalSamples={selectedRow.samples} + totalSeconds={totalSeconds} + totalSamples={totalCount} samplingRate={topNFunctions?.SamplingRate ?? 1.0} /> )} diff --git a/x-pack/plugins/profiling/public/components/topn_functions/utils.ts b/x-pack/plugins/profiling/public/components/topn_functions/utils.ts index f30d36a423fc4..84639d100e38e 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/utils.ts +++ b/x-pack/plugins/profiling/public/components/topn_functions/utils.ts @@ -28,12 +28,16 @@ export interface IFunctionRow { samples: number; selfCPU: number; totalCPU: number; + selfCPUPerc: number; + totalCPUPerc: number; impactEstimates?: ReturnType; diff?: { rank: number; samples: number; selfCPU: number; totalCPU: number; + selfCPUPerc: number; + totalCPUPerc: number; }; } @@ -61,20 +65,21 @@ export function getFunctionsRows({ return topNFunctions.TopN.filter((topN) => topN.CountExclusive > 0).map((topN, i) => { const comparisonRow = comparisonDataById?.[topN.Id]; + const totalSamples = topN.CountExclusive; + const topNCountExclusiveScaled = scaleValue({ - value: topN.CountExclusive, + value: totalSamples, scaleFactor: baselineScaleFactor, }); - const totalCPU = (topN.CountInclusive / topNFunctions.TotalCount) * 100; - const selfCPU = (topN.CountExclusive / topNFunctions.TotalCount) * 100; - const totalSamples = topN.CountExclusive; + const totalCPUPerc = (topN.CountInclusive / topNFunctions.TotalCount) * 100; + const selfCPUPerc = (topN.CountExclusive / topNFunctions.TotalCount) * 100; const impactEstimates = totalSeconds > 0 ? calculateImpactEstimates({ - countExclusive: selfCPU, - countInclusive: totalCPU, + countExclusive: topN.CountExclusive, + countInclusive: topN.CountInclusive, totalSamples, totalSeconds, }) @@ -90,10 +95,13 @@ export function getFunctionsRows({ return { rank: topN.Rank - comparisonRow.Rank, samples: topNCountExclusiveScaled - comparisonCountExclusiveScaled, - selfCPU: - selfCPU - (comparisonRow.CountExclusive / comparisonTopNFunctions.TotalCount) * 100, - totalCPU: - totalCPU - (comparisonRow.CountInclusive / comparisonTopNFunctions.TotalCount) * 100, + selfCPU: comparisonRow.CountExclusive, + selfCPUPerc: + selfCPUPerc - (comparisonRow.CountExclusive / comparisonTopNFunctions.TotalCount) * 100, + totalCPU: comparisonRow.CountInclusive, + totalCPUPerc: + totalCPUPerc - + (comparisonRow.CountInclusive / comparisonTopNFunctions.TotalCount) * 100, }; } } @@ -102,8 +110,10 @@ export function getFunctionsRows({ rank: topN.Rank, frame: topN.Frame, samples: topNCountExclusiveScaled, - selfCPU, - totalCPU, + selfCPU: topN.CountExclusive, + selfCPUPerc, + totalCPU: topN.CountInclusive, + totalCPUPerc, impactEstimates, diff: calculateDiff(), }; From f58bf1f8a0c64de6b0909a879f1a5263e87a5e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Hironimuz=20Marcondes?= Date: Thu, 13 Jul 2023 15:24:47 -0300 Subject: [PATCH 14/15] fixing grid --- .../components/label_with_hint/index.tsx | 41 ++++++++++ .../topn_functions/function_row.tsx | 1 + .../components/topn_functions/index.tsx | 75 ++++++++++++++++--- .../public/utils/formatters/as_weight.ts | 9 +-- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 7 files changed, 109 insertions(+), 20 deletions(-) create mode 100644 x-pack/plugins/profiling/public/components/label_with_hint/index.tsx diff --git a/x-pack/plugins/profiling/public/components/label_with_hint/index.tsx b/x-pack/plugins/profiling/public/components/label_with_hint/index.tsx new file mode 100644 index 0000000000000..1c3dd7d2c5be3 --- /dev/null +++ b/x-pack/plugins/profiling/public/components/label_with_hint/index.tsx @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiIconProps, + EuiText, + EuiTextProps, + EuiToolTip, +} from '@elastic/eui'; + +interface Props { + label: string; + hint: string; + labelSize?: EuiTextProps['size']; + labelStyle?: EuiTextProps['style']; + iconSize?: EuiIconProps['size']; +} + +export function LabelWithHint({ label, hint, iconSize, labelSize, labelStyle }: Props) { + return ( + + + + {label} + + + + + + + + + ); +} diff --git a/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx b/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx index f374fa501725d..53f4a3701125e 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx +++ b/x-pack/plugins/profiling/public/components/topn_functions/function_row.tsx @@ -82,6 +82,7 @@ export function FunctionRow({ } if (columnId === TopNFunctionSortField.Samples) { + setCellProps({ css: { textAlign: 'right' } }); return ( + ), }, { id: TopNFunctionSortField.SelfCPU, @@ -161,16 +173,38 @@ export const TopNFunctionsGrid = forwardRef( { id: TopNFunctionSortField.AnnualizedCo2, initialWidth: isDifferentialView ? 100 : 200, - displayAsText: i18n.translate('xpack.profiling.functionsView.annualizedCo2', { - defaultMessage: 'Annualized CO2', - }), + schema: 'numeric', + display: ( + + ), }, { id: TopNFunctionSortField.AnnualizedDollarCost, initialWidth: isDifferentialView ? 100 : 200, - displayAsText: i18n.translate('xpack.profiling.functionsView.annualizedDollarCost', { - defaultMessage: `Annualized dollar cost`, - }), + display: ( + + ), } ); @@ -261,6 +295,29 @@ export const TopNFunctionsGrid = forwardRef( virtualizationOptions={{ onScroll, }} + schemaDetectors={[ + { + type: 'samples', + comparator: (a, b, direction) => { + const aNumber = parseFloat(a.replace(/,/g, '')); + const bNumber = parseFloat(b.replace(/,/g, '')); + + if (aNumber < bNumber) { + return direction === 'desc' ? 1 : -1; + } + if (aNumber > bNumber) { + return direction === 'desc' ? -1 : 1; + } + return 0; + }, + detector: (a) => { + return 1; + }, + icon: '', + sortTextAsc: 'Low-High', + sortTextDesc: 'High-Low', + }, + ]} /> {selectedRow && ( Date: Fri, 14 Jul 2023 09:35:24 -0300 Subject: [PATCH 15/15] fixing grid rezise problem --- .../public/components/profiling_app_page_template/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/profiling/public/components/profiling_app_page_template/index.tsx b/x-pack/plugins/profiling/public/components/profiling_app_page_template/index.tsx index 2a353f3b4db61..2193cb6b0e334 100644 --- a/x-pack/plugins/profiling/public/components/profiling_app_page_template/index.tsx +++ b/x-pack/plugins/profiling/public/components/profiling_app_page_template/index.tsx @@ -94,7 +94,7 @@ export function ProfilingAppPageTemplate({ }, }} > - + {!hideSearchBar && (