Skip to content

Commit

Permalink
[Profiling] Displaying inline frames (elastic#169212)
Browse files Browse the repository at this point in the history
  • Loading branch information
cauemarcondes authored Oct 19, 2023
1 parent 1c4573d commit 0366351
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 42 deletions.
9 changes: 5 additions & 4 deletions packages/kbn-profiling-utils/common/profiling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,14 +241,15 @@ function getExeFileName(metadata: StackFrameMetadata) {
* @returns string
*/
export function getCalleeLabel(metadata: StackFrameMetadata) {
const inlineLabel = metadata.Inline ? '-> ' : '';
if (metadata.FunctionName !== '') {
const sourceFilename = metadata.SourceFilename;
const sourceURL = sourceFilename ? sourceFilename.split('/').pop() : '';
return `${getExeFileName(metadata)}: ${getFunctionName(metadata)} in ${sourceURL}#${
metadata.SourceLine
}`;
return `${inlineLabel}${getExeFileName(metadata)}: ${getFunctionName(
metadata
)} in ${sourceURL}#${metadata.SourceLine}`;
}
return getExeFileName(metadata);
return `${inlineLabel}${getExeFileName(metadata)}`;
}
/**
* Get callee function name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,26 @@
import { TooltipContainer } from '@elastic/charts';
import {
EuiButtonEmpty,
EuiCallOut,
EuiFlexGroup,
EuiFlexItem,
EuiHorizontalRule,
EuiIcon,
EuiPanel,
EuiText,
EuiTitle,
useEuiTheme,
} from '@elastic/eui';
import { css } from '@emotion/react';
import { i18n } from '@kbn/i18n';
import { isNumber } from 'lodash';
import React from 'react';
import { useCalculateImpactEstimate } from '../../hooks/use_calculate_impact_estimates';
import { asCost } from '../../utils/formatters/as_cost';
import { asPercentage } from '../../utils/formatters/as_percentage';
import { asWeight } from '../../utils/formatters/as_weight';
import { CPULabelWithHint } from '../cpu_label_with_hint';
import { TooltipRow } from './tooltip_row';
import { useCalculateImpactEstimate } from '../../hooks/use_calculate_impact_estimates';

interface Props {
isRoot: boolean;
Expand All @@ -39,6 +42,8 @@ interface Props {
comparisonTotalSamples?: number;
comparisonTotalSeconds?: number;
onShowMoreClick?: () => void;
inline: boolean;
parentLabel?: string;
}

export function FlameGraphTooltip({
Expand All @@ -55,6 +60,8 @@ export function FlameGraphTooltip({
comparisonTotalSamples,
comparisonTotalSeconds,
onShowMoreClick,
inline,
parentLabel,
}: Props) {
const theme = useEuiTheme();
const calculateImpactEstimates = useCalculateImpactEstimate();
Expand Down Expand Up @@ -83,8 +90,33 @@ export function FlameGraphTooltip({
<TooltipContainer>
<EuiPanel paddingSize="s">
<EuiFlexGroup direction="column" gutterSize="xs">
<EuiFlexItem>{label}</EuiFlexItem>
<EuiFlexItem>
<EuiTitle size="xxxs">
<EuiText>{label}</EuiText>
</EuiTitle>
</EuiFlexItem>

<EuiHorizontalRule margin="none" style={{ background: theme.euiTheme.border.color }} />
{inline && (
<EuiCallOut
css={css`
p {
display: flex;
}
`}
color="primary"
title={
<EuiText size="xs">
{i18n.translate('xpack.profiling.flameGraphTooltip.inlineCallout', {
defaultMessage: 'This function has been inlined by {parentLabel}',
values: { parentLabel },
})}
</EuiText>
}
size="s"
iconType="iInCircle"
/>
)}
{isRoot === false && (
<>
<TooltipRow
Expand Down
11 changes: 10 additions & 1 deletion x-pack/plugins/profiling/public/components/flamegraph/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,16 @@ export function FlameGraph({
const countExclusive = primaryFlamegraph.CountExclusive[valueIndex];
const totalSeconds = primaryFlamegraph.TotalSeconds;
const nodeID = primaryFlamegraph.ID[valueIndex];

const inline = primaryFlamegraph.Inline[valueIndex];
const comparisonNode = columnarData.comparisonNodesById[nodeID];

const parentLabel = inline
? // If it's an inline frame, look up for its parent frame
primaryFlamegraph.Label[
primaryFlamegraph.Edges.findIndex((edge) => edge.includes(valueIndex))
]
: undefined;

return (
<FlameGraphTooltip
isRoot={valueIndex === 0}
Expand All @@ -164,6 +171,8 @@ export function FlameGraph({
toggleShowInformationWindow();
setHighlightedVmIndex(valueIndex);
}}
inline={inline}
parentLabel={parentLabel}
/>
);
}}
Expand Down
107 changes: 87 additions & 20 deletions x-pack/plugins/profiling/public/components/subchart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
Tooltip,
} from '@elastic/charts';
import {
EuiAccordion,
EuiBadge,
EuiButton,
EuiFlexGroup,
Expand All @@ -28,20 +29,23 @@ import {
EuiLink,
EuiSpacer,
EuiText,
EuiToolTip,
useEuiTheme,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import type { StackFrameMetadata } from '@kbn/profiling-utils';
import { groupBy } from 'lodash';
import React, { Fragment } from 'react';
import { css } from '@emotion/react';
import { CountPerTime, OTHER_BUCKET_LABEL, TopNSample } from '../../common/topn';
import { useKibanaTimeZoneSetting } from '../hooks/use_kibana_timezone_setting';
import { useProfilingChartsTheme } from '../hooks/use_profiling_charts_theme';
import { useProfilingParams } from '../hooks/use_profiling_params';
import { useProfilingRouter } from '../hooks/use_profiling_router';
import { asNumber } from '../utils/formatters/as_number';
import { asPercentage } from '../utils/formatters/as_percentage';
import { StackFrameSummary } from './stack_frame_summary';
import { getTracesViewRouteParams } from '../views/stack_traces_view/utils';
import { StackFrameSummary } from './stack_frame_summary';

export interface SubChartProps {
index: number;
Expand All @@ -63,6 +67,19 @@ export interface SubChartProps {

const NUM_DISPLAYED_FRAMES = 5;

function renderFrameItem(frame: StackFrameMetadata, parentIndex: number | string) {
return (
<EuiFlexItem grow={false} key={frame.FrameID}>
<EuiFlexGroup direction="row" alignItems="center">
<EuiFlexItem grow={false}>{parentIndex}</EuiFlexItem>
<EuiFlexItem grow>
<StackFrameSummary frame={frame} />
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
);
}

export function SubChart({
index,
color,
Expand Down Expand Up @@ -97,9 +114,14 @@ export function SubChart({

const compact = !!onShowMoreClick;

const groupedMetadata = groupBy(metadata, 'AddressOrLine');
const parentsMetadata = Object.values(groupedMetadata)
.map((items) => items.shift())
.filter((_) => _) as StackFrameMetadata[];

const displayedFrames = compact
? metadata.concat().reverse().slice(0, NUM_DISPLAYED_FRAMES)
: metadata.concat().reverse();
? parentsMetadata.concat().reverse().slice(0, NUM_DISPLAYED_FRAMES)
: parentsMetadata.concat().reverse();

const hasMoreFrames = displayedFrames.length < metadata.length;

Expand All @@ -115,23 +137,68 @@ export function SubChart({
}}
>
<EuiFlexGroup direction="column" gutterSize="none">
{displayedFrames.map((frame, frameIndex) => (
<>
<EuiFlexItem grow={false} key={frame.FrameID}>
<EuiFlexGroup direction="row" alignItems="center">
<EuiFlexItem grow={false}>{metadata.indexOf(frame) + 1}</EuiFlexItem>
<EuiFlexItem grow>
<StackFrameSummary frame={frame} />
{displayedFrames.map((frame, frameIndex) => {
const parentIndex = parentsMetadata.indexOf(frame) + 1;
const children = groupedMetadata[frame.AddressOrLine].concat().reverse();

return (
<>
{children.length > 0 ? (
<EuiAccordion
css={css`
display: flex;
flex-direction: column-reverse;
.css-bknxw4-euiButtonIcon-xs-empty-text-euiAccordion__arrow-left-isOpen {
transform: rotate(-90deg) !important;
}
`}
id={`accordion_${frame.AddressOrLine}`}
buttonContent={renderFrameItem(frame, parentIndex)}
paddingSize="s"
extraAction={
<EuiToolTip
content={i18n.translate(
'xpack.profiling.traces.subChart.inlineDescription',
{
defaultMessage:
'This frame has {numberOfChildren} inline {numberOfChildren, plural, one {frame} other {frames}} inside, this allows for optimised processes.',
values: { numberOfChildren: children.length },
}
)}
>
<EuiBadge color="primary">{`-> ${children.length}`}</EuiBadge>
</EuiToolTip>
}
>
<EuiFlexGroup
direction="column"
gutterSize="s"
style={{ marginLeft: '12px' }}
>
{children.map((child, childIndex) => {
return (
<Fragment key={child.FrameID}>
{renderFrameItem(
child,
`${parentIndex}.${children.length - childIndex} ->`
)}
</Fragment>
);
})}
</EuiFlexGroup>
</EuiAccordion>
) : (
renderFrameItem(frame, parentIndex)
)}
{frameIndex < displayedFrames.length - 1 || hasMoreFrames ? (
<EuiFlexItem grow={false}>
<EuiHorizontalRule size="full" margin="s" />
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
{frameIndex < displayedFrames.length - 1 || hasMoreFrames ? (
<EuiFlexItem grow={false}>
<EuiHorizontalRule size="full" margin="s" />
</EuiFlexItem>
) : null}
</>
))}
) : null}
</>
);
})}
</EuiFlexGroup>

{hasMoreFrames && !!onShowMoreClick && (
Expand Down
30 changes: 15 additions & 15 deletions x-pack/plugins/profiling/public/utils/get_flamegraph_model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,7 @@ export function getFlamegraphModel({

let legendItems: Array<{ label: string; color: string }>;

if (!comparisonFlamegraph) {
const usedFrameTypes = new Set([...primaryFlamegraph.FrameType]);
legendItems = compact(
Object.entries(FRAME_TYPE_COLOR_MAP).map(([frameTypeKey, colors]) => {
const frameType = Number(frameTypeKey) as FrameType;

return usedFrameTypes.has(frameType)
? {
color: `#${colors[0].toString(16)}`,
label: describeFrameType(frameType),
}
: undefined;
})
);
} else {
if (comparisonFlamegraph) {
const positiveChangeInterpolator = d3.interpolateRgb(colorNeutral, colorSuccess);

const negativeChangeInterpolator = d3.interpolateRgb(colorNeutral, colorDanger);
Expand Down Expand Up @@ -162,6 +148,20 @@ export function getFlamegraphModel({
const rgba = rgbToRGBA(Number(nodeColor.replace('#', '0x')));
viewModel.color.set(rgba, 4 * index);
});
} else {
const usedFrameTypes = new Set([...primaryFlamegraph.FrameType]);
legendItems = compact(
Object.entries(FRAME_TYPE_COLOR_MAP).map(([frameTypeKey, colors]) => {
const frameType = Number(frameTypeKey) as FrameType;

return usedFrameTypes.has(frameType)
? {
color: `#${colors[0].toString(16)}`,
label: describeFrameType(frameType),
}
: undefined;
})
);
}

return {
Expand Down

0 comments on commit 0366351

Please sign in to comment.