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'; tooltipRef.current.style.top = e.clientY + 'px';
const bar = levels[levelIndex][barIndex]; 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); setTooltipData(tooltipData);
setShowTooltip(true); setShowTooltip(true);
} }

View File

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

View File

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

View File

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