Skip to content

Commit 15cc62f

Browse files
authored
Merge pull request grafana/phlare#178 from grafana/joey/canvas
Use canvas for Flamegraph
2 parents f4161ec + b59906c commit 15cc62f

File tree

8 files changed

+29376
-320
lines changed

8 files changed

+29376
-320
lines changed

grafana/flamegraph/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@testing-library/react": "12.1.4",
2121
"@testing-library/user-event": "14.2.0",
2222
"@types/lodash": "4.14.181",
23+
"jest-canvas-mock": "2.4.0",
2324
"prettier": "2.6.0",
2425
"ts-node": "9.1.1",
2526
"typescript": "^4.7.4"
Lines changed: 13 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { screen } from '@testing-library/dom';
2-
import { act, render } from '@testing-library/react';
3-
import userEvent from '@testing-library/user-event';
2+
import { render } from '@testing-library/react';
43
import React, { useState } from 'react';
54

65
import FlameGraph from './FlameGraph';
76
import { data } from '../data';
87
import { MutableDataFrame } from '@grafana/data';
8+
import 'jest-canvas-mock';
99

1010
describe('FlameGraph', () => {
1111
const FlameGraphWithProps = () => {
@@ -39,147 +39,17 @@ describe('FlameGraph', () => {
3939
);
4040
};
4141

42-
it('should render children', async () => {
43-
Object.defineProperty(HTMLDivElement.prototype, 'clientWidth', { value: 1600 });
44-
render(<FlameGraphWithProps />);
45-
46-
// first bar
47-
expect(screen.getByTestId('flamegraph').children.length).toEqual(338);
48-
expect(screen.getByTestId('flamegraph').children[0].textContent).toEqual('total');
49-
50-
// first bar click goes nowhere
51-
await userEvent.click(screen.getByTestId('flamegraph').children[0]);
52-
expect(screen.getByTestId('flamegraph').children.length).toEqual(338);
53-
expect(screen.getByTestId('flamegraph').children[0].textContent).toEqual('total');
54-
55-
// second bar has no text (below label threshold)
56-
expect(screen.getByTestId('flamegraph').children[1].textContent).toEqual('');
57-
58-
// second bar click (focuses second bar and shows every bar above itself)
59-
await act(async () => {
60-
await userEvent.click(screen.getByTestId('flamegraph').children[1]);
61-
expect(screen.getByTestId('flamegraph').children.length).toEqual(41);
62-
expect(screen.getByTestId('flamegraph').children[0].textContent).toEqual('total');
63-
expect(screen.getByTestId('flamegraph').children[1].textContent).toEqual(
64-
'github.com/grafana/fire/pkg/distributor.(*Distributor).Push.func1'
65-
);
66-
expect(screen.getByTestId('flamegraph').children[35].textContent).toEqual('sync.(*Pool).Get');
67-
});
68-
69-
// reset to show all bars
70-
await act(async () => {
71-
await userEvent.click(screen.getByTestId('flamegraph').children[0]);
72-
expect(screen.getByTestId('flamegraph').children.length).toEqual(338);
73-
expect(screen.getByTestId('flamegraph').children[0].textContent).toEqual('total');
74-
});
75-
76-
// fourth bar click
77-
await act(async () => {
78-
await userEvent.click(screen.getByTestId('flamegraph').children[0]); // reset to show all bars
79-
expect(screen.getByTestId('flamegraph').children[3].textContent).toEqual(
80-
'github.com/grafana/fire/pkg/agent.(*Target).start.func1'
81-
);
82-
await userEvent.click(screen.getByTestId('flamegraph').children[3]);
83-
expect(screen.getByTestId('flamegraph').children.length).toEqual(31);
84-
expect(screen.getByTestId('flamegraph').children[0].textContent).toEqual('total');
85-
expect(screen.getByTestId('flamegraph').children[1].textContent).toEqual(
86-
'github.com/grafana/fire/pkg/agent.(*Target).start.func1'
87-
);
88-
});
89-
90-
// greyed out bar click that has no data-x, data-y attributes (bar is collapsed) so click goes nowhere
91-
await act(async () => {
92-
await userEvent.click(screen.getByTestId('flamegraph').children[0]);
93-
expect(screen.getByTestId('flamegraph').children[41].textContent).toEqual('');
94-
await userEvent.click(screen.getByTestId('flamegraph').children[41]);
95-
expect(screen.getByTestId('flamegraph').children.length).toEqual(338);
96-
expect(screen.getByTestId('flamegraph').children[0].textContent).toEqual('total');
97-
expect(screen.getByTestId('flamegraph').children[2].textContent).toEqual('net/http.(*conn).serve');
98-
expect(screen.getByTestId('flamegraph').children[41].textContent).toEqual('');
99-
});
100-
101-
// clicking down the tree
102-
await act(async () => {
103-
await userEvent.click(screen.getByTestId('flamegraph').children[0]);
104-
expect(screen.getByTestId('flamegraph').children.length).toEqual(338);
105-
expect(screen.getByTestId('flamegraph').children[4].textContent).toEqual('runtime.main');
106-
await userEvent.click(screen.getByTestId('flamegraph').children[4]);
107-
expect(screen.getByTestId('flamegraph').children.length).toEqual(130);
108-
expect(screen.getByTestId('flamegraph').children[0].textContent).toEqual('total');
109-
expect(screen.getByTestId('flamegraph').children[1].textContent).toEqual('runtime.main');
110-
expect(screen.getByTestId('flamegraph').children[7].textContent).toEqual('runtime.doInit');
111-
await userEvent.click(screen.getByTestId('flamegraph').children[7]);
112-
expect(screen.getByTestId('flamegraph').children.length).toEqual(108);
113-
expect(screen.getByTestId('flamegraph').children[0].textContent).toEqual('total');
114-
expect(screen.getByTestId('flamegraph').children[1].textContent).toEqual('runtime.main');
115-
expect(screen.getByTestId('flamegraph').children[2].textContent).toEqual('runtime.doInit');
116-
expect(screen.getByTestId('flamegraph').children[3].textContent).toEqual('runtime.doInit');
117-
expect(screen.getByTestId('flamegraph').children[20].textContent).toEqual('text/template/parse.(*Tree).Parse');
118-
await userEvent.click(screen.getByTestId('flamegraph').children[20]);
119-
expect(screen.getByTestId('flamegraph').children.length).toEqual(21);
120-
expect(screen.getByTestId('flamegraph').children[0].textContent).toEqual('total');
121-
expect(screen.getByTestId('flamegraph').children[5].textContent).toEqual('github.com/grafana/dskit/ring.init');
122-
expect(screen.getByTestId('flamegraph').children[7].textContent).toEqual('text/template.(*Template).Parse');
123-
expect(screen.getByTestId('flamegraph').children[9].textContent).toEqual('text/template/parse.(*Tree).Parse');
124-
expect(screen.getByTestId('flamegraph').children[20].textContent).toEqual(
125-
'text/template/parse.(*PipeNode).append'
126-
);
127-
await userEvent.click(screen.getByTestId('flamegraph').children[20]);
128-
expect(screen.getByTestId('flamegraph').children.length).toEqual(20);
129-
expect(screen.getByTestId('flamegraph').children[0].textContent).toEqual('total');
130-
expect(screen.getByTestId('flamegraph').children[10].textContent).toEqual('text/template/parse.(*Tree).parse');
131-
expect(screen.getByTestId('flamegraph').children[15].textContent).toEqual('text/template/parse.(*Tree).itemList');
132-
expect(screen.getByTestId('flamegraph').children[18].textContent).toEqual('text/template/parse.(*Tree).pipeline');
133-
expect(screen.getByTestId('flamegraph').children[19].textContent).toEqual(
134-
'text/template/parse.(*PipeNode).append'
135-
);
136-
});
42+
it('should render without error', async () => {
43+
expect(() => render(<FlameGraphWithProps />)).not.toThrow();
44+
});
13745

138-
// clicking back up the tree
139-
await act(async () => {
140-
await userEvent.click(screen.getByTestId('flamegraph').children[18]);
141-
expect(screen.getByTestId('flamegraph').children.length).toEqual(21);
142-
expect(screen.getByTestId('flamegraph').children[19].textContent).toEqual(
143-
'text/template/parse.(*Tree).newPipeline'
144-
);
145-
expect(screen.getByTestId('flamegraph').children[20].textContent).toEqual(
146-
'text/template/parse.(*PipeNode).append'
147-
);
148-
await userEvent.click(screen.getByTestId('flamegraph').children[8]);
149-
expect(screen.getByTestId('flamegraph').children.length).toEqual(21);
150-
expect(screen.getByTestId('flamegraph').children[19].textContent).toEqual(
151-
'text/template/parse.(*Tree).newPipeline'
152-
);
153-
expect(screen.getByTestId('flamegraph').children[20].textContent).toEqual(
154-
'text/template/parse.(*PipeNode).append'
155-
);
156-
await userEvent.click(screen.getByTestId('flamegraph').children[4]);
157-
expect(screen.getByTestId('flamegraph').children.length).toEqual(108);
158-
expect(screen.getByTestId('flamegraph').children[19].textContent).toEqual(
159-
'github.com/prometheus/client_golang/prometheus.(*SummaryVec).WithLabelValues'
160-
);
161-
expect(screen.getByTestId('flamegraph').children[20].textContent).toEqual('text/template/parse.(*Tree).Parse');
162-
await userEvent.click(screen.getByTestId('flamegraph').children[3]);
163-
expect(screen.getByTestId('flamegraph').children.length).toEqual(108);
164-
expect(screen.getByTestId('flamegraph').children[19].textContent).toEqual(
165-
'github.com/prometheus/client_golang/prometheus.(*SummaryVec).WithLabelValues'
166-
);
167-
expect(screen.getByTestId('flamegraph').children[20].textContent).toEqual('text/template/parse.(*Tree).Parse');
168-
await userEvent.click(screen.getByTestId('flamegraph').children[1]);
169-
expect(screen.getByTestId('flamegraph').children.length).toEqual(130);
170-
expect(screen.getByTestId('flamegraph').children[19].textContent).toEqual(
171-
'github.com/mwitkow/go-conntrack.NewDialContextFunc'
172-
);
173-
expect(screen.getByTestId('flamegraph').children[20].textContent).toEqual('runtime.doInit');
174-
await userEvent.click(screen.getByTestId('flamegraph').children[0]);
175-
expect(screen.getByTestId('flamegraph').children.length).toEqual(338);
176-
expect(screen.getByTestId('flamegraph').children[0].textContent).toEqual('total');
177-
expect(screen.getByTestId('flamegraph').children[1].textContent).toEqual('');
178-
expect(screen.getByTestId('flamegraph').children[2].textContent).toEqual('net/http.(*conn).serve');
179-
expect(screen.getByTestId('flamegraph').children[19].textContent).toEqual('runtime.gcMarkDone');
180-
expect(screen.getByTestId('flamegraph').children[20].textContent).toEqual(
181-
'github.com/weaveworks/common/signals.(*Handler).Loop'
182-
);
183-
});
46+
it('should render correctly', async () => {
47+
Object.defineProperty(HTMLCanvasElement.prototype, 'clientWidth', { value: 1600 });
48+
render(<FlameGraphWithProps />);
49+
50+
const canvas = screen.getByTestId("flamegraph") as HTMLCanvasElement;
51+
const ctx = canvas!.getContext('2d');
52+
const calls = ctx!.__getDrawCalls();
53+
expect(calls).toMatchSnapshot();
18454
});
18555
});

0 commit comments

Comments
 (0)