[Profiling] Improve the differential flamegraph tooltip (#144895)

Improve the root tooltip for the differential flamegraph:
- remove the superfluous CPU usages (it's always 100% inclusive and 0%
exclusive)
 - add the change rate of the samples as colored text

**Before**

![Screenshot_20221109_130516](https://user-images.githubusercontent.com/2087964/200828112-045196e2-88cb-4f5c-906a-4e61d73be9c7.png)
**After**

![Screenshot_20221109_125746](https://user-images.githubusercontent.com/2087964/200828152-cb2f0cc7-28cc-4e54-800f-d5c9df0448c4.png)

Improve the non-root tooltips for the differential flamegraph:
 - remove the 'no change' label if there is no change
 - add the change rate of the samples as colored text

**Before**

![Screenshot_20221109_130600](https://user-images.githubusercontent.com/2087964/200828108-c6c78866-4aff-4617-ac0f-e78aeba78a54.png)
**After**

![Screenshot_20221109_125916](https://user-images.githubusercontent.com/2087964/200828149-8caac941-3c58-4389-ac7f-bda2e687faaa.png)

Fixes https://github.com/elastic/prodfiler/issues/2714

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Joseph Crail <joseph.crail@elastic.co>
This commit is contained in:
Tim Rühsen 2022-11-09 20:58:35 +01:00 committed by GitHub
parent ec3e66e213
commit f7758e0ada
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -6,7 +6,16 @@
*/
import { Chart, Datum, Flame, FlameLayerValue, PartialTheme, Settings } from '@elastic/charts';
import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSwitch, useEuiTheme } from '@elastic/eui';
import {
EuiFlexGroup,
EuiFlexItem,
EuiPanel,
EuiSpacer,
EuiSwitch,
EuiText,
EuiTextColor,
useEuiTheme,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { Maybe } from '@kbn/observability-plugin/common/typings';
import { isNumber } from 'lodash';
@ -29,46 +38,62 @@ function TooltipRow({
formatAsPercentage: boolean;
showChange: boolean;
}) {
const valueLabel = formatAsPercentage ? asPercentage(value) : value.toString();
const valueLabel = formatAsPercentage ? asPercentage(Math.abs(value)) : value.toString();
const comparisonLabel =
formatAsPercentage && isNumber(comparison) ? asPercentage(comparison) : comparison?.toString();
const diff = showChange && isNumber(comparison) ? comparison - value : undefined;
let diff: number | undefined;
let diffLabel = '';
let color = '';
let diffLabel: string | undefined = diff?.toString();
if (diff === 0) {
diffLabel = i18n.translate('xpack.profiling.flameGraphToolTip.diffNoChange', {
defaultMessage: 'no change',
});
} else if (formatAsPercentage && diff !== undefined) {
diffLabel = asPercentage(diff);
if (isNumber(comparison)) {
if (showChange) {
color = value < comparison ? 'danger' : 'success';
if (formatAsPercentage) {
// CPU percent values
diff = comparison - value;
diffLabel =
'(' + (diff > 0 ? '+' : diff < 0 ? '-' : '') + asPercentage(Math.abs(diff)) + ')';
} else {
// Sample counts
diff = 1 - comparison / value;
diffLabel =
'(' + (diff > 0 ? '-' : diff < 0 ? '+' : '') + asPercentage(Math.abs(diff)) + ')';
}
if (Math.abs(diff) < 0.0001) {
diffLabel = '';
}
}
}
return (
<EuiFlexItem style={{ width: 200, overflowWrap: 'anywhere' }}>
<EuiFlexItem style={{ width: 256, overflowWrap: 'anywhere' }}>
<EuiFlexGroup direction="row" gutterSize="xs">
<EuiFlexItem grow={false} style={{ fontWeight: 'bold' }}>
{label}
</EuiFlexItem>
<EuiFlexItem style={{}}>
{comparison
? i18n.translate('xpack.profiling.flameGraphTooltip.valueLabel', {
defaultMessage: `{value} vs {comparison}`,
values: {
value: valueLabel,
comparison: comparisonLabel,
},
})
: valueLabel}
{diffLabel ? ` (${diffLabel})` : ''}
<EuiText size="xs">
<strong>{label}</strong>
</EuiText>
<EuiText size="xs" style={{ marginLeft: '20px' }}>
{comparison !== undefined
? i18n.translate('xpack.profiling.flameGraphTooltip.valueLabel', {
defaultMessage: `{value} vs {comparison}`,
values: {
value: valueLabel,
comparison: comparisonLabel,
},
})
: valueLabel}
<EuiTextColor color={color}> {diffLabel}</EuiTextColor>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="xs" />
</EuiFlexItem>
);
}
function FlameGraphTooltip({
isRoot,
label,
countInclusive,
countExclusive,
@ -79,6 +104,7 @@ function FlameGraphTooltip({
comparisonSamples,
comparisonTotalSamples,
}: {
isRoot: boolean;
samples: number;
label: string;
countInclusive: number;
@ -101,40 +127,44 @@ function FlameGraphTooltip({
<EuiFlexItem>{label}</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup direction="column" gutterSize="xs">
<TooltipRow
label={i18n.translate('xpack.profiling.flameGraphTooltip.inclusiveCpuLabel', {
defaultMessage: `Inclusive CPU:`,
})}
value={countInclusive / totalSamples}
comparison={
isNumber(comparisonCountInclusive) && isNumber(comparisonTotalSamples)
? comparisonCountInclusive / comparisonTotalSamples
: undefined
}
formatAsPercentage
showChange
/>
<TooltipRow
label={i18n.translate('xpack.profiling.flameGraphTooltip.exclusiveCpuLabel', {
defaultMessage: `Exclusive CPU:`,
})}
value={countExclusive / totalSamples}
comparison={
isNumber(comparisonCountExclusive) && isNumber(comparisonTotalSamples)
? comparisonCountExclusive / comparisonTotalSamples
: undefined
}
formatAsPercentage
showChange
/>
{isRoot === false && (
<>
<TooltipRow
label={i18n.translate('xpack.profiling.flameGraphTooltip.inclusiveCpuLabel', {
defaultMessage: `CPU incl. subfunctions`,
})}
value={countInclusive / totalSamples}
comparison={
isNumber(comparisonCountInclusive) && isNumber(comparisonTotalSamples)
? comparisonCountInclusive / comparisonTotalSamples
: undefined
}
formatAsPercentage
showChange
/>
<TooltipRow
label={i18n.translate('xpack.profiling.flameGraphTooltip.exclusiveCpuLabel', {
defaultMessage: `CPU`,
})}
value={countExclusive / totalSamples}
comparison={
isNumber(comparisonCountExclusive) && isNumber(comparisonTotalSamples)
? comparisonCountExclusive / comparisonTotalSamples
: undefined
}
formatAsPercentage
showChange
/>
</>
)}
<TooltipRow
label={i18n.translate('xpack.profiling.flameGraphTooltip.samplesLabel', {
defaultMessage: `Samples:`,
defaultMessage: `Samples`,
})}
value={samples}
comparison={comparisonSamples}
value={countInclusive}
comparison={comparisonCountInclusive}
formatAsPercentage={false}
showChange={false}
showChange
/>
</EuiFlexGroup>
</EuiFlexItem>
@ -251,6 +281,7 @@ export const FlameGraph: React.FC<FlameGraphProps> = ({
return (
<FlameGraphTooltip
isRoot={valueIndex === 0}
label={label}
samples={samples}
countInclusive={countInclusive}