Flamegraph: Add self to tooltip (#57548)

* Add self to tooltip

* Fix tests

* Update layout

* Fixed too much space on the bottom
This commit is contained in:
Andrej Ocenas 2022-11-02 19:07:11 +01:00 committed by GitHub
parent d5a92e8f42
commit 9e03355e53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 23 deletions

View File

@ -142,7 +142,7 @@ const FlameGraph = ({
tooltipRef.current.style.top = e.clientY + 'px';
const bar = levels[levelIndex][barIndex];
const tooltipData = getTooltipData(valueField!, bar.label, bar.value, totalTicks);
const tooltipData = getTooltipData(valueField!, bar.label, bar.value, bar.self, totalTicks);
setTooltipData(tooltipData);
setShowTooltip(true);
}

View File

@ -4,23 +4,27 @@ import { getTooltipData } from './FlameGraphTooltip';
describe('should get tooltip data correctly', () => {
it('for bytes', () => {
const tooltipData = getTooltipData(makeField('bytes'), 'total', 8_624_078_250, 8_624_078_250);
const tooltipData = getTooltipData(makeField('bytes'), 'total', 8_624_078_250, 978_250, 8_624_078_250);
expect(tooltipData).toEqual({
name: 'total',
percentSelf: 0.01,
percentTitle: '% of total',
percentValue: 100,
unitTitle: 'RAM',
unitSelf: '955 KiB',
unitValue: '8.03 GiB',
samples: '8,624,078,250',
});
});
it('with none unit', () => {
const tooltipData = getTooltipData(makeField('none'), 'total', 8_624_078_250, 8_624_078_250);
const tooltipData = getTooltipData(makeField('none'), 'total', 8_624_078_250, 978_250, 8_624_078_250);
expect(tooltipData).toEqual({
name: 'total',
percentSelf: 0.01,
percentTitle: '% of total',
percentValue: 100,
unitSelf: '978250',
unitTitle: 'Count',
unitValue: '8624078250',
samples: '8,624,078,250',
@ -37,37 +41,44 @@ describe('should get tooltip data correctly', () => {
},
'total',
8_624_078_250,
978_250,
8_624_078_250
);
expect(tooltipData).toEqual({
name: 'total',
percentSelf: 0.01,
percentTitle: '% of total',
percentValue: 100,
unitTitle: 'Count',
unitSelf: '978250',
unitValue: '8624078250',
samples: '8,624,078,250',
});
});
it('for objects', () => {
const tooltipData = getTooltipData(makeField('short'), 'total', 8_624_078_250, 8_624_078_250);
const tooltipData = getTooltipData(makeField('short'), 'total', 8_624_078_250, 978_250, 8_624_078_250);
expect(tooltipData).toEqual({
name: 'total',
percentSelf: 0.01,
percentTitle: '% of total',
percentValue: 100,
unitTitle: 'Count',
unitSelf: '978 K',
unitValue: '8.62 Bil',
samples: '8,624,078,250',
});
});
it('for nanoseconds', () => {
const tooltipData = getTooltipData(makeField('ns'), 'total', 8_624_078_250, 8_624_078_250);
const tooltipData = getTooltipData(makeField('ns'), 'total', 8_624_078_250, 978_250, 8_624_078_250);
expect(tooltipData).toEqual({
name: 'total',
percentSelf: 0.01,
percentTitle: '% of total time',
percentValue: 100,
unitTitle: 'Time',
unitSelf: '978 µs',
unitValue: '8.62 s',
samples: '8,624,078,250',
});

View File

@ -21,16 +21,16 @@ const FlameGraphTooltip = ({ tooltipRef, tooltipData, showTooltip }: Props) => {
<Tooltip
content={
<div>
<div className={styles.name}>{tooltipData.name}</div>
<div>
{tooltipData.percentTitle}: <b>{tooltipData.percentValue}%</b>
</div>
<div>
{tooltipData.unitTitle}: <b>{tooltipData.unitValue}</b>
</div>
<div>
<p>{tooltipData.name}</p>
<p className={styles.lastParagraph}>
{tooltipData.unitTitle}
<br />
Total: <b>{tooltipData.unitValue}</b> ({tooltipData.percentValue}%)
<br />
Self: <b>{tooltipData.unitSelf}</b> ({tooltipData.percentSelf}%)
<br />
Samples: <b>{tooltipData.samples}</b>
</div>
</p>
</div>
}
placement={'right'}
@ -43,15 +43,24 @@ const FlameGraphTooltip = ({ tooltipRef, tooltipData, showTooltip }: Props) => {
);
};
export const getTooltipData = (field: Field, label: string, value: number, totalTicks: number): TooltipData => {
let samples = value;
let percentTitle = '';
let unitTitle = '';
export const getTooltipData = (
field: Field,
label: string,
value: number,
self: number,
totalTicks: number
): TooltipData => {
let percentTitle;
let unitTitle;
const processor = getDisplayProcessor({ field, theme: createTheme() /* theme does not matter for us here */ });
const displayValue = processor(value);
const percent = Math.round(10000 * (samples / totalTicks)) / 100;
const displaySelf = processor(self);
const percentValue = Math.round(10000 * (value / totalTicks)) / 100;
const percentSelf = Math.round(10000 * (self / totalTicks)) / 100;
let unitValue = displayValue.text + displayValue.suffix;
let unitSelf = displaySelf.text + displaySelf.suffix;
switch (field.config.unit) {
case SampleUnit.Bytes:
@ -69,16 +78,22 @@ export const getTooltipData = (field: Field, label: string, value: number, total
// Makes sure we don't show 123undefined or something like that if suffix isn't defined
unitValue = displayValue.text;
}
if (!displaySelf.suffix) {
// Makes sure we don't show 123undefined or something like that if suffix isn't defined
unitSelf = displaySelf.text;
}
break;
}
return {
name: label,
percentTitle: percentTitle,
percentValue: percent,
unitTitle: unitTitle,
percentTitle,
percentValue,
percentSelf,
unitTitle,
unitValue,
samples: samples.toLocaleString(),
unitSelf,
samples: value.toLocaleString(),
};
};
@ -86,6 +101,9 @@ const getStyles = () => ({
tooltip: css`
position: fixed;
`,
lastParagraph: css`
margin-bottom: 0;
`,
name: css`
margin-bottom: 10px;
`,

View File

@ -2,8 +2,10 @@ export type TooltipData = {
name: string;
percentTitle: string;
percentValue: number;
percentSelf: number;
unitTitle: string;
unitValue: string;
unitSelf: string;
samples: string;
};