@kylincloud/flamegraph 0.35.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1211 -0
- package/LICENSE +202 -0
- package/README.md +251 -0
- package/dist/FlameGraph/FlameGraphComponent/CheckIcon.d.ts +2 -0
- package/dist/FlameGraph/FlameGraphComponent/CheckIcon.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/ContextMenu.d.ts +17 -0
- package/dist/FlameGraph/FlameGraphComponent/ContextMenu.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/ContextMenuHighlight.d.ts +14 -0
- package/dist/FlameGraph/FlameGraphComponent/ContextMenuHighlight.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/DiffLegend.d.ts +9 -0
- package/dist/FlameGraph/FlameGraphComponent/DiffLegend.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.d.ts +8 -0
- package/dist/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/Flamegraph.d.ts +96 -0
- package/dist/FlameGraph/FlameGraphComponent/Flamegraph.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/Flamegraph_render.d.ts +27 -0
- package/dist/FlameGraph/FlameGraphComponent/Flamegraph_render.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/GraphVizPane.d.ts +7 -0
- package/dist/FlameGraph/FlameGraphComponent/GraphVizPane.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/Header.d.ts +12 -0
- package/dist/FlameGraph/FlameGraphComponent/Header.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/Highlight.d.ts +18 -0
- package/dist/FlameGraph/FlameGraphComponent/Highlight.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/LogoLink.d.ts +2 -0
- package/dist/FlameGraph/FlameGraphComponent/LogoLink.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/color.d.ts +20 -0
- package/dist/FlameGraph/FlameGraphComponent/color.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/colorPalette.d.ts +11 -0
- package/dist/FlameGraph/FlameGraphComponent/colorPalette.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/constants.d.ts +6 -0
- package/dist/FlameGraph/FlameGraphComponent/constants.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/index.d.ts +37 -0
- package/dist/FlameGraph/FlameGraphComponent/index.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/murmur3.d.ts +2 -0
- package/dist/FlameGraph/FlameGraphComponent/murmur3.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/testData.d.ts +53 -0
- package/dist/FlameGraph/FlameGraphComponent/testData.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/utils.d.ts +6 -0
- package/dist/FlameGraph/FlameGraphComponent/utils.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphComponent/viewTypes.d.ts +2 -0
- package/dist/FlameGraph/FlameGraphComponent/viewTypes.d.ts.map +1 -0
- package/dist/FlameGraph/FlameGraphRenderer.d.ts +86 -0
- package/dist/FlameGraph/FlameGraphRenderer.d.ts.map +1 -0
- package/dist/FlameGraph/decode.d.ts +27 -0
- package/dist/FlameGraph/decode.d.ts.map +1 -0
- package/dist/FlameGraph/normalize.d.ts +6 -0
- package/dist/FlameGraph/normalize.d.ts.map +1 -0
- package/dist/FlameGraph/uniqueness.d.ts +3 -0
- package/dist/FlameGraph/uniqueness.d.ts.map +1 -0
- package/dist/FlamegraphRenderer.d.ts +19 -0
- package/dist/FlamegraphRenderer.d.ts.map +1 -0
- package/dist/Icons.d.ts +9 -0
- package/dist/Icons.d.ts.map +1 -0
- package/dist/ProfilerTable.d.ts +21 -0
- package/dist/ProfilerTable.d.ts.map +1 -0
- package/dist/SharedQueryInput.d.ts +10 -0
- package/dist/SharedQueryInput.d.ts.map +1 -0
- package/dist/Toolbar.d.ts +31 -0
- package/dist/Toolbar.d.ts.map +1 -0
- package/dist/Tooltip/FlamegraphTooltip.d.ts +59 -0
- package/dist/Tooltip/FlamegraphTooltip.d.ts.map +1 -0
- package/dist/Tooltip/LeftClickIcon.d.ts +2 -0
- package/dist/Tooltip/LeftClickIcon.d.ts.map +1 -0
- package/dist/Tooltip/RightClickIcon.d.ts +2 -0
- package/dist/Tooltip/RightClickIcon.d.ts.map +1 -0
- package/dist/Tooltip/TableTooltip.d.ts +12 -0
- package/dist/Tooltip/TableTooltip.d.ts.map +1 -0
- package/dist/Tooltip/Tooltip.d.ts +29 -0
- package/dist/Tooltip/Tooltip.d.ts.map +1 -0
- package/dist/convert/convertJaegerTraceToProfile.d.ts +3 -0
- package/dist/convert/convertJaegerTraceToProfile.d.ts.map +1 -0
- package/dist/convert/diffTwoProfiles.d.ts +3 -0
- package/dist/convert/diffTwoProfiles.d.ts.map +1 -0
- package/dist/convert/flamebearersToTree.d.ts +11 -0
- package/dist/convert/flamebearersToTree.d.ts.map +1 -0
- package/dist/convert/sandwichViewProfiles.d.ts +14 -0
- package/dist/convert/sandwichViewProfiles.d.ts.map +1 -0
- package/dist/convert/subtract.d.ts +3 -0
- package/dist/convert/subtract.d.ts.map +1 -0
- package/dist/convert/testData.d.ts +50 -0
- package/dist/convert/testData.d.ts.map +1 -0
- package/dist/convert/toGraphviz.d.ts +3 -0
- package/dist/convert/toGraphviz.d.ts.map +1 -0
- package/dist/fitMode/fitMode.d.ts +42 -0
- package/dist/fitMode/fitMode.d.ts.map +1 -0
- package/dist/format/format.d.ts +42 -0
- package/dist/format/format.d.ts.map +1 -0
- package/dist/i18n.d.ts +55 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/index.cjs.css +792 -0
- package/dist/index.cjs.js +5087 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.css +792 -0
- package/dist/index.esm.js +5079 -0
- package/dist/index.node.d.ts +9 -0
- package/dist/index.node.d.ts.map +1 -0
- package/dist/logo-v3-small-T5VXIMRR.svg +32 -0
- package/dist/models/decode.d.ts +3 -0
- package/dist/models/decode.d.ts.map +1 -0
- package/dist/models/flamebearer.d.ts +63 -0
- package/dist/models/flamebearer.d.ts.map +1 -0
- package/dist/models/groups.d.ts +37 -0
- package/dist/models/groups.d.ts.map +1 -0
- package/dist/models/index.d.ts +8 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/profile.d.ts +152 -0
- package/dist/models/profile.d.ts.map +1 -0
- package/dist/models/spyName.d.ts +8 -0
- package/dist/models/spyName.d.ts.map +1 -0
- package/dist/models/trace.d.ts +357 -0
- package/dist/models/trace.d.ts.map +1 -0
- package/dist/models/units.d.ts +6 -0
- package/dist/models/units.d.ts.map +1 -0
- package/dist/search.d.ts +2 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/shims/Box.d.ts +38 -0
- package/dist/shims/Box.d.ts.map +1 -0
- package/dist/shims/Button.d.ts +26 -0
- package/dist/shims/Button.d.ts.map +1 -0
- package/dist/shims/Dropdown.d.ts +30 -0
- package/dist/shims/Dropdown.d.ts.map +1 -0
- package/dist/shims/Input.d.ts +19 -0
- package/dist/shims/Input.d.ts.map +1 -0
- package/dist/shims/LoadingSpinner.d.ts +7 -0
- package/dist/shims/LoadingSpinner.d.ts.map +1 -0
- package/dist/shims/Menu.d.ts +4 -0
- package/dist/shims/Menu.d.ts.map +1 -0
- package/dist/shims/NoData.d.ts +2 -0
- package/dist/shims/NoData.d.ts.map +1 -0
- package/dist/shims/Table.d.ts +52 -0
- package/dist/shims/Table.d.ts.map +1 -0
- package/dist/shims/Tooltip.d.ts +9 -0
- package/dist/shims/Tooltip.d.ts.map +1 -0
- package/package.json +84 -0
- package/src/FlameGraph/FlameGraphComponent/CheckIcon.tsx +27 -0
- package/src/FlameGraph/FlameGraphComponent/ContextMenu.module.scss +10 -0
- package/src/FlameGraph/FlameGraphComponent/ContextMenu.spec.tsx +84 -0
- package/src/FlameGraph/FlameGraphComponent/ContextMenu.tsx +86 -0
- package/src/FlameGraph/FlameGraphComponent/ContextMenuHighlight.module.css +8 -0
- package/src/FlameGraph/FlameGraphComponent/ContextMenuHighlight.tsx +47 -0
- package/src/FlameGraph/FlameGraphComponent/DiffLegend.module.css +21 -0
- package/src/FlameGraph/FlameGraphComponent/DiffLegend.tsx +52 -0
- package/src/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.module.css +40 -0
- package/src/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.tsx +129 -0
- package/src/FlameGraph/FlameGraphComponent/Flamegraph.spec.ts +552 -0
- package/src/FlameGraph/FlameGraphComponent/Flamegraph.ts +446 -0
- package/src/FlameGraph/FlameGraphComponent/Flamegraph_render.spec.tsx +233 -0
- package/src/FlameGraph/FlameGraphComponent/Flamegraph_render.ts +478 -0
- package/src/FlameGraph/FlameGraphComponent/GraphVizPane.tsx +56 -0
- package/src/FlameGraph/FlameGraphComponent/GraphVizPanel.module.scss +55 -0
- package/src/FlameGraph/FlameGraphComponent/Header.module.css +27 -0
- package/src/FlameGraph/FlameGraphComponent/Header.tsx +71 -0
- package/src/FlameGraph/FlameGraphComponent/Highlight.module.css +7 -0
- package/src/FlameGraph/FlameGraphComponent/Highlight.spec.tsx +53 -0
- package/src/FlameGraph/FlameGraphComponent/Highlight.tsx +94 -0
- package/src/FlameGraph/FlameGraphComponent/LogoLink.module.scss +10 -0
- package/src/FlameGraph/FlameGraphComponent/LogoLink.tsx +101 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/canvas-renderer-spec-tsx-canvas-renderer-group-snapshot-collapses-small-blocks-into-one-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/canvas-renderer-spec-tsx-canvas-renderer-group-snapshot-works-with-diff-mode-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/canvas-renderer-spec-tsx-canvas-renderer-group-snapshot-works-with-highlighted-flamegraph-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/canvas-renderer-spec-tsx-canvas-renderer-group-snapshot-works-with-normal-flamegraph-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/canvas-renderer-spec-tsx-canvas-renderer-group-snapshot-works-with-selected-node-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-focused-also-zooms-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-focused-renders-a-focused-node-in-the-beginning-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-focused-renders-a-focused-node-when-node-is-not-in-the-beginning-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-focused-renders-a-focused-node-zoom-top-level-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-complex-flamegraph-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-double-diff-flamegraph-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-highlighted-double-flamegraph-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-highlighted-flamegraph-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-simple-flamegraph-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-simple-tree-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-zoomed-flamegraph-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/__image_snapshots__/flamegraph-render-spec-tsx-render-group-snapshot-renders-a-zoomed-with-fit-mode-tail-1-snap.png +0 -0
- package/src/FlameGraph/FlameGraphComponent/canvas.module.css +6 -0
- package/src/FlameGraph/FlameGraphComponent/color.spec.ts +308 -0
- package/src/FlameGraph/FlameGraphComponent/color.ts +167 -0
- package/src/FlameGraph/FlameGraphComponent/colorPalette.ts +58 -0
- package/src/FlameGraph/FlameGraphComponent/constants.ts +5 -0
- package/src/FlameGraph/FlameGraphComponent/index.spec.tsx +291 -0
- package/src/FlameGraph/FlameGraphComponent/index.tsx +411 -0
- package/src/FlameGraph/FlameGraphComponent/murmur3.ts +97 -0
- package/src/FlameGraph/FlameGraphComponent/styles.module.scss +10 -0
- package/src/FlameGraph/FlameGraphComponent/testData.ts +427 -0
- package/src/FlameGraph/FlameGraphComponent/utils.ts +31 -0
- package/src/FlameGraph/FlameGraphComponent/viewTypes.ts +6 -0
- package/src/FlameGraph/FlameGraphRenderer.tsx +603 -0
- package/src/FlameGraph/FlamegraphRenderer.module.scss +93 -0
- package/src/FlameGraph/decode.ts +78 -0
- package/src/FlameGraph/normalize.spec.ts +76 -0
- package/src/FlameGraph/normalize.ts +60 -0
- package/src/FlameGraph/testData.json +423 -0
- package/src/FlameGraph/uniqueness.spec.ts +16 -0
- package/src/FlameGraph/uniqueness.ts +84 -0
- package/src/FlamegraphRenderer.tsx +61 -0
- package/src/Icons.tsx +74 -0
- package/src/ProfilerTable.tsx +527 -0
- package/src/SharedQueryInput.module.scss +82 -0
- package/src/SharedQueryInput.tsx +127 -0
- package/src/Toolbar.module.scss +117 -0
- package/src/Toolbar.spec.tsx +217 -0
- package/src/Toolbar.tsx +471 -0
- package/src/Tooltip/FlamegraphTooltip.spec.tsx +81 -0
- package/src/Tooltip/FlamegraphTooltip.tsx +257 -0
- package/src/Tooltip/LeftClickIcon.tsx +18 -0
- package/src/Tooltip/RightClickIcon.tsx +18 -0
- package/src/Tooltip/TableTooltip.spec.tsx +44 -0
- package/src/Tooltip/TableTooltip.tsx +145 -0
- package/src/Tooltip/Tooltip.module.scss +71 -0
- package/src/Tooltip/Tooltip.spec.tsx +395 -0
- package/src/Tooltip/Tooltip.tsx +336 -0
- package/src/__snapshots__/Toolbar.spec.tsx.snap +297 -0
- package/src/convert/convertJaegerTraceToProfile.ts +97 -0
- package/src/convert/diffTwoProfiles.ts +81 -0
- package/src/convert/flamebearersToTree.ts +78 -0
- package/src/convert/sandwichViewProfiles.spec.ts +65 -0
- package/src/convert/sandwichViewProfiles.ts +191 -0
- package/src/convert/subtract.ts +87 -0
- package/src/convert/testData.ts +145 -0
- package/src/convert/toGraphviz.ts +485 -0
- package/src/fitMode/fitMode.spec.ts +93 -0
- package/src/fitMode/fitMode.ts +122 -0
- package/src/format/format.spec.ts +291 -0
- package/src/format/format.ts +303 -0
- package/src/globals.d.ts +13 -0
- package/src/i18n.tsx +293 -0
- package/src/index.node.ts +19 -0
- package/src/index.spec.tsx +383 -0
- package/src/index.tsx +10 -0
- package/src/logo-v3-small.svg +32 -0
- package/src/models/decode.ts +45 -0
- package/src/models/flamebearer.ts +86 -0
- package/src/models/groups.ts +14 -0
- package/src/models/index.ts +7 -0
- package/src/models/profile.spec.ts +32 -0
- package/src/models/profile.ts +48 -0
- package/src/models/spyName.spec.ts +18 -0
- package/src/models/spyName.ts +32 -0
- package/src/models/trace.ts +45 -0
- package/src/models/units.spec.ts +21 -0
- package/src/models/units.ts +24 -0
- package/src/sass/_common.scss +206 -0
- package/src/sass/_css-variables.scss +201 -0
- package/src/sass/_mixins.scss +15 -0
- package/src/sass/_sanitize.scss +407 -0
- package/src/sass/_variables.scss +53 -0
- package/src/sass/flamegraph.scss +18 -0
- package/src/search.spec.ts +11 -0
- package/src/search.ts +4 -0
- package/src/shameful-any.d.ts +2 -0
- package/src/shims/Box.module.scss +57 -0
- package/src/shims/Box.tsx +105 -0
- package/src/shims/Button.module.scss +129 -0
- package/src/shims/Button.tsx +128 -0
- package/src/shims/Dropdown.module.scss +63 -0
- package/src/shims/Dropdown.tsx +96 -0
- package/src/shims/Input.module.scss +15 -0
- package/src/shims/Input.tsx +55 -0
- package/src/shims/LoadingSpinner.tsx +19 -0
- package/src/shims/Menu.tsx +9 -0
- package/src/shims/NoData.module.scss +6 -0
- package/src/shims/NoData.tsx +11 -0
- package/src/shims/Table.module.scss +82 -0
- package/src/shims/Table.spec.tsx +121 -0
- package/src/shims/Table.tsx +252 -0
- package/src/shims/Tooltip.tsx +51 -0
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
/* eslint-disable react/no-unused-state */
|
|
2
|
+
/* eslint-disable no-bitwise */
|
|
3
|
+
/* eslint-disable react/no-access-state-in-setstate */
|
|
4
|
+
/* eslint-disable react/jsx-props-no-spreading */
|
|
5
|
+
/* eslint-disable react/destructuring-assignment */
|
|
6
|
+
/* eslint-disable no-nested-ternary */
|
|
7
|
+
/* eslint-disable global-require */
|
|
8
|
+
|
|
9
|
+
import React, { Dispatch, SetStateAction, ReactNode, Component } from 'react';
|
|
10
|
+
import clsx from 'clsx';
|
|
11
|
+
import { Maybe } from 'true-myth';
|
|
12
|
+
import { createFF, Flamebearer, Profile } from '../models';
|
|
13
|
+
import NoData from '../shims/NoData';
|
|
14
|
+
|
|
15
|
+
import Graph from './FlameGraphComponent';
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
17
|
+
// @ts-ignore: let's move this to typescript some time in the future
|
|
18
|
+
import ProfilerTable from '../ProfilerTable';
|
|
19
|
+
import Toolbar, { ProfileHeaderProps } from '../Toolbar';
|
|
20
|
+
import {
|
|
21
|
+
calleesProfile,
|
|
22
|
+
callersProfile,
|
|
23
|
+
} from '../convert/sandwichViewProfiles';
|
|
24
|
+
import { DefaultPalette } from './FlameGraphComponent/colorPalette';
|
|
25
|
+
import styles from './FlamegraphRenderer.module.scss';
|
|
26
|
+
import PyroscopeLogo from '../logo-v3-small.svg';
|
|
27
|
+
import { FitModes } from '../fitMode/fitMode';
|
|
28
|
+
import { ViewTypes } from './FlameGraphComponent/viewTypes';
|
|
29
|
+
import { GraphVizPane } from './FlameGraphComponent/GraphVizPane';
|
|
30
|
+
import { isSameFlamebearer } from './uniqueness';
|
|
31
|
+
import { normalize } from './normalize';
|
|
32
|
+
|
|
33
|
+
// Refers to a node in the flamegraph
|
|
34
|
+
interface Node {
|
|
35
|
+
i: number;
|
|
36
|
+
j: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface FlamegraphRendererProps {
|
|
40
|
+
profile?: Profile;
|
|
41
|
+
|
|
42
|
+
/** in case you ONLY want to display a specific visualization mode. It will also disable the dropdown that allows you to change mode. */
|
|
43
|
+
onlyDisplay?: ViewTypes;
|
|
44
|
+
showToolbar?: boolean;
|
|
45
|
+
|
|
46
|
+
/** whether to display the panes (table and flamegraph) side by side ('horizontal') or one on top of the other ('vertical') */
|
|
47
|
+
panesOrientation?: 'horizontal' | 'vertical';
|
|
48
|
+
showPyroscopeLogo?: boolean;
|
|
49
|
+
showCredit?: boolean;
|
|
50
|
+
ExportData?: ProfileHeaderProps['ExportData'];
|
|
51
|
+
|
|
52
|
+
/** @deprecated prefer Profile */
|
|
53
|
+
flamebearer?: Flamebearer;
|
|
54
|
+
sharedQuery?: {
|
|
55
|
+
searchQuery?: string;
|
|
56
|
+
onQueryChange: Dispatch<SetStateAction<string | undefined>>;
|
|
57
|
+
syncEnabled: string | boolean;
|
|
58
|
+
toggleSync: Dispatch<SetStateAction<boolean | string>>;
|
|
59
|
+
id: string;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
children?: ReactNode;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface FlamegraphRendererState {
|
|
66
|
+
/** A dirty flamegraph refers to a flamegraph where its original state can be reset */
|
|
67
|
+
isFlamegraphDirty: boolean;
|
|
68
|
+
|
|
69
|
+
view: NonNullable<FlamegraphRendererProps['onlyDisplay']>;
|
|
70
|
+
panesOrientation: NonNullable<FlamegraphRendererProps['panesOrientation']>;
|
|
71
|
+
|
|
72
|
+
fitMode: 'HEAD' | 'TAIL';
|
|
73
|
+
flamebearer: NonNullable<FlamegraphRendererProps['flamebearer']>;
|
|
74
|
+
|
|
75
|
+
/** Query searched in the input box.
|
|
76
|
+
* It's used to filter data in the table AND highlight items in the flamegraph */
|
|
77
|
+
searchQuery: string;
|
|
78
|
+
/** Triggered when an item is clicked on the table. It overwrites the searchQuery */
|
|
79
|
+
selectedItem: Maybe<string>;
|
|
80
|
+
|
|
81
|
+
flamegraphConfigs: {
|
|
82
|
+
focusedNode: Maybe<Node>;
|
|
83
|
+
zoom: Maybe<Node>;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
palette: typeof DefaultPalette;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
class FlameGraphRenderer extends Component<
|
|
90
|
+
FlamegraphRendererProps,
|
|
91
|
+
FlamegraphRendererState
|
|
92
|
+
> {
|
|
93
|
+
resetFlamegraphState = {
|
|
94
|
+
focusedNode: Maybe.nothing<Node>(),
|
|
95
|
+
zoom: Maybe.nothing<Node>(),
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// TODO: At some point the initial state may be set via the user
|
|
99
|
+
// Eg when sharing a specific node
|
|
100
|
+
initialFlamegraphState = this.resetFlamegraphState;
|
|
101
|
+
|
|
102
|
+
// eslint-disable-next-line react/static-property-placement
|
|
103
|
+
static defaultProps = {
|
|
104
|
+
showCredit: true,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
constructor(props: FlamegraphRendererProps) {
|
|
108
|
+
super(props);
|
|
109
|
+
|
|
110
|
+
this.state = {
|
|
111
|
+
isFlamegraphDirty: false,
|
|
112
|
+
view: this.props.onlyDisplay ? this.props.onlyDisplay : 'both',
|
|
113
|
+
fitMode: 'HEAD',
|
|
114
|
+
flamebearer: normalize(props),
|
|
115
|
+
|
|
116
|
+
// Default to horizontal since it's the most common case
|
|
117
|
+
panesOrientation: props.panesOrientation
|
|
118
|
+
? props.panesOrientation
|
|
119
|
+
: 'horizontal',
|
|
120
|
+
|
|
121
|
+
// query used in the 'search' checkbox
|
|
122
|
+
searchQuery: '',
|
|
123
|
+
selectedItem: Maybe.nothing(),
|
|
124
|
+
|
|
125
|
+
flamegraphConfigs: this.initialFlamegraphState,
|
|
126
|
+
|
|
127
|
+
// TODO make this come from the redux store?
|
|
128
|
+
palette: DefaultPalette,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
componentDidUpdate(
|
|
133
|
+
prevProps: FlamegraphRendererProps,
|
|
134
|
+
prevState: FlamegraphRendererState
|
|
135
|
+
) {
|
|
136
|
+
// TODO: this is a slow operation
|
|
137
|
+
const prevFlame = normalize(prevProps);
|
|
138
|
+
const currFlame = normalize(this.props);
|
|
139
|
+
|
|
140
|
+
if (!this.isSameFlamebearer(prevFlame, currFlame)) {
|
|
141
|
+
const newConfigs = this.calcNewConfigs(prevFlame, currFlame);
|
|
142
|
+
|
|
143
|
+
// Batch these updates to not do unnecessary work
|
|
144
|
+
// eslint-disable-next-line react/no-did-update-set-state
|
|
145
|
+
this.setState({
|
|
146
|
+
flamebearer: currFlame,
|
|
147
|
+
flamegraphConfigs: {
|
|
148
|
+
...this.state.flamegraphConfigs,
|
|
149
|
+
...newConfigs,
|
|
150
|
+
},
|
|
151
|
+
selectedItem: Maybe.nothing(),
|
|
152
|
+
});
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// flamegraph configs changed
|
|
157
|
+
if (prevState.flamegraphConfigs !== this.state.flamegraphConfigs) {
|
|
158
|
+
this.updateFlamegraphDirtiness();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Calculate what should be the new configs
|
|
163
|
+
// It checks if the zoom/selectNode still points to the same node
|
|
164
|
+
// If not, it resets to the resetFlamegraphState
|
|
165
|
+
calcNewConfigs = (prevFlame: Flamebearer, currFlame: Flamebearer) => {
|
|
166
|
+
const newConfigs = this.state.flamegraphConfigs;
|
|
167
|
+
|
|
168
|
+
// This is a simple heuristic based on the name
|
|
169
|
+
// It does not account for eg recursive calls
|
|
170
|
+
const isSameNode = (f: Flamebearer, f2: Flamebearer, s: Maybe<Node>) => {
|
|
171
|
+
// TODO: don't use createFF directly
|
|
172
|
+
const getBarName = (f: Flamebearer, i: number, j: number) => {
|
|
173
|
+
return f.names[createFF(f.format).getBarName(f.levels[i], j)];
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// No node is technically the same node
|
|
177
|
+
if (s.isNothing) {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// if the bar doesn't exist, it will throw an error
|
|
182
|
+
try {
|
|
183
|
+
const sAny = s as any
|
|
184
|
+
const barName1 = getBarName(f, sAny.value.i, sAny.value.j)
|
|
185
|
+
const barName2 = getBarName(f2, sAny.value.i, sAny.value.j)
|
|
186
|
+
return barName1 === barName2;
|
|
187
|
+
} catch {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// Reset zoom
|
|
193
|
+
const currZoom = this.state.flamegraphConfigs.zoom;
|
|
194
|
+
if (!isSameNode(prevFlame, currFlame, currZoom)) {
|
|
195
|
+
newConfigs.zoom = this.resetFlamegraphState.zoom;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Reset focused node
|
|
199
|
+
const currFocusedNode = this.state.flamegraphConfigs.focusedNode;
|
|
200
|
+
if (!isSameNode(prevFlame, currFlame, currFocusedNode)) {
|
|
201
|
+
newConfigs.focusedNode = this.resetFlamegraphState.focusedNode;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return newConfigs;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
onSearchChange = (e: string) => {
|
|
208
|
+
this.setState({ searchQuery: e });
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
isSameFlamebearer = (prevFlame: Flamebearer, currFlame: Flamebearer) => {
|
|
212
|
+
return isSameFlamebearer(prevFlame, currFlame);
|
|
213
|
+
// TODO: come up with a less resource intensive operation
|
|
214
|
+
// keep in mind naive heuristics may provide bad behaviours like (https://github.com/pyroscope-io/pyroscope/issues/1192)
|
|
215
|
+
// return JSON.stringify(prevFlame) === JSON.stringify(currFlame);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
onReset = () => {
|
|
219
|
+
this.setState({
|
|
220
|
+
...this.state,
|
|
221
|
+
flamegraphConfigs: {
|
|
222
|
+
...this.state.flamegraphConfigs,
|
|
223
|
+
...this.initialFlamegraphState,
|
|
224
|
+
},
|
|
225
|
+
selectedItem: Maybe.nothing(),
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
onFlamegraphZoom = (bar: Maybe<Node>) => {
|
|
230
|
+
// zooming on the topmost bar is equivalent to resetting to the original state
|
|
231
|
+
if (bar.isJust && bar.value.i === 0 && bar.value.j === 0) {
|
|
232
|
+
this.onReset();
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// otherwise just pass it up to the state
|
|
237
|
+
// doesn't matter if it's some or none
|
|
238
|
+
this.setState({
|
|
239
|
+
...this.state,
|
|
240
|
+
flamegraphConfigs: {
|
|
241
|
+
...this.state.flamegraphConfigs,
|
|
242
|
+
zoom: bar,
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
onFocusOnNode = (i: number, j: number) => {
|
|
248
|
+
if (i === 0 && j === 0) {
|
|
249
|
+
this.onReset();
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
let flamegraphConfigs = { ...this.state.flamegraphConfigs };
|
|
254
|
+
|
|
255
|
+
// reset zoom if we are focusing below the zoom
|
|
256
|
+
// or the same one we were zoomed
|
|
257
|
+
const { zoom } = this.state.flamegraphConfigs;
|
|
258
|
+
if (zoom.isJust) {
|
|
259
|
+
if (zoom.value.i <= i) {
|
|
260
|
+
flamegraphConfigs = {
|
|
261
|
+
...flamegraphConfigs,
|
|
262
|
+
zoom: this.initialFlamegraphState.zoom,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
this.setState({
|
|
268
|
+
...this.state,
|
|
269
|
+
flamegraphConfigs: {
|
|
270
|
+
...flamegraphConfigs,
|
|
271
|
+
focusedNode: Maybe.just({ i, j }),
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
setActiveItem = (item: { name: string }) => {
|
|
277
|
+
const { name } = item;
|
|
278
|
+
|
|
279
|
+
// if clicking on the same item, undo the search
|
|
280
|
+
if (this.state.selectedItem.isJust) {
|
|
281
|
+
if (name === this.state.selectedItem.value) {
|
|
282
|
+
this.setState({
|
|
283
|
+
selectedItem: Maybe.nothing(),
|
|
284
|
+
});
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// clicking for the first time
|
|
290
|
+
this.setState({
|
|
291
|
+
selectedItem: Maybe.just(name),
|
|
292
|
+
});
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
getHighlightQuery = () => {
|
|
296
|
+
// prefer table selected
|
|
297
|
+
if (this.state.selectedItem.isJust) {
|
|
298
|
+
return this.state.selectedItem.value;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return this.state.searchQuery;
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
updateView = (newView: ViewTypes) => {
|
|
305
|
+
if (newView === 'sandwich') {
|
|
306
|
+
this.setState({
|
|
307
|
+
searchQuery: '',
|
|
308
|
+
flamegraphConfigs: this.resetFlamegraphState,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
this.setState({
|
|
313
|
+
view: newView,
|
|
314
|
+
});
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
updateFlamegraphDirtiness = () => {
|
|
318
|
+
// TODO(eh-am): find a better approach
|
|
319
|
+
const isDirty = this.isDirty();
|
|
320
|
+
|
|
321
|
+
this.setState({
|
|
322
|
+
isFlamegraphDirty: isDirty,
|
|
323
|
+
});
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
updateFitMode = (newFitMode: FitModes) => {
|
|
327
|
+
this.setState({
|
|
328
|
+
fitMode: newFitMode,
|
|
329
|
+
});
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
// used as a variable instead of keeping in the state
|
|
333
|
+
// so that the flamegraph doesn't rerender unnecessarily
|
|
334
|
+
isDirty = () => {
|
|
335
|
+
return (
|
|
336
|
+
this.state.selectedItem.isJust ||
|
|
337
|
+
JSON.stringify(this.initialFlamegraphState) !==
|
|
338
|
+
JSON.stringify(this.state.flamegraphConfigs)
|
|
339
|
+
);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
shouldShowToolbar() {
|
|
343
|
+
// default to true
|
|
344
|
+
return this.props.showToolbar !== undefined ? this.props.showToolbar : true;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
render = () => {
|
|
348
|
+
// This is necessary because the order switches depending on single vs comparison view
|
|
349
|
+
const tablePane = (
|
|
350
|
+
<div
|
|
351
|
+
key="table-pane"
|
|
352
|
+
className={clsx(
|
|
353
|
+
styles.tablePane,
|
|
354
|
+
this.state.panesOrientation === 'vertical'
|
|
355
|
+
? styles.vertical
|
|
356
|
+
: styles.horizontal
|
|
357
|
+
)}
|
|
358
|
+
>
|
|
359
|
+
<ProfilerTable
|
|
360
|
+
data-testid="table-view"
|
|
361
|
+
flamebearer={this.state.flamebearer}
|
|
362
|
+
fitMode={this.state.fitMode}
|
|
363
|
+
highlightQuery={this.state.searchQuery}
|
|
364
|
+
selectedItem={this.state.selectedItem}
|
|
365
|
+
handleTableItemClick={this.setActiveItem}
|
|
366
|
+
palette={this.state.palette}
|
|
367
|
+
/>
|
|
368
|
+
</div>
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
const toolbarVisible = this.shouldShowToolbar();
|
|
372
|
+
|
|
373
|
+
const flameGraphPane = (
|
|
374
|
+
<Graph
|
|
375
|
+
key="flamegraph-pane"
|
|
376
|
+
// data-testid={flamegraphDataTestId}
|
|
377
|
+
showCredit={this.props.showCredit as boolean}
|
|
378
|
+
flamebearer={this.state.flamebearer}
|
|
379
|
+
highlightQuery={this.getHighlightQuery()}
|
|
380
|
+
setActiveItem={this.setActiveItem}
|
|
381
|
+
selectedItem={this.state.selectedItem}
|
|
382
|
+
updateView={this.props.onlyDisplay ? undefined : this.updateView}
|
|
383
|
+
fitMode={this.state.fitMode}
|
|
384
|
+
updateFitMode={this.updateFitMode}
|
|
385
|
+
zoom={this.state.flamegraphConfigs.zoom}
|
|
386
|
+
focusedNode={this.state.flamegraphConfigs.focusedNode}
|
|
387
|
+
onZoom={this.onFlamegraphZoom}
|
|
388
|
+
onFocusOnNode={this.onFocusOnNode}
|
|
389
|
+
onReset={this.onReset}
|
|
390
|
+
isDirty={this.isDirty}
|
|
391
|
+
palette={this.state.palette}
|
|
392
|
+
toolbarVisible={toolbarVisible}
|
|
393
|
+
setPalette={(p) =>
|
|
394
|
+
this.setState({
|
|
395
|
+
palette: p,
|
|
396
|
+
})
|
|
397
|
+
}
|
|
398
|
+
/>
|
|
399
|
+
);
|
|
400
|
+
|
|
401
|
+
const sandwichPane = (() => {
|
|
402
|
+
if (this.state.selectedItem.isNothing) {
|
|
403
|
+
return (
|
|
404
|
+
<div className={styles.sandwichPane} key="sandwich-pane">
|
|
405
|
+
<div
|
|
406
|
+
className={clsx(
|
|
407
|
+
styles.sandwichPaneInfo,
|
|
408
|
+
this.state.panesOrientation === 'vertical'
|
|
409
|
+
? styles.vertical
|
|
410
|
+
: styles.horizontal
|
|
411
|
+
)}
|
|
412
|
+
>
|
|
413
|
+
<div className={styles.arrow} />
|
|
414
|
+
Select a function to view callers/callees sandwich view
|
|
415
|
+
</div>
|
|
416
|
+
</div>
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const callersFlamebearer = callersProfile(
|
|
421
|
+
this.state.flamebearer,
|
|
422
|
+
(this.state.selectedItem as any).value
|
|
423
|
+
);
|
|
424
|
+
const calleesFlamebearer = calleesProfile(
|
|
425
|
+
this.state.flamebearer,
|
|
426
|
+
(this.state.selectedItem as any).value
|
|
427
|
+
);
|
|
428
|
+
const sandwitchGraph = (myCustomParams: {
|
|
429
|
+
flamebearer: Flamebearer;
|
|
430
|
+
headerVisible?: boolean;
|
|
431
|
+
showSingleLevel?: boolean;
|
|
432
|
+
}) => (
|
|
433
|
+
<Graph
|
|
434
|
+
disableClick
|
|
435
|
+
showCredit={this.props.showCredit as boolean}
|
|
436
|
+
highlightQuery=""
|
|
437
|
+
setActiveItem={this.setActiveItem}
|
|
438
|
+
selectedItem={this.state.selectedItem}
|
|
439
|
+
fitMode={this.state.fitMode}
|
|
440
|
+
updateFitMode={this.updateFitMode}
|
|
441
|
+
zoom={this.state.flamegraphConfigs.zoom}
|
|
442
|
+
focusedNode={this.state.flamegraphConfigs.focusedNode}
|
|
443
|
+
onZoom={this.onFlamegraphZoom}
|
|
444
|
+
onFocusOnNode={this.onFocusOnNode}
|
|
445
|
+
onReset={this.onReset}
|
|
446
|
+
isDirty={this.isDirty}
|
|
447
|
+
palette={this.state.palette}
|
|
448
|
+
toolbarVisible={toolbarVisible}
|
|
449
|
+
setPalette={(p) =>
|
|
450
|
+
this.setState({
|
|
451
|
+
palette: p,
|
|
452
|
+
})
|
|
453
|
+
}
|
|
454
|
+
{...myCustomParams}
|
|
455
|
+
/>
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
return (
|
|
459
|
+
<div className={styles.sandwichPane} key="sandwich-pane">
|
|
460
|
+
<div className={styles.sandwichTop}>
|
|
461
|
+
<span className={styles.name}>Callers</span>
|
|
462
|
+
{/* todo(dogfrogfog): to allow left/right click on the node we should
|
|
463
|
+
store Graph component we clicking and append action only on to
|
|
464
|
+
this component
|
|
465
|
+
will be implemented i nnext PR */}
|
|
466
|
+
{sandwitchGraph({ flamebearer: callersFlamebearer })}
|
|
467
|
+
</div>
|
|
468
|
+
<div className={styles.sandwichBottom}>
|
|
469
|
+
<span className={styles.name}>Callees</span>
|
|
470
|
+
{sandwitchGraph({
|
|
471
|
+
flamebearer: calleesFlamebearer,
|
|
472
|
+
headerVisible: false,
|
|
473
|
+
showSingleLevel: true,
|
|
474
|
+
})}
|
|
475
|
+
</div>
|
|
476
|
+
</div>
|
|
477
|
+
);
|
|
478
|
+
})();
|
|
479
|
+
|
|
480
|
+
// export type Flamebearer = {
|
|
481
|
+
// /**
|
|
482
|
+
// * List of names
|
|
483
|
+
// */
|
|
484
|
+
// names: string[];
|
|
485
|
+
// /**
|
|
486
|
+
// * List of level
|
|
487
|
+
// *
|
|
488
|
+
// * This is NOT the same as in the flamebearer
|
|
489
|
+
// * that we receive from the server.
|
|
490
|
+
// * As in there are some transformations required
|
|
491
|
+
// * (see deltaDiffWrapper)
|
|
492
|
+
// */
|
|
493
|
+
// levels: number[][];
|
|
494
|
+
// numTicks: number;
|
|
495
|
+
// maxSelf: number;
|
|
496
|
+
|
|
497
|
+
// /**
|
|
498
|
+
// * Sample Rate, used in text information
|
|
499
|
+
// */
|
|
500
|
+
// sampleRate: number;
|
|
501
|
+
// units: Units;
|
|
502
|
+
|
|
503
|
+
// spyName: SpyName;
|
|
504
|
+
// // format: 'double' | 'single';
|
|
505
|
+
// // leftTicks?: number;
|
|
506
|
+
// // rightTicks?: number;
|
|
507
|
+
// } & addTicks;
|
|
508
|
+
|
|
509
|
+
const dataUnavailable =
|
|
510
|
+
!this.state.flamebearer || this.state.flamebearer.names.length <= 1;
|
|
511
|
+
const panes = decidePanesOrder(
|
|
512
|
+
this.state.view,
|
|
513
|
+
flameGraphPane,
|
|
514
|
+
tablePane,
|
|
515
|
+
sandwichPane,
|
|
516
|
+
<GraphVizPane flamebearer={this.state.flamebearer} />
|
|
517
|
+
);
|
|
518
|
+
|
|
519
|
+
return (
|
|
520
|
+
<div>
|
|
521
|
+
<div>
|
|
522
|
+
{toolbarVisible && (
|
|
523
|
+
<Toolbar
|
|
524
|
+
sharedQuery={this.props.sharedQuery}
|
|
525
|
+
enableChangingDisplay={!this.props.onlyDisplay}
|
|
526
|
+
flamegraphType={this.state.flamebearer.format}
|
|
527
|
+
view={this.state.view}
|
|
528
|
+
handleSearchChange={this.onSearchChange}
|
|
529
|
+
reset={this.onReset}
|
|
530
|
+
updateView={this.updateView}
|
|
531
|
+
updateFitMode={this.updateFitMode}
|
|
532
|
+
fitMode={this.state.fitMode}
|
|
533
|
+
isFlamegraphDirty={this.isDirty()}
|
|
534
|
+
selectedNode={this.state.flamegraphConfigs.zoom}
|
|
535
|
+
highlightQuery={this.state.searchQuery}
|
|
536
|
+
onFocusOnSubtree={this.onFocusOnNode}
|
|
537
|
+
ExportData={this.props.ExportData}
|
|
538
|
+
/>
|
|
539
|
+
)}
|
|
540
|
+
{this.props.children}
|
|
541
|
+
<div
|
|
542
|
+
className={`${styles.flamegraphContainer} ${clsx(
|
|
543
|
+
this.state.panesOrientation === 'vertical'
|
|
544
|
+
? styles.vertical
|
|
545
|
+
: styles.horizontal,
|
|
546
|
+
styles[this.state.panesOrientation],
|
|
547
|
+
styles.panesWrapper
|
|
548
|
+
)}`}
|
|
549
|
+
>
|
|
550
|
+
{dataUnavailable ? <NoData /> : panes.map((pane) => pane)}
|
|
551
|
+
</div>
|
|
552
|
+
</div>
|
|
553
|
+
|
|
554
|
+
{this.props.showPyroscopeLogo && (
|
|
555
|
+
<div className={styles.createdBy}>
|
|
556
|
+
Created by
|
|
557
|
+
<a
|
|
558
|
+
href="https://twitter.com/PyroscopeIO"
|
|
559
|
+
rel="noreferrer"
|
|
560
|
+
target="_blank"
|
|
561
|
+
>
|
|
562
|
+
<PyroscopeLogo width="30" height="30" />
|
|
563
|
+
@PyroscopeIO
|
|
564
|
+
</a>
|
|
565
|
+
</div>
|
|
566
|
+
)}
|
|
567
|
+
</div>
|
|
568
|
+
);
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
function decidePanesOrder(
|
|
573
|
+
view: FlamegraphRendererState['view'],
|
|
574
|
+
flamegraphPane: JSX.Element | null,
|
|
575
|
+
tablePane: JSX.Element,
|
|
576
|
+
sandwichPane: JSX.Element,
|
|
577
|
+
graphvizPane: JSX.Element
|
|
578
|
+
) {
|
|
579
|
+
switch (view) {
|
|
580
|
+
case 'table': {
|
|
581
|
+
return [tablePane];
|
|
582
|
+
}
|
|
583
|
+
case 'flamegraph': {
|
|
584
|
+
return [flamegraphPane];
|
|
585
|
+
}
|
|
586
|
+
case 'sandwich': {
|
|
587
|
+
return [tablePane, sandwichPane];
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
case 'both': {
|
|
591
|
+
return [tablePane, flamegraphPane];
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
case 'graphviz': {
|
|
595
|
+
return [graphvizPane];
|
|
596
|
+
}
|
|
597
|
+
default: {
|
|
598
|
+
throw new Error(`Invalid view '${view}'`);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
export default FlameGraphRenderer;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
.flamegraphContainer {
|
|
2
|
+
width: 100%;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/* We take a gamble here and assume only 2 items will exist */
|
|
6
|
+
.flamegraphContainer > *:first-child {
|
|
7
|
+
margin-right: 8px;
|
|
8
|
+
}
|
|
9
|
+
.flamegraphContainer > *:nth-child(2) {
|
|
10
|
+
margin-left: 8px;
|
|
11
|
+
/* width: 50%; */
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.createdBy {
|
|
15
|
+
color: white;
|
|
16
|
+
text-align: center;
|
|
17
|
+
margin: 10px 0;
|
|
18
|
+
}
|
|
19
|
+
.createdBy a {
|
|
20
|
+
color: #199bef !important;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.horizontal {
|
|
24
|
+
flex-direction: row;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.vertical {
|
|
28
|
+
/* reverse, since by default the table is on the left in the DOM */
|
|
29
|
+
flex-direction: column-reverse;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.panesWrapper {
|
|
33
|
+
display: flex;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.tablePane,
|
|
37
|
+
.sandwichPane {
|
|
38
|
+
flex: 1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.sandwichPane {
|
|
42
|
+
.sandwichPaneInfo {
|
|
43
|
+
display: inline-block;
|
|
44
|
+
position: relative;
|
|
45
|
+
margin: 30px 0 0 10px;
|
|
46
|
+
padding: 8px;
|
|
47
|
+
border-radius: 5px;
|
|
48
|
+
background-color: var(--ps-sandwich-pane-info-bg);
|
|
49
|
+
color: var(--ps-neutral-1);
|
|
50
|
+
|
|
51
|
+
&.vertical {
|
|
52
|
+
margin: 30px 0;
|
|
53
|
+
|
|
54
|
+
.arrow {
|
|
55
|
+
top: initial;
|
|
56
|
+
bottom: -15px;
|
|
57
|
+
left: 20px;
|
|
58
|
+
transform: rotate(-90deg);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.arrow {
|
|
63
|
+
position: absolute;
|
|
64
|
+
top: 14px;
|
|
65
|
+
left: -20px;
|
|
66
|
+
width: 0;
|
|
67
|
+
height: 0;
|
|
68
|
+
border-style: solid;
|
|
69
|
+
border-width: 8px 20px 8px 0;
|
|
70
|
+
border-color: transparent var(--ps-sandwich-pane-info-bg) transparent
|
|
71
|
+
transparent;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.sandwichTop {
|
|
76
|
+
margin-bottom: 10px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.sandwichTop,
|
|
80
|
+
.sandwichBottom {
|
|
81
|
+
display: flex;
|
|
82
|
+
|
|
83
|
+
.name {
|
|
84
|
+
writing-mode: vertical-rl;
|
|
85
|
+
transform: rotate(-180deg);
|
|
86
|
+
padding: 5px 0;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.sandwichBottom span {
|
|
91
|
+
text-align: right;
|
|
92
|
+
}
|
|
93
|
+
}
|