mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Flamegraph: Rendering from tree instead of levels (#76215)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { createDataFrame, FieldType } from '@grafana/data';
|
||||
|
||||
import { FlameGraphDataContainer, LevelItem } from './dataTransform';
|
||||
import { getRectDimensionsForLevel } from './rendering';
|
||||
import { walkTree } from './rendering';
|
||||
|
||||
function makeDataFrame(fields: Record<string, Array<number | string>>) {
|
||||
return createDataFrame({
|
||||
@@ -13,76 +13,99 @@ function makeDataFrame(fields: Record<string, Array<number | string>>) {
|
||||
});
|
||||
}
|
||||
|
||||
describe('getRectDimensionsForLevel', () => {
|
||||
it('should render a single item', () => {
|
||||
const level: LevelItem[] = [{ start: 0, itemIndexes: [0], children: [], value: 100 }];
|
||||
type RenderData = {
|
||||
item: LevelItem;
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
label: string;
|
||||
collapsed: boolean;
|
||||
};
|
||||
|
||||
describe('walkTree', () => {
|
||||
it('correctly compute sizes for a single item', () => {
|
||||
const root: LevelItem = { start: 0, itemIndexes: [0], children: [], value: 100, level: 0 };
|
||||
const container = new FlameGraphDataContainer(makeDataFrame({ value: [100], level: [1], label: ['1'], self: [0] }));
|
||||
const result = getRectDimensionsForLevel(container, level, 1, 100, 0, 10);
|
||||
expect(result).toEqual([
|
||||
{
|
||||
width: 999,
|
||||
height: 22,
|
||||
itemIndex: 0,
|
||||
x: 0,
|
||||
y: 22,
|
||||
collapsed: false,
|
||||
ticks: 100,
|
||||
label: '1',
|
||||
unitLabel: '100',
|
||||
},
|
||||
]);
|
||||
walkTree(root, 'children', container, 100, 0, 1, 100, (item, x, y, width, height, label, collapsed) => {
|
||||
expect(item).toEqual(root);
|
||||
expect(x).toEqual(0);
|
||||
expect(y).toEqual(0);
|
||||
expect(width).toEqual(99); // -1 for border
|
||||
expect(height).toEqual(22);
|
||||
expect(label).toEqual('1');
|
||||
expect(collapsed).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should render a multiple items', () => {
|
||||
const level: LevelItem[] = [
|
||||
{ start: 0, itemIndexes: [0], children: [], value: 100 },
|
||||
{ start: 100, itemIndexes: [1], children: [], value: 50 },
|
||||
{ start: 150, itemIndexes: [2], children: [], value: 50 },
|
||||
];
|
||||
const root: LevelItem = {
|
||||
start: 0,
|
||||
itemIndexes: [0],
|
||||
value: 100,
|
||||
level: 0,
|
||||
children: [
|
||||
{ start: 0, itemIndexes: [1], children: [], value: 50, level: 1 },
|
||||
{ start: 50, itemIndexes: [2], children: [], value: 50, level: 1 },
|
||||
],
|
||||
};
|
||||
const container = new FlameGraphDataContainer(
|
||||
makeDataFrame({ value: [100, 50, 50], level: [2, 2, 2], label: ['1', '2', '3'], self: [0, 0, 0] })
|
||||
makeDataFrame({ value: [100, 50, 50], level: [0, 1, 1], label: ['1', '2', '3'], self: [0, 50, 50] })
|
||||
);
|
||||
const result = getRectDimensionsForLevel(container, level, 2, 100, 0, 10);
|
||||
expect(result).toEqual([
|
||||
{ width: 999, height: 22, x: 0, y: 44, collapsed: false, ticks: 100, label: '1', unitLabel: '100', itemIndex: 0 },
|
||||
{
|
||||
width: 499,
|
||||
height: 22,
|
||||
x: 1000,
|
||||
y: 44,
|
||||
collapsed: false,
|
||||
ticks: 50,
|
||||
label: '2',
|
||||
unitLabel: '50',
|
||||
itemIndex: 1,
|
||||
},
|
||||
{
|
||||
width: 499,
|
||||
height: 22,
|
||||
x: 1500,
|
||||
y: 44,
|
||||
collapsed: false,
|
||||
ticks: 50,
|
||||
label: '3',
|
||||
unitLabel: '50',
|
||||
itemIndex: 2,
|
||||
},
|
||||
const renderData: RenderData[] = [];
|
||||
walkTree(root, 'children', container, 100, 0, 1, 100, (item, x, y, width, height, label, collapsed) => {
|
||||
renderData.push({ item, x, y, width, height, label, collapsed });
|
||||
});
|
||||
expect(renderData).toEqual([
|
||||
{ item: root, width: 99, height: 22, x: 0, y: 0, collapsed: false, label: '1' },
|
||||
{ item: root.children[0], width: 49, height: 22, x: 0, y: 22, collapsed: false, label: '2' },
|
||||
{ item: root.children[1], width: 49, height: 22, x: 50, y: 22, collapsed: false, label: '3' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should render a collapsed items', () => {
|
||||
const level: LevelItem[] = [
|
||||
{ start: 0, itemIndexes: [0], children: [], value: 100 },
|
||||
{ start: 100, itemIndexes: [1], children: [], value: 2 },
|
||||
{ start: 102, itemIndexes: [2], children: [], value: 1 },
|
||||
];
|
||||
const root: LevelItem = {
|
||||
start: 0,
|
||||
itemIndexes: [0],
|
||||
value: 100,
|
||||
level: 0,
|
||||
children: [
|
||||
{ start: 0, itemIndexes: [1], children: [], value: 1, level: 1 },
|
||||
{ start: 1, itemIndexes: [2], children: [], value: 1, level: 1 },
|
||||
],
|
||||
};
|
||||
const container = new FlameGraphDataContainer(
|
||||
makeDataFrame({ value: [100, 2, 1], level: [2, 2, 2], label: ['1', '2', '3'], self: [0, 0, 0] })
|
||||
makeDataFrame({ value: [100, 1, 1], level: [0, 1, 1], label: ['1', '2', '3'], self: [0, 1, 1] })
|
||||
);
|
||||
const result = getRectDimensionsForLevel(container, level, 2, 100, 0, 1);
|
||||
expect(result).toEqual([
|
||||
{ width: 99, height: 22, x: 0, y: 44, collapsed: false, ticks: 100, label: '1', unitLabel: '100', itemIndex: 0 },
|
||||
{ width: 3, height: 22, x: 100, y: 44, collapsed: true, ticks: 3, label: '2', unitLabel: '2', itemIndex: 1 },
|
||||
const renderData: RenderData[] = [];
|
||||
walkTree(root, 'children', container, 100, 0, 1, 100, (item, x, y, width, height, label, collapsed) => {
|
||||
renderData.push({ item, x, y, width, height, label, collapsed });
|
||||
});
|
||||
expect(renderData).toEqual([
|
||||
{ item: root, width: 99, height: 22, x: 0, y: 0, collapsed: false, label: '1' },
|
||||
{ item: root.children[0], width: 1, height: 22, x: 0, y: 22, collapsed: true, label: '2' },
|
||||
{ item: root.children[1], width: 1, height: 22, x: 1, y: 22, collapsed: true, label: '3' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('skips too small items', () => {
|
||||
const root: LevelItem = {
|
||||
start: 0,
|
||||
itemIndexes: [0],
|
||||
value: 100,
|
||||
level: 0,
|
||||
children: [
|
||||
{ start: 0, itemIndexes: [1], children: [], value: 0.1, level: 1 },
|
||||
{ start: 1, itemIndexes: [2], children: [], value: 0.1, level: 1 },
|
||||
],
|
||||
};
|
||||
const container = new FlameGraphDataContainer(
|
||||
makeDataFrame({ value: [100, 0.1, 0.1], level: [0, 1, 1], label: ['1', '2', '3'], self: [0, 0.1, 0.1] })
|
||||
);
|
||||
const renderData: RenderData[] = [];
|
||||
walkTree(root, 'children', container, 100, 0, 1, 100, (item, x, y, width, height, label, collapsed) => {
|
||||
renderData.push({ item, x, y, width, height, label, collapsed });
|
||||
});
|
||||
expect(renderData).toEqual([{ item: root, width: 99, height: 22, x: 0, y: 0, collapsed: false, label: '1' }]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user