@grafana/flamegraph
Version:
Grafana flamegraph visualization component
1 lines • 20.3 kB
Source Map (JSON)
{"version":3,"file":"FlameGraphTopTableContainer.mjs","sources":["../../../src/TopTable/FlameGraphTopTableContainer.tsx"],"sourcesContent":["import { css } from '@emotion/css';\nimport { memo, useMemo, useState } from 'react';\nimport AutoSizer from 'react-virtualized-auto-sizer';\n\nimport {\n applyFieldOverrides,\n DataFrame,\n DataLinkClickEvent,\n Field,\n FieldType,\n GrafanaTheme2,\n MappingType,\n} from '@grafana/data';\nimport {\n IconButton,\n Table,\n TableCellDisplayMode,\n TableCustomCellOptions,\n TableFieldOptions,\n TableSortByFieldState,\n useStyles2,\n useTheme2,\n} from '@grafana/ui';\n\nimport { diffColorBlindColors, diffDefaultColors } from '../FlameGraph/colors';\nimport { FlameGraphDataContainer } from '../FlameGraph/dataTransform';\nimport { TOP_TABLE_COLUMN_WIDTH } from '../constants';\nimport { ColorScheme, ColorSchemeDiff, TableData } from '../types';\n\ntype Props = {\n data: FlameGraphDataContainer;\n onSymbolClick: (symbol: string) => void;\n // This is used for highlighting the search button in case there is exact match.\n search?: string;\n // We use these to filter out rows in the table if users is doing text search.\n matchedLabels?: Set<string>;\n sandwichItem?: string;\n onSearch: (str: string) => void;\n onSandwich: (str?: string) => void;\n onTableSort?: (sort: string) => void;\n colorScheme: ColorScheme | ColorSchemeDiff;\n};\n\nconst FlameGraphTopTableContainer = memo(\n ({\n data,\n onSymbolClick,\n search,\n matchedLabels,\n onSearch,\n sandwichItem,\n onSandwich,\n onTableSort,\n colorScheme,\n }: Props) => {\n const table = useMemo(() => {\n // Group the data by label, we show only one row per label and sum the values\n // TODO: should be by filename + funcName + linenumber?\n let filteredTable: { [key: string]: TableData } = {};\n for (let i = 0; i < data.data.length; i++) {\n const value = data.getValue(i);\n const valueRight = data.getValueRight(i);\n const self = data.getSelf(i);\n const label = data.getLabel(i);\n\n // If user is doing text search we filter out labels in the same way we highlight them in flame graph.\n if (!matchedLabels || matchedLabels.has(label)) {\n filteredTable[label] = filteredTable[label] || {};\n filteredTable[label].self = filteredTable[label].self ? filteredTable[label].self + self : self;\n filteredTable[label].total = filteredTable[label].total ? filteredTable[label].total + value : value;\n filteredTable[label].totalRight = filteredTable[label].totalRight\n ? filteredTable[label].totalRight + valueRight\n : valueRight;\n }\n }\n return filteredTable;\n }, [data, matchedLabels]);\n\n const styles = useStyles2(getStyles);\n const theme = useTheme2();\n\n const [sort, setSort] = useState<TableSortByFieldState[]>([{ displayName: 'Self', desc: true }]);\n\n return (\n <div className={styles.topTableContainer} data-testid=\"topTable\">\n <AutoSizer style={{ width: '100%' }}>\n {({ width, height }) => {\n if (width < 3 || height < 3) {\n return null;\n }\n\n const frame = buildTableDataFrame(\n data,\n table,\n width,\n onSymbolClick,\n onSearch,\n onSandwich,\n theme,\n colorScheme,\n search,\n sandwichItem\n );\n return (\n <Table\n initialSortBy={sort}\n onSortByChange={(s) => {\n if (s && s.length) {\n onTableSort?.(s[0].displayName + '_' + (s[0].desc ? 'desc' : 'asc'));\n }\n setSort(s);\n }}\n data={frame}\n width={width}\n height={height}\n />\n );\n }}\n </AutoSizer>\n </div>\n );\n }\n);\n\nFlameGraphTopTableContainer.displayName = 'FlameGraphTopTableContainer';\n\nfunction buildTableDataFrame(\n data: FlameGraphDataContainer,\n table: { [key: string]: TableData },\n width: number,\n onSymbolClick: (str: string) => void,\n onSearch: (str: string) => void,\n onSandwich: (str?: string) => void,\n theme: GrafanaTheme2,\n colorScheme: ColorScheme | ColorSchemeDiff,\n search?: string,\n sandwichItem?: string\n): DataFrame {\n const actionField: Field = createActionField(onSandwich, onSearch, search, sandwichItem);\n\n const symbolField: Field = {\n type: FieldType.string,\n name: 'Symbol',\n values: [],\n config: {\n custom: { width: width - actionColumnWidth - TOP_TABLE_COLUMN_WIDTH * 2 },\n links: [\n {\n title: 'Highlight symbol',\n url: '',\n onClick: (e: DataLinkClickEvent) => {\n const field: Field = e.origin.field;\n const value = field.values[e.origin.rowIndex];\n onSymbolClick(value);\n },\n },\n ],\n },\n };\n\n let frame;\n\n if (data.isDiffFlamegraph()) {\n symbolField.config.custom.width = width - actionColumnWidth - TOP_TABLE_COLUMN_WIDTH * 3;\n\n const baselineField = createNumberField('Baseline', 'percent');\n const comparisonField = createNumberField('Comparison', 'percent');\n const diffField = createNumberField('Diff', 'percent');\n diffField.config.custom.cellOptions.type = TableCellDisplayMode.ColorText;\n\n const [removeColor, addColor] =\n colorScheme === ColorSchemeDiff.DiffColorBlind\n ? [diffColorBlindColors[0], diffColorBlindColors[2]]\n : [diffDefaultColors[0], diffDefaultColors[2]];\n\n diffField.config.mappings = [\n { type: MappingType.ValueToText, options: { [Infinity]: { text: 'new', color: addColor } } },\n { type: MappingType.ValueToText, options: { [-100]: { text: 'removed', color: removeColor } } },\n { type: MappingType.RangeToText, options: { from: 0, to: Infinity, result: { color: addColor } } },\n { type: MappingType.RangeToText, options: { from: -Infinity, to: 0, result: { color: removeColor } } },\n ];\n\n // For this we don't really consider sandwich view even though you can switch it on.\n const levels = data.getLevels();\n const totalTicks = levels.length ? levels[0][0].value : 0;\n const totalTicksRight = levels.length ? levels[0][0].valueRight : undefined;\n\n for (let key in table) {\n actionField.values.push(null);\n symbolField.values.push(key);\n\n const ticksLeft = table[key].total;\n const ticksRight = table[key].totalRight;\n\n // We are iterating over table of the data so totalTicksRight needs to be defined\n const totalTicksLeft = totalTicks - totalTicksRight!;\n\n const percentageLeft = Math.round((10000 * ticksLeft) / totalTicksLeft) / 100;\n const percentageRight = Math.round((10000 * ticksRight) / totalTicksRight!) / 100;\n\n const diff = ((percentageRight - percentageLeft) / percentageLeft) * 100;\n\n diffField.values.push(diff);\n baselineField.values.push(percentageLeft);\n comparisonField.values.push(percentageRight);\n }\n\n frame = {\n fields: [actionField, symbolField, baselineField, comparisonField, diffField],\n length: symbolField.values.length,\n };\n } else {\n const selfField = createNumberField('Self', data.selfField.config.unit);\n const totalField = createNumberField('Total', data.valueField.config.unit);\n\n for (let key in table) {\n actionField.values.push(null);\n symbolField.values.push(key);\n selfField.values.push(table[key].self);\n totalField.values.push(table[key].total);\n }\n\n frame = { fields: [actionField, symbolField, selfField, totalField], length: symbolField.values.length };\n }\n\n const dataFrames = applyFieldOverrides({\n data: [frame],\n fieldConfig: {\n defaults: {},\n overrides: [],\n },\n replaceVariables: (value: string) => value,\n theme,\n });\n\n return dataFrames[0];\n}\n\nfunction createNumberField(name: string, unit?: string): Field {\n const tableFieldOptions: TableFieldOptions = {\n width: TOP_TABLE_COLUMN_WIDTH,\n align: 'auto',\n inspect: false,\n cellOptions: { type: TableCellDisplayMode.Auto },\n };\n\n return {\n type: FieldType.number,\n name,\n values: [],\n config: {\n unit,\n custom: tableFieldOptions,\n },\n };\n}\n\nconst actionColumnWidth = 61;\n\nfunction createActionField(\n onSandwich: (str?: string) => void,\n onSearch: (str: string) => void,\n search?: string,\n sandwichItem?: string\n): Field {\n const options: TableCustomCellOptions = {\n type: TableCellDisplayMode.Custom,\n cellComponent: (props) => {\n return (\n <ActionCell\n frame={props.frame}\n onSandwich={onSandwich}\n onSearch={onSearch}\n search={search}\n sandwichItem={sandwichItem}\n rowIndex={props.rowIndex}\n />\n );\n },\n };\n\n const actionFieldTableConfig: TableFieldOptions = {\n filterable: false,\n width: actionColumnWidth,\n hideHeader: true,\n inspect: false,\n align: 'auto',\n cellOptions: options,\n };\n\n return {\n type: FieldType.number,\n name: 'actions',\n values: [],\n config: {\n custom: actionFieldTableConfig,\n },\n };\n}\n\ntype ActionCellProps = {\n frame: DataFrame;\n rowIndex: number;\n search?: string;\n sandwichItem?: string;\n onSearch: (symbol: string) => void;\n onSandwich: (symbol: string) => void;\n};\n\nfunction ActionCell(props: ActionCellProps) {\n const styles = getStylesActionCell();\n const symbol = props.frame.fields.find((f: Field) => f.name === 'Symbol')?.values[props.rowIndex];\n const isSearched = props.search === symbol;\n const isSandwiched = props.sandwichItem === symbol;\n\n return (\n <div className={styles.actionCellWrapper}>\n <IconButton\n className={styles.actionCellButton}\n name={'search'}\n variant={isSearched ? 'primary' : 'secondary'}\n tooltip={isSearched ? 'Clear from search' : 'Search for symbol'}\n aria-label={isSearched ? 'Clear from search' : 'Search for symbol'}\n onClick={() => {\n props.onSearch(isSearched ? '' : symbol);\n }}\n />\n <IconButton\n className={styles.actionCellButton}\n name={'gf-show-context'}\n tooltip={isSandwiched ? 'Remove from sandwich view' : 'Show in sandwich view'}\n variant={isSandwiched ? 'primary' : 'secondary'}\n aria-label={isSandwiched ? 'Remove from sandwich view' : 'Show in sandwich view'}\n onClick={() => {\n props.onSandwich(isSandwiched ? undefined : symbol);\n }}\n />\n </div>\n );\n}\n\nconst getStyles = (theme: GrafanaTheme2) => {\n return {\n topTableContainer: css({\n label: 'topTableContainer',\n padding: theme.spacing(1),\n backgroundColor: theme.colors.background.secondary,\n height: '100%',\n }),\n };\n};\n\nconst getStylesActionCell = () => {\n return {\n actionCellWrapper: css({\n label: 'actionCellWrapper',\n display: 'flex',\n height: '24px',\n }),\n actionCellButton: css({\n label: 'actionCellButton',\n marginRight: 0,\n width: '24px',\n }),\n };\n};\n\nexport default FlameGraphTopTableContainer;\n"],"names":[],"mappings":"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"}