UNPKG

@grafana/flamegraph

Version:

Grafana flamegraph visualization component

281 lines (277 loc) • 8.92 kB
'use strict'; var jsxRuntime = require('react/jsx-runtime'); var css = require('@emotion/css'); var react = require('react'); var data = require('@grafana/data'); var FlameGraphCallTreeContainer = require('./CallTree/FlameGraphCallTreeContainer.cjs'); var FlameGraph = require('./FlameGraph/FlameGraph.cjs'); var FlameGraphTopTableContainer = require('./TopTable/FlameGraphTopTableContainer.cjs'); var constants = require('./constants.cjs'); var hooks = require('./hooks.cjs'); var types = require('./types.cjs'); "use strict"; const FlameGraphPane = ({ paneView, dataContainer, search, matchedLabels, onTableSymbolClick, onTextAlignSelected, onTableSort, showFlameGraphOnly, disableCollapsing, getExtraContextMenuButtons, viewMode, paneViewForContextMenu, setSearch, resetKey, keepFocusOnDataChange, focusedItemIndexes, setFocusedItemIndexes, sharedSandwichItem, setSharedSandwichItem }) => { const [focusedItemData, setFocusedItemData] = react.useState(); const [rangeMin, setRangeMin] = react.useState(0); const [rangeMax, setRangeMax] = react.useState(1); const [textAlign, setTextAlign] = react.useState("left"); const [localSandwichItem, setLocalSandwichItem] = react.useState(); const isUsingSharedSandwich = setSharedSandwichItem !== void 0; const sandwichItem = isUsingSharedSandwich ? sharedSandwichItem : localSandwichItem; const setSandwichItem = react.useCallback( (item) => { if (isUsingSharedSandwich && setSharedSandwichItem) { setSharedSandwichItem(item); } else { setLocalSandwichItem(item); } }, [isUsingSharedSandwich, setSharedSandwichItem] ); const [collapsedMap, setCollapsedMap] = react.useState(() => dataContainer.getCollapsedMap()); const [colorScheme, setColorScheme] = hooks.useColorScheme(dataContainer); const styles = getStyles(); react.useLayoutEffect(() => { setCollapsedMap(dataContainer.getCollapsedMap()); }, [dataContainer]); react.useEffect(() => { if (resetKey !== void 0 && resetKey > 0) { setFocusedItemData(void 0); setRangeMin(0); setRangeMax(1); setLocalSandwichItem(void 0); } }, [resetKey]); react.useEffect(() => { var _a; if (!keepFocusOnDataChange) { setFocusedItemData(void 0); setRangeMin(0); setRangeMax(1); setSandwichItem(void 0); return; } if (dataContainer && focusedItemData) { const item = (_a = dataContainer.getNodesWithLabel(focusedItemData.label)) == null ? void 0 : _a[0]; if (item) { setFocusedItemData({ ...focusedItemData, item }); const levels = dataContainer.getLevels(); const totalViewTicks = levels.length ? levels[0][0].value : 0; setRangeMin(item.start / totalViewTicks); setRangeMax((item.start + item.value) / totalViewTicks); } else { setFocusedItemData({ ...focusedItemData, item: { start: 0, value: 0, itemIndexes: [], children: [], level: 0 } }); setRangeMin(0); setRangeMax(1); } } }, [dataContainer, keepFocusOnDataChange]); const weSetFocusRef = react.useRef(false); react.useEffect(() => { if (!focusedItemIndexes || focusedItemIndexes.length === 0) { return; } if (weSetFocusRef.current) { weSetFocusRef.current = false; return; } const currentIndexes = focusedItemData == null ? void 0 : focusedItemData.item.itemIndexes; if (currentIndexes && currentIndexes.length === focusedItemIndexes.length) { const matches = currentIndexes.every((val, idx) => val === focusedItemIndexes[idx]); if (matches) { return; } } const levels = dataContainer.getLevels(); for (const level of levels) { for (const item of level) { if (item.itemIndexes.length === focusedItemIndexes.length && item.itemIndexes.every((val, idx) => val === focusedItemIndexes[idx])) { const label = dataContainer.getLabel(item.itemIndexes[0]); const totalViewTicks = levels[0][0].value; setFocusedItemData({ label, item, posX: 0, posY: 0 }); setRangeMin(item.start / totalViewTicks); setRangeMax((item.start + item.value) / totalViewTicks); return; } } } }, [focusedItemIndexes, dataContainer, focusedItemData]); const resetFocus = react.useCallback(() => { setFocusedItemData(void 0); setRangeMin(0); setRangeMax(1); setFocusedItemIndexes == null ? void 0 : setFocusedItemIndexes(void 0); }, [setFocusedItemIndexes]); const resetSandwich = react.useCallback(() => { setSandwichItem(void 0); }, [setSandwichItem]); const onSymbolClick = react.useCallback( (symbol) => { const anchored = `^${data.escapeStringForRegex(symbol)}$`; if (search === anchored) { setSearch(""); } else { onTableSymbolClick == null ? void 0 : onTableSymbolClick(symbol); setSearch(anchored); resetFocus(); } }, [search, setSearch, resetFocus, onTableSymbolClick] ); const onCallTreeSymbolClick = react.useCallback( (symbol) => { onTableSymbolClick == null ? void 0 : onTableSymbolClick(symbol); }, [onTableSymbolClick] ); const onCallTreeSearch = react.useCallback( (symbol) => { const anchored = `^${data.escapeStringForRegex(symbol)}$`; if (search === anchored) { setSearch(""); } else { onTableSymbolClick == null ? void 0 : onTableSymbolClick(symbol); setSearch(anchored); resetFocus(); } }, [search, setSearch, resetFocus, onTableSymbolClick] ); const onTopTableSearch = react.useCallback( (str) => { if (!str) { setSearch(""); return; } setSearch(`^${data.escapeStringForRegex(str)}$`); }, [setSearch] ); let content; switch (paneView) { case types.PaneView.TopTable: content = /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.tableContainer, children: /* @__PURE__ */ jsxRuntime.jsx( FlameGraphTopTableContainer.default, { data: dataContainer, onSymbolClick, search, matchedLabels, sandwichItem, onSandwich: setSandwichItem, onSearch: onTopTableSearch, onTableSort, colorScheme } ) }); break; case types.PaneView.FlameGraph: default: content = /* @__PURE__ */ jsxRuntime.jsx( FlameGraph, { data: dataContainer, rangeMin, rangeMax, matchedLabels, setRangeMin, setRangeMax, onItemFocused: (data) => { setFocusedItemData(data); weSetFocusRef.current = true; setFocusedItemIndexes == null ? void 0 : setFocusedItemIndexes(data.item.itemIndexes); }, focusedItemData, textAlign, onTextAlignChange: (align) => { setTextAlign(align); onTextAlignSelected == null ? void 0 : onTextAlignSelected(align); }, sandwichItem, onSandwich: (label) => { resetFocus(); setSandwichItem(label); }, onFocusPillClick: resetFocus, onSandwichPillClick: resetSandwich, colorScheme, onColorSchemeChange: setColorScheme, isDiffMode: dataContainer.isDiffFlamegraph(), showFlameGraphOnly, collapsing: !disableCollapsing, getExtraContextMenuButtons, enableNewUI: true, viewMode, paneView: paneViewForContextMenu, search, collapsedMap, setCollapsedMap } ); break; case types.PaneView.CallTree: content = /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.tableContainer, children: /* @__PURE__ */ jsxRuntime.jsx( FlameGraphCallTreeContainer, { data: dataContainer, onSymbolClick: onCallTreeSymbolClick, sandwichItem, onSandwich: setSandwichItem, onTableSort, search, onSearch: onCallTreeSearch, focusedItemIndexes, setFocusedItemIndexes, getExtraContextMenuButtons, viewMode, paneView: paneViewForContextMenu } ) }); break; } return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.paneWrapper, children: content }); }; function getStyles() { return { paneWrapper: css.css({ width: "100%", height: "100%" }), tableContainer: css.css({ height: constants.FLAMEGRAPH_CONTAINER_HEIGHT, minWidth: 0, overflow: "hidden" }) }; } module.exports = FlameGraphPane; //# sourceMappingURL=FlameGraphPane.cjs.map