UNPKG

@grafana/flamegraph

Version:

Grafana flamegraph visualization component

1 lines • 17.5 kB
{"version":3,"file":"FlameGraphCanvas.cjs","sources":["../../../src/FlameGraph/FlameGraphCanvas.tsx"],"sourcesContent":["import { css } from '@emotion/css';\nimport { type MouseEvent as ReactMouseEvent, useCallback, useEffect, useRef, useState } from 'react';\nimport * as React from 'react';\nimport { useMeasure } from 'react-use';\n\nimport { PIXELS_PER_LEVEL } from '../constants';\nimport {\n type ClickedItemData,\n type ColorScheme,\n type ColorSchemeDiff,\n type PaneView,\n type SelectedView,\n type ViewMode,\n type TextAlign,\n} from '../types';\n\nimport FlameGraphContextMenu, { type GetExtraContextMenuButtonsFunction } from './FlameGraphContextMenu';\nimport FlameGraphTooltip from './FlameGraphTooltip';\nimport { type CollapsedMap, type FlameGraphDataContainer, type LevelItem } from './dataTransform';\nimport { getBarX, useFlameRender } from './rendering';\n\ntype Props = {\n data: FlameGraphDataContainer;\n rangeMin: number;\n rangeMax: number;\n matchedLabels: Set<string> | undefined;\n setRangeMin: (range: number) => void;\n setRangeMax: (range: number) => void;\n style?: React.CSSProperties;\n onItemFocused: (data: ClickedItemData) => void;\n focusedItemData?: ClickedItemData;\n textAlign: TextAlign;\n onSandwich: (label: string) => void;\n colorScheme: ColorScheme | ColorSchemeDiff;\n\n root: LevelItem;\n direction: 'children' | 'parents';\n // Depth in number of levels\n depth: number;\n\n totalProfileTicks: number;\n totalProfileTicksRight?: number;\n totalViewTicks: number;\n showFlameGraphOnly?: boolean;\n\n collapsedMap: CollapsedMap;\n setCollapsedMap: (collapsedMap: CollapsedMap) => void;\n collapsing?: boolean;\n getExtraContextMenuButtons?: GetExtraContextMenuButtonsFunction;\n\n selectedView?: SelectedView;\n viewMode?: ViewMode;\n paneView?: PaneView;\n search: string;\n};\n\nconst FlameGraphCanvas = ({\n data,\n rangeMin,\n rangeMax,\n matchedLabels,\n setRangeMin,\n setRangeMax,\n onItemFocused,\n focusedItemData,\n textAlign,\n onSandwich,\n colorScheme,\n totalProfileTicks,\n totalProfileTicksRight,\n totalViewTicks,\n root,\n direction,\n depth,\n showFlameGraphOnly,\n collapsedMap,\n setCollapsedMap,\n collapsing,\n getExtraContextMenuButtons,\n selectedView,\n viewMode,\n paneView,\n search,\n}: Props) => {\n const styles = getStyles();\n\n const [sizeRef, { width: wrapperWidth }] = useMeasure<HTMLDivElement>();\n const graphRef = useRef<HTMLCanvasElement>(null);\n const [tooltipItem, setTooltipItem] = useState<LevelItem>();\n\n const [clickedItemData, setClickedItemData] = useState<ClickedItemData>();\n\n useFlameRender({\n canvasRef: graphRef,\n colorScheme,\n data,\n focusedItemData,\n root,\n direction,\n depth,\n rangeMax,\n rangeMin,\n matchedLabels,\n textAlign,\n totalViewTicks,\n // We need this so that if we have a diff profile and are in sandwich view we still show the same diff colors.\n totalColorTicks: data.isDiffFlamegraph() ? totalProfileTicks : totalViewTicks,\n totalTicksRight: totalProfileTicksRight,\n wrapperWidth,\n collapsedMap,\n });\n\n const onGraphClick = useCallback(\n (e: ReactMouseEvent<HTMLCanvasElement>) => {\n setTooltipItem(undefined);\n const pixelsPerTick = graphRef.current!.clientWidth / totalViewTicks / (rangeMax - rangeMin);\n const item = convertPixelCoordinatesToBarCoordinates(\n { x: e.nativeEvent.offsetX, y: e.nativeEvent.offsetY },\n root,\n direction,\n depth,\n pixelsPerTick,\n totalViewTicks,\n rangeMin,\n collapsedMap\n );\n\n // if clicking on a block in the canvas\n if (item) {\n setClickedItemData({\n posY: e.clientY,\n posX: e.clientX,\n item,\n label: data.getLabel(item.itemIndexes[0]),\n });\n } else {\n // if clicking on the canvas but there is no block beneath the cursor\n setClickedItemData(undefined);\n }\n },\n [data, rangeMin, rangeMax, totalViewTicks, root, direction, depth, collapsedMap]\n );\n\n const [mousePosition, setMousePosition] = useState<{ x: number; y: number }>();\n const onGraphMouseMove = useCallback(\n (e: ReactMouseEvent<HTMLCanvasElement>) => {\n if (clickedItemData === undefined) {\n setTooltipItem(undefined);\n setMousePosition(undefined);\n const pixelsPerTick = graphRef.current!.clientWidth / totalViewTicks / (rangeMax - rangeMin);\n const item = convertPixelCoordinatesToBarCoordinates(\n { x: e.nativeEvent.offsetX, y: e.nativeEvent.offsetY },\n root,\n direction,\n depth,\n pixelsPerTick,\n totalViewTicks,\n rangeMin,\n collapsedMap\n );\n\n if (item) {\n setMousePosition({ x: e.clientX, y: e.clientY });\n setTooltipItem(item);\n }\n }\n },\n [rangeMin, rangeMax, totalViewTicks, clickedItemData, setMousePosition, root, direction, depth, collapsedMap]\n );\n\n const onGraphMouseLeave = useCallback(() => {\n setTooltipItem(undefined);\n }, []);\n\n // hide context menu if outside the flame graph canvas is clicked\n useEffect(() => {\n const handleOnClick = (e: MouseEvent) => {\n if (\n e.target instanceof HTMLElement &&\n e.target.parentElement?.id !== 'flameGraphCanvasContainer_clickOutsideCheck'\n ) {\n setClickedItemData(undefined);\n }\n };\n window.addEventListener('click', handleOnClick);\n return () => window.removeEventListener('click', handleOnClick);\n }, [setClickedItemData]);\n\n return (\n <div className={styles.graph}>\n <div className={styles.canvasWrapper} id=\"flameGraphCanvasContainer_clickOutsideCheck\" ref={sizeRef}>\n <canvas\n ref={graphRef}\n data-testid=\"flameGraph\"\n onClick={onGraphClick}\n onMouseMove={onGraphMouseMove}\n onMouseLeave={onGraphMouseLeave}\n />\n </div>\n <FlameGraphTooltip\n position={mousePosition}\n item={tooltipItem}\n data={data}\n totalTicks={totalViewTicks}\n collapseConfig={tooltipItem ? collapsedMap.get(tooltipItem) : undefined}\n />\n {!showFlameGraphOnly && clickedItemData && (\n <FlameGraphContextMenu\n data={data}\n itemData={clickedItemData}\n collapsing={collapsing}\n collapseConfig={collapsedMap.get(clickedItemData.item)}\n onMenuItemClick={() => {\n setClickedItemData(undefined);\n }}\n onItemFocus={() => {\n setRangeMin(clickedItemData.item.start / totalViewTicks);\n setRangeMax((clickedItemData.item.start + clickedItemData.item.value) / totalViewTicks);\n onItemFocused(clickedItemData);\n }}\n onSandwich={() => {\n onSandwich(data.getLabel(clickedItemData.item.itemIndexes[0]));\n }}\n onExpandGroup={() => {\n setCollapsedMap(collapsedMap.setCollapsedStatus(clickedItemData.item, false));\n }}\n onCollapseGroup={() => {\n setCollapsedMap(collapsedMap.setCollapsedStatus(clickedItemData.item, true));\n }}\n onExpandAllGroups={() => {\n setCollapsedMap(collapsedMap.setAllCollapsedStatus(false));\n }}\n onCollapseAllGroups={() => {\n setCollapsedMap(collapsedMap.setAllCollapsedStatus(true));\n }}\n allGroupsCollapsed={Array.from(collapsedMap.values()).every((i) => i.collapsed)}\n allGroupsExpanded={Array.from(collapsedMap.values()).every((i) => !i.collapsed)}\n getExtraContextMenuButtons={getExtraContextMenuButtons}\n selectedView={selectedView}\n viewMode={viewMode}\n paneView={paneView}\n search={search}\n />\n )}\n </div>\n );\n};\n\nconst getStyles = () => ({\n graph: css({\n label: 'graph',\n overflow: 'auto',\n flexGrow: 1,\n flexBasis: '50%',\n }),\n canvasContainer: css({\n label: 'canvasContainer',\n display: 'flex',\n }),\n canvasWrapper: css({\n label: 'canvasWrapper',\n cursor: 'pointer',\n flex: 1,\n overflow: 'hidden',\n }),\n sandwichMarker: css({\n label: 'sandwichMarker',\n writingMode: 'vertical-lr',\n transform: 'rotate(180deg)',\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n }),\n sandwichMarkerIcon: css({\n label: 'sandwichMarkerIcon',\n verticalAlign: 'baseline',\n }),\n});\n\nexport const convertPixelCoordinatesToBarCoordinates = (\n // position relative to the start of the graph\n pos: { x: number; y: number },\n root: LevelItem,\n direction: 'children' | 'parents',\n depth: number,\n pixelsPerTick: number,\n totalTicks: number,\n rangeMin: number,\n collapsedMap: CollapsedMap\n): LevelItem | undefined => {\n let next: LevelItem | undefined = root;\n let currentLevel = direction === 'children' ? 0 : depth - 1;\n const levelIndex = Math.floor(pos.y / (PIXELS_PER_LEVEL / window.devicePixelRatio));\n let found = undefined;\n\n while (next) {\n const node: LevelItem = next;\n next = undefined;\n if (currentLevel === levelIndex) {\n found = node;\n break;\n }\n\n const nextList = direction === 'children' ? node.children : node.parents || [];\n\n for (const child of nextList) {\n const xStart = getBarX(child.start, totalTicks, rangeMin, pixelsPerTick);\n const xEnd = getBarX(child.start + child.value, totalTicks, rangeMin, pixelsPerTick);\n if (xStart <= pos.x && pos.x < xEnd) {\n next = child;\n // Check if item is a collapsed item. if so also check if the item is the first collapsed item in the chain,\n // which we render, or a child which we don't render. If it's a child in the chain then don't increase the\n // level end effectively skip it.\n const collapsedConfig = collapsedMap.get(child);\n if (!collapsedConfig || !collapsedConfig.collapsed || collapsedConfig.items[0] === child) {\n currentLevel = currentLevel + (direction === 'children' ? 1 : -1);\n }\n break;\n }\n }\n }\n\n return found;\n};\n\nexport default FlameGraphCanvas;\n"],"names":["useMeasure","useRef","useState","useFlameRender","useCallback","useEffect","jsxs","jsx","FlameGraphTooltip","css","PIXELS_PER_LEVEL","getBarX"],"mappings":"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"}