mirror of https://github.com/grafana/grafana.git
[release-12.0.6] FlameGraph: Ensure total is only counted once for recursive function calls (#111604)
Actionlint / Lint GitHub Actions files (push) Waiting to run
Details
Backend Code Checks / Validate Backend Configs (push) Waiting to run
Details
Backend Unit Tests / Detect whether code changed (push) Waiting to run
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (1/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (2/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (3/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (4/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (5/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (6/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (7/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (8/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (1/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (2/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (3/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (4/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (5/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (6/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (7/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (8/8) (push) Blocked by required conditions
Details
Backend Unit Tests / All backend unit tests complete (push) Blocked by required conditions
Details
CodeQL checks / Analyze (actions) (push) Waiting to run
Details
CodeQL checks / Analyze (go) (push) Waiting to run
Details
CodeQL checks / Analyze (javascript) (push) Waiting to run
Details
Lint Frontend / Detect whether code changed (push) Waiting to run
Details
Lint Frontend / Lint (push) Blocked by required conditions
Details
Lint Frontend / Typecheck (push) Blocked by required conditions
Details
Lint Frontend / Betterer (push) Blocked by required conditions
Details
Verify i18n / verify-i18n (push) Waiting to run
Details
End-to-end tests / Detect whether code changed (push) Waiting to run
Details
End-to-end tests / Build & Package Grafana (push) Blocked by required conditions
Details
End-to-end tests / Build E2E test runner (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env DISABLE_SCENES=true", e2e/old-arch/dashboards-suite, dashboards-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env DISABLE_SCENES=true", e2e/old-arch/panels-suite, panels-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env DISABLE_SCENES=true", e2e/old-arch/smoke-tests-suite, smoke-tests-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env DISABLE_SCENES=true", e2e/old-arch/various-suite, various-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/dashboards-suite, dashboards-suite) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/panels-suite, panels-suite) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/smoke-tests-suite, smoke-tests-suite) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/various-suite, various-suite) (push) Blocked by required conditions
Details
End-to-end tests / A11y test (push) Blocked by required conditions
Details
End-to-end tests / All E2E tests complete (push) Blocked by required conditions
Details
Frontend tests / Detect whether code changed (push) Waiting to run
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (1) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (2) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (3) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (4) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (5) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (6) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (7) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (8) (push) Blocked by required conditions
Details
Frontend tests / All frontend unit tests complete (push) Blocked by required conditions
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / All backend integration tests complete (push) Blocked by required conditions
Details
Reject GitHub secrets / reject-gh-secrets (push) Waiting to run
Details
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Waiting to run
Details
Shellcheck / Shellcheck scripts (push) Waiting to run
Details
Swagger generated code / Verify committed API specs match (push) Waiting to run
Details
Dispatch sync to mirror / dispatch-job (push) Waiting to run
Details
Actionlint / Lint GitHub Actions files (push) Waiting to run
Details
Backend Code Checks / Validate Backend Configs (push) Waiting to run
Details
Backend Unit Tests / Detect whether code changed (push) Waiting to run
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (1/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (2/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (3/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (4/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (5/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (6/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (7/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (8/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (1/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (2/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (3/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (4/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (5/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (6/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (7/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (8/8) (push) Blocked by required conditions
Details
Backend Unit Tests / All backend unit tests complete (push) Blocked by required conditions
Details
CodeQL checks / Analyze (actions) (push) Waiting to run
Details
CodeQL checks / Analyze (go) (push) Waiting to run
Details
CodeQL checks / Analyze (javascript) (push) Waiting to run
Details
Lint Frontend / Detect whether code changed (push) Waiting to run
Details
Lint Frontend / Lint (push) Blocked by required conditions
Details
Lint Frontend / Typecheck (push) Blocked by required conditions
Details
Lint Frontend / Betterer (push) Blocked by required conditions
Details
Verify i18n / verify-i18n (push) Waiting to run
Details
End-to-end tests / Detect whether code changed (push) Waiting to run
Details
End-to-end tests / Build & Package Grafana (push) Blocked by required conditions
Details
End-to-end tests / Build E2E test runner (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env DISABLE_SCENES=true", e2e/old-arch/dashboards-suite, dashboards-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env DISABLE_SCENES=true", e2e/old-arch/panels-suite, panels-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env DISABLE_SCENES=true", e2e/old-arch/smoke-tests-suite, smoke-tests-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env DISABLE_SCENES=true", e2e/old-arch/various-suite, various-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/dashboards-suite, dashboards-suite) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/panels-suite, panels-suite) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/smoke-tests-suite, smoke-tests-suite) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/various-suite, various-suite) (push) Blocked by required conditions
Details
End-to-end tests / A11y test (push) Blocked by required conditions
Details
End-to-end tests / All E2E tests complete (push) Blocked by required conditions
Details
Frontend tests / Detect whether code changed (push) Waiting to run
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (1) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (2) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (3) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (4) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (5) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (6) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (7) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (8) (push) Blocked by required conditions
Details
Frontend tests / All frontend unit tests complete (push) Blocked by required conditions
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / All backend integration tests complete (push) Blocked by required conditions
Details
Reject GitHub secrets / reject-gh-secrets (push) Waiting to run
Details
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Waiting to run
Details
Shellcheck / Shellcheck scripts (push) Waiting to run
Details
Swagger generated code / Verify committed API specs match (push) Waiting to run
Details
Dispatch sync to mirror / dispatch-job (push) Waiting to run
Details
FlameGraph: Ensure total is only counted once for recursive function calls (#111548)
grafana-flamegraph: Ensure total is only counted once for recursive function calls
Example flamegraph: https://flamegraph.com/share/2bb59df3-9930-11f0-94ec-760777e76ccd
(cherry picked from commit c5f6318b7b
)
Co-authored-by: Christian Simon <simon@swine.de>
This commit is contained in:
parent
d351ebe919
commit
ef3e1b4731
|
@ -5,9 +5,10 @@ import { createDataFrame } from '@grafana/data';
|
||||||
|
|
||||||
import { FlameGraphDataContainer } from '../FlameGraph/dataTransform';
|
import { FlameGraphDataContainer } from '../FlameGraph/dataTransform';
|
||||||
import { data } from '../FlameGraph/testData/dataNestedSet';
|
import { data } from '../FlameGraph/testData/dataNestedSet';
|
||||||
|
import { textToDataContainer } from '../FlameGraph/testHelpers';
|
||||||
import { ColorScheme } from '../types';
|
import { ColorScheme } from '../types';
|
||||||
|
|
||||||
import FlameGraphTopTableContainer from './FlameGraphTopTableContainer';
|
import FlameGraphTopTableContainer, { buildFilteredTable } from './FlameGraphTopTableContainer';
|
||||||
|
|
||||||
describe('FlameGraphTopTableContainer', () => {
|
describe('FlameGraphTopTableContainer', () => {
|
||||||
const setup = () => {
|
const setup = () => {
|
||||||
|
@ -48,7 +49,10 @@ describe('FlameGraphTopTableContainer', () => {
|
||||||
expect(cells).toHaveLength(60); // 16 rows
|
expect(cells).toHaveLength(60); // 16 rows
|
||||||
expect(cells[1].textContent).toEqual('net/http.HandlerFunc.ServeHTTP');
|
expect(cells[1].textContent).toEqual('net/http.HandlerFunc.ServeHTTP');
|
||||||
expect(cells[2].textContent).toEqual('31.7 K');
|
expect(cells[2].textContent).toEqual('31.7 K');
|
||||||
expect(cells[3].textContent).toEqual('31.7 Bil');
|
expect(cells[3].textContent).toEqual('5.58 Bil');
|
||||||
|
expect(cells[5].textContent).toEqual('total');
|
||||||
|
expect(cells[6].textContent).toEqual('16.5 K');
|
||||||
|
expect(cells[7].textContent).toEqual('16.5 Bil');
|
||||||
expect(cells[25].textContent).toEqual('net/http.(*conn).serve');
|
expect(cells[25].textContent).toEqual('net/http.(*conn).serve');
|
||||||
expect(cells[26].textContent).toEqual('5.63 K');
|
expect(cells[26].textContent).toEqual('5.63 K');
|
||||||
expect(cells[27].textContent).toEqual('5.63 Bil');
|
expect(cells[27].textContent).toEqual('5.63 Bil');
|
||||||
|
@ -74,3 +78,111 @@ describe('FlameGraphTopTableContainer', () => {
|
||||||
expect(mocks.onSandwich).toHaveBeenCalledWith('net/http.HandlerFunc.ServeHTTP');
|
expect(mocks.onSandwich).toHaveBeenCalledWith('net/http.HandlerFunc.ServeHTTP');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('buildFilteredTable', () => {
|
||||||
|
it('should group data by label and sum values', () => {
|
||||||
|
const container = textToDataContainer(`
|
||||||
|
[0////]
|
||||||
|
[1][2]
|
||||||
|
[3][4]
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = buildFilteredTable(container!);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
'0': { self: 1, total: 7, totalRight: 0 },
|
||||||
|
'1': { self: 0, total: 3, totalRight: 0 },
|
||||||
|
'2': { self: 0, total: 3, totalRight: 0 },
|
||||||
|
'3': { self: 3, total: 3, totalRight: 0 },
|
||||||
|
'4': { self: 3, total: 3, totalRight: 0 },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should sum values for duplicate labels', () => {
|
||||||
|
const container = textToDataContainer(`
|
||||||
|
[0///]
|
||||||
|
[1][1]
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = buildFilteredTable(container!);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
'0': { self: 0, total: 6, totalRight: 0 },
|
||||||
|
'1': { self: 6, total: 6, totalRight: 0 },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter by matchedLabels when provided', () => {
|
||||||
|
const container = textToDataContainer(`
|
||||||
|
[0////]
|
||||||
|
[1][2]
|
||||||
|
[3][4]
|
||||||
|
`);
|
||||||
|
|
||||||
|
const matchedLabels = new Set(['1', '3']);
|
||||||
|
const result = buildFilteredTable(container!, matchedLabels);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
'1': { self: 0, total: 3, totalRight: 0 },
|
||||||
|
'3': { self: 3, total: 3, totalRight: 0 },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty matchedLabels set', () => {
|
||||||
|
const container = textToDataContainer(`
|
||||||
|
[0////]
|
||||||
|
[1][2]
|
||||||
|
[3][4]
|
||||||
|
`);
|
||||||
|
|
||||||
|
const matchedLabels = new Set<string>();
|
||||||
|
const result = buildFilteredTable(container!, matchedLabels);
|
||||||
|
|
||||||
|
expect(result).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle data with no matches', () => {
|
||||||
|
const container = textToDataContainer(`
|
||||||
|
[0////]
|
||||||
|
[1][2]
|
||||||
|
[3][4]
|
||||||
|
`);
|
||||||
|
|
||||||
|
const matchedLabels = new Set(['9']);
|
||||||
|
const result = buildFilteredTable(container!, matchedLabels);
|
||||||
|
|
||||||
|
expect(result).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work without matchedLabels filter', () => {
|
||||||
|
const container = textToDataContainer(`
|
||||||
|
[0]
|
||||||
|
[1]
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = buildFilteredTable(container!);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
'0': { self: 0, total: 3, totalRight: 0 },
|
||||||
|
'1': { self: 3, total: 3, totalRight: 0 },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should not inflate totals for recursive calls', () => {
|
||||||
|
const container = textToDataContainer(`
|
||||||
|
[0////]
|
||||||
|
[1][2]
|
||||||
|
[3][4]
|
||||||
|
[0]
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = buildFilteredTable(container!);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
'0': { self: 4, total: 7, totalRight: 0 },
|
||||||
|
'1': { self: 0, total: 3, totalRight: 0 },
|
||||||
|
'2': { self: 0, total: 3, totalRight: 0 },
|
||||||
|
'3': { self: 0, total: 3, totalRight: 0 },
|
||||||
|
'4': { self: 3, total: 3, totalRight: 0 },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -53,28 +53,7 @@ const FlameGraphTopTableContainer = memo(
|
||||||
onTableSort,
|
onTableSort,
|
||||||
colorScheme,
|
colorScheme,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const table = useMemo(() => {
|
const table = useMemo(() => buildFilteredTable(data, matchedLabels), [data, matchedLabels]);
|
||||||
// Group the data by label, we show only one row per label and sum the values
|
|
||||||
// TODO: should be by filename + funcName + linenumber?
|
|
||||||
let filteredTable: { [key: string]: TableData } = Object.create(null);
|
|
||||||
for (let i = 0; i < data.data.length; i++) {
|
|
||||||
const value = data.getValue(i);
|
|
||||||
const valueRight = data.getValueRight(i);
|
|
||||||
const self = data.getSelf(i);
|
|
||||||
const label = data.getLabel(i);
|
|
||||||
|
|
||||||
// If user is doing text search we filter out labels in the same way we highlight them in flame graph.
|
|
||||||
if (!matchedLabels || matchedLabels.has(label)) {
|
|
||||||
filteredTable[label] = filteredTable[label] || {};
|
|
||||||
filteredTable[label].self = filteredTable[label].self ? filteredTable[label].self + self : self;
|
|
||||||
filteredTable[label].total = filteredTable[label].total ? filteredTable[label].total + value : value;
|
|
||||||
filteredTable[label].totalRight = filteredTable[label].totalRight
|
|
||||||
? filteredTable[label].totalRight + valueRight
|
|
||||||
: valueRight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filteredTable;
|
|
||||||
}, [data, matchedLabels]);
|
|
||||||
|
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
|
@ -124,6 +103,49 @@ const FlameGraphTopTableContainer = memo(
|
||||||
|
|
||||||
FlameGraphTopTableContainer.displayName = 'FlameGraphTopTableContainer';
|
FlameGraphTopTableContainer.displayName = 'FlameGraphTopTableContainer';
|
||||||
|
|
||||||
|
function buildFilteredTable(data: FlameGraphDataContainer, matchedLabels?: Set<string>) {
|
||||||
|
// Group the data by label, we show only one row per label and sum the values
|
||||||
|
// TODO: should be by filename + funcName + linenumber?
|
||||||
|
let filteredTable: { [key: string]: TableData } = Object.create(null);
|
||||||
|
|
||||||
|
// Track call stack to detect recursive calls
|
||||||
|
const callStack: string[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < data.data.length; i++) {
|
||||||
|
const value = data.getValue(i);
|
||||||
|
const valueRight = data.getValueRight(i);
|
||||||
|
const self = data.getSelf(i);
|
||||||
|
const label = data.getLabel(i);
|
||||||
|
const level = data.getLevel(i);
|
||||||
|
|
||||||
|
// Maintain call stack based on level changes
|
||||||
|
while (callStack.length > level) {
|
||||||
|
callStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this is a recursive call (same label already in call stack)
|
||||||
|
const isRecursive = callStack.some((entry) => entry === label);
|
||||||
|
|
||||||
|
// If user is doing text search we filter out labels in the same way we highlight them in flame graph.
|
||||||
|
if (!matchedLabels || matchedLabels.has(label)) {
|
||||||
|
filteredTable[label] = filteredTable[label] || {};
|
||||||
|
filteredTable[label].self = filteredTable[label].self ? filteredTable[label].self + self : self;
|
||||||
|
|
||||||
|
// Only add to total if this is not a recursive call
|
||||||
|
if (!isRecursive) {
|
||||||
|
filteredTable[label].total = filteredTable[label].total ? filteredTable[label].total + value : value;
|
||||||
|
filteredTable[label].totalRight = filteredTable[label].totalRight
|
||||||
|
? filteredTable[label].totalRight + valueRight
|
||||||
|
: valueRight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add current call to the stack
|
||||||
|
callStack.push(label);
|
||||||
|
}
|
||||||
|
return filteredTable;
|
||||||
|
}
|
||||||
|
|
||||||
function buildTableDataFrame(
|
function buildTableDataFrame(
|
||||||
data: FlameGraphDataContainer,
|
data: FlameGraphDataContainer,
|
||||||
table: { [key: string]: TableData },
|
table: { [key: string]: TableData },
|
||||||
|
@ -365,4 +387,6 @@ const getStylesActionCell = () => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { buildFilteredTable };
|
||||||
|
|
||||||
export default FlameGraphTopTableContainer;
|
export default FlameGraphTopTableContainer;
|
||||||
|
|
Loading…
Reference in New Issue