mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Flamegraph: Fix rendering on contextMenu click and improve rendering perf (#64742)
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
// THIS SOFTWARE.
|
||||
import { css } from '@emotion/css';
|
||||
import uFuzzy from '@leeoniya/ufuzzy';
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useMeasure } from 'react-use';
|
||||
|
||||
import { CoreApp, createTheme, DataFrame, FieldType, getDisplayProcessor } from '@grafana/data';
|
||||
@@ -113,11 +113,11 @@ const FlameGraph = ({
|
||||
return foundLabels;
|
||||
}, [ufuzzy, search, uniqueLabels]);
|
||||
|
||||
const render = useCallback(
|
||||
(pixelsPerTick: number) => {
|
||||
useEffect(() => {
|
||||
if (!levels.length) {
|
||||
return;
|
||||
}
|
||||
const pixelsPerTick = (wrapperWidth * window.devicePixelRatio) / totalTicks / (rangeMax - rangeMin);
|
||||
const ctx = graphRef.current?.getContext('2d')!;
|
||||
const graph = graphRef.current!;
|
||||
|
||||
@@ -154,8 +154,7 @@ const FlameGraph = ({
|
||||
renderRect(ctx, rect, totalTicks, rangeMin, rangeMax, search, levelIndex, topLevelIndex, foundLabels);
|
||||
}
|
||||
}
|
||||
},
|
||||
[
|
||||
}, [
|
||||
levels,
|
||||
wrapperWidth,
|
||||
valueField,
|
||||
@@ -166,14 +165,10 @@ const FlameGraph = ({
|
||||
topLevelIndex,
|
||||
foundLabels,
|
||||
getLabelValue,
|
||||
]
|
||||
);
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (graphRef.current) {
|
||||
const pixelsPerTick = (wrapperWidth * window.devicePixelRatio) / totalTicks / (rangeMax - rangeMin);
|
||||
render(pixelsPerTick);
|
||||
|
||||
graphRef.current.onclick = (e) => {
|
||||
setTooltipData(undefined);
|
||||
const pixelsPerTick = graphRef.current!.clientWidth / totalTicks / (rangeMax - rangeMin);
|
||||
@@ -222,7 +217,6 @@ const FlameGraph = ({
|
||||
};
|
||||
}
|
||||
}, [
|
||||
render,
|
||||
levels,
|
||||
rangeMin,
|
||||
rangeMax,
|
||||
|
@@ -2,8 +2,8 @@ import { css } from '@emotion/css';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useMeasure } from 'react-use';
|
||||
|
||||
import { DataFrame, DataFrameView, CoreApp, getEnumDisplayProcessor, createTheme } from '@grafana/data';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { DataFrame, DataFrameView, CoreApp, getEnumDisplayProcessor } from '@grafana/data';
|
||||
import { useStyles2, useTheme2 } from '@grafana/ui';
|
||||
|
||||
import { MIN_WIDTH_TO_SHOW_BOTH_TOPTABLE_AND_FLAMEGRAPH, PIXELS_PER_LEVEL } from '../constants';
|
||||
|
||||
@@ -33,6 +33,8 @@ const FlameGraphContainer = (props: Props) => {
|
||||
|
||||
const labelField = props.data?.fields.find((f) => f.name === 'label');
|
||||
|
||||
const theme = useTheme2();
|
||||
|
||||
// Label can actually be an enum field so depending on that we have to access it through display processor. This is
|
||||
// both a backward compatibility but also to allow using a simple dataFrame without enum config. This would allow
|
||||
// users to use this panel with correct query from data sources that do not return profiles natively.
|
||||
@@ -40,12 +42,12 @@ const FlameGraphContainer = (props: Props) => {
|
||||
(label: string | number) => {
|
||||
const enumConfig = labelField?.config?.type?.enum;
|
||||
if (enumConfig) {
|
||||
return getEnumDisplayProcessor(createTheme(), enumConfig)(label).text;
|
||||
return getEnumDisplayProcessor(theme, enumConfig)(label).text;
|
||||
} else {
|
||||
return label.toString();
|
||||
}
|
||||
},
|
||||
[labelField]
|
||||
[labelField, theme]
|
||||
);
|
||||
|
||||
// Transform dataFrame with nested set format to array of levels. Each level contains all the bars for a particular
|
||||
|
@@ -2,8 +2,8 @@ import { css } from '@emotion/css';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
|
||||
import { CoreApp, createTheme, DataFrame, Field, FieldType, getDisplayProcessor } from '@grafana/data';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { CoreApp, DataFrame, Field, FieldType, getDisplayProcessor } from '@grafana/data';
|
||||
import { useStyles2, useTheme2 } from '@grafana/ui';
|
||||
|
||||
import { PIXELS_PER_LEVEL } from '../../constants';
|
||||
import { SampleUnit, SelectedView, TableData, TopTableData } from '../types';
|
||||
@@ -38,6 +38,7 @@ const FlameGraphTopTableContainer = ({
|
||||
getLabelValue,
|
||||
}: Props) => {
|
||||
const styles = useStyles2(() => getStyles(selectedView, app));
|
||||
const theme = useTheme2();
|
||||
const [topTable, setTopTable] = useState<TopTableData[]>();
|
||||
const valueField =
|
||||
data.fields.find((f) => f.name === 'value') ?? data.fields.find((f) => f.type === FieldType.number);
|
||||
@@ -67,8 +68,9 @@ const FlameGraphTopTableContainer = ({
|
||||
return table;
|
||||
}, [getLabelValue, selfField, valueField, labelsField]);
|
||||
|
||||
const getTopTableData = (field: Field, value: number) => {
|
||||
const processor = getDisplayProcessor({ field, theme: createTheme() /* theme does not matter for us here */ });
|
||||
const getTopTableData = useCallback(
|
||||
(field: Field, value: number) => {
|
||||
const processor = getDisplayProcessor({ field, theme });
|
||||
const displayValue = processor(value);
|
||||
let unitValue = displayValue.text + displayValue.suffix;
|
||||
|
||||
@@ -86,7 +88,9 @@ const FlameGraphTopTableContainer = ({
|
||||
}
|
||||
|
||||
return unitValue;
|
||||
};
|
||||
},
|
||||
[theme]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const table = sortLevelsIntoTable();
|
||||
@@ -104,7 +108,7 @@ const FlameGraphTopTableContainer = ({
|
||||
}
|
||||
|
||||
setTopTable(topTable);
|
||||
}, [data.fields, selfField, sortLevelsIntoTable, valueField]);
|
||||
}, [data.fields, selfField, sortLevelsIntoTable, valueField, getTopTableData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
Reference in New Issue
Block a user