diff --git a/packages/grafana-flamegraph/src/FlameGraph/FlameGraphTooltip.tsx b/packages/grafana-flamegraph/src/FlameGraph/FlameGraphTooltip.tsx index 81422d948d0..1949d2ba08c 100644 --- a/packages/grafana-flamegraph/src/FlameGraph/FlameGraphTooltip.tsx +++ b/packages/grafana-flamegraph/src/FlameGraph/FlameGraphTooltip.tsx @@ -183,6 +183,7 @@ const getStyles = (theme: GrafanaTheme2) => ({ `, tooltipName: css` title: tooltipName; + margin-top: 0; word-break: break-all; `, lastParagraph: css` @@ -196,7 +197,7 @@ const getStyles = (theme: GrafanaTheme2) => ({ tooltipTable: css` title: tooltipTable; - max-width: 300px; + max-width: 400px; `, }); diff --git a/packages/grafana-flamegraph/src/FlameGraph/colors.ts b/packages/grafana-flamegraph/src/FlameGraph/colors.ts index 1ef5acf3a41..d2863694c43 100644 --- a/packages/grafana-flamegraph/src/FlameGraph/colors.ts +++ b/packages/grafana-flamegraph/src/FlameGraph/colors.ts @@ -77,22 +77,29 @@ export function getBarColorByDiff( totalTicksRight: number, colorScheme: ColorSchemeDiff ) { - const ticksLeft = ticks - ticksRight; - const totalTicksLeft = totalTicks - totalTicksRight; - - const percentageLeft = Math.round((10000 * ticksLeft) / totalTicksLeft) / 100; - const percentageRight = Math.round((10000 * ticksRight) / totalTicksRight) / 100; - - const diff = ((percentageRight - percentageLeft) / percentageLeft) * 100; - const range = colorScheme === ColorSchemeDiff.Default ? diffDefaultColors : diffColorBlindColors; - const colorScale = scaleLinear() .domain([-100, 0, 100]) // TODO types from DefinitelyTyped seem to mismatch // @ts-ignore .range(range); + const ticksLeft = ticks - ticksRight; + const totalTicksLeft = totalTicks - totalTicksRight; + + if (totalTicksRight === 0 || totalTicksLeft === 0) { + // TODO types from DefinitelyTyped seem to mismatch + // @ts-ignore + const rgbString: string = colorScale(0); + // Fallback to neutral color as we probably have no data for one of the sides. + return color(rgbString); + } + + const percentageLeft = Math.round((10000 * ticksLeft) / totalTicksLeft) / 100; + const percentageRight = Math.round((10000 * ticksRight) / totalTicksRight) / 100; + + const diff = ((percentageRight - percentageLeft) / percentageLeft) * 100; + // TODO types from DefinitelyTyped seem to mismatch // @ts-ignore const rgbString: string = colorScale(diff); diff --git a/packages/grafana-flamegraph/src/FlameGraph/rendering.ts b/packages/grafana-flamegraph/src/FlameGraph/rendering.ts index bc2b40eafd1..b017ddbed2b 100644 --- a/packages/grafana-flamegraph/src/FlameGraph/rendering.ts +++ b/packages/grafana-flamegraph/src/FlameGraph/rendering.ts @@ -1,8 +1,8 @@ import uFuzzy from '@leeoniya/ufuzzy'; import { RefObject, useEffect, useMemo, useState } from 'react'; +import color from 'tinycolor2'; import { GrafanaTheme2 } from '@grafana/data'; -import { colors } from '@grafana/ui'; import { BAR_BORDER_WIDTH, @@ -240,7 +240,7 @@ export function renderRect( ctx.beginPath(); ctx.rect(rect.x + (rect.collapsed ? 0 : BAR_BORDER_WIDTH), rect.y, rect.width, rect.height); - const color = + const barColor = rect.ticksRight !== undefined && (colorScheme === ColorSchemeDiff.Default || colorScheme === ColorSchemeDiff.DiffColorBlind) ? getBarColorByDiff(rect.ticks, rect.ticksRight, totalTicks, totalTicksRight!, colorScheme) @@ -248,17 +248,22 @@ export function renderRect( ? getBarColorByValue(rect.ticks, totalTicks, rangeMin, rangeMax) : getBarColorByPackage(rect.label, theme); + const barMutedColor = color(theme.colors.background.secondary); + const barMutedColorHex = theme.isLight + ? barMutedColor.darken(10).toHexString() + : barMutedColor.lighten(10).toHexString(); + if (foundNames) { // Means we are searching, we use color for matches and gray the rest - ctx.fillStyle = foundNames.has(rect.label) ? color.toHslString() : colors[55]; + ctx.fillStyle = foundNames.has(rect.label) ? barColor.toHslString() : barMutedColorHex; } else { // No search if (rect.collapsed) { // Collapsed are always grayed - ctx.fillStyle = colors[55]; + ctx.fillStyle = barMutedColorHex; } else { // Mute if we are above the focused symbol - ctx.fillStyle = levelIndex > topLevelIndex - 1 ? color.toHslString() : color.lighten(15).toHslString(); + ctx.fillStyle = levelIndex > topLevelIndex - 1 ? barColor.toHslString() : barColor.lighten(15).toHslString(); } } diff --git a/packages/grafana-flamegraph/src/FlameGraphContainer.tsx b/packages/grafana-flamegraph/src/FlameGraphContainer.tsx index f329f72e0d8..bee6c307839 100644 --- a/packages/grafana-flamegraph/src/FlameGraphContainer.tsx +++ b/packages/grafana-flamegraph/src/FlameGraphContainer.tsx @@ -245,6 +245,7 @@ function getStyles(theme: GrafanaTheme2, vertical?: boolean) { flexGrow: 1, minHeight: 0, flexDirection: vertical ? 'column-reverse' : 'row', + columnGap: theme.spacing(1), }), }; } diff --git a/packages/grafana-flamegraph/src/FlameGraphHeader.tsx b/packages/grafana-flamegraph/src/FlameGraphHeader.tsx index d2299543985..178efeb4b3e 100644 --- a/packages/grafana-flamegraph/src/FlameGraphHeader.tsx +++ b/packages/grafana-flamegraph/src/FlameGraphHeader.tsx @@ -229,9 +229,9 @@ const getStyles = (theme: GrafanaTheme2, sticky?: boolean) => ({ justify-content: space-between; width: 100%; top: 0; - z-index: ${theme.zIndex.navbarFixed}; ${sticky ? css` + z-index: ${theme.zIndex.navbarFixed}; position: sticky; padding-bottom: ${theme.spacing(1)}; padding-top: ${theme.spacing(1)}; diff --git a/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.tsx b/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.tsx index e106f052e85..51de2965308 100644 --- a/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.tsx +++ b/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.tsx @@ -73,7 +73,7 @@ const FlameGraphTopTableContainer = React.memo( // so we don't show potentially thousands of rows at once which can hinder performance (the table is virtualized // so with some max height it handles it fine) const tableHeight = vertical ? Math.min(Object.keys(table).length * rowHeight, 800) : 0; - const styles = getStyles(tableHeight); + const styles = getStyles(tableHeight, getTheme()); const [sort, setSort] = useState([{ displayName: 'Self', desc: true }]); @@ -327,13 +327,15 @@ function ActionCell(props: ActionCellProps) { ); } -const getStyles = (height: number) => { +const getStyles = (height: number, theme: GrafanaTheme2) => { return { topTableContainer: css` label: topTableContainer; flex-grow: 1; flex-basis: 50%; overflow: hidden; + padding: ${theme.spacing(1)}; + background-color: ${theme.colors.background.secondary}; ${height ? css` min-height: ${height}px;