github.com/grafana/pyroscope@v1.18.0/public/app/components/FlameGraphWrapper.tsx (about) 1 import React from 'react'; 2 import { createTheme } from '@grafana/data'; 3 import { FlameGraph } from '@grafana/flamegraph'; 4 import { Button, Tooltip } from '@grafana/ui'; 5 6 import useColorMode from '@pyroscope/hooks/colorMode.hook'; 7 import ExportData from '@pyroscope/components/ExportData'; 8 import type { Profile } from '@pyroscope/legacy/models'; 9 import useExportToFlamegraphDotCom from '@pyroscope/components/exportToFlamegraphDotCom.hook'; 10 11 import { isExportToFlamegraphDotComEnabled } from '@pyroscope/util/features'; 12 13 import { flamebearerToDataFrameDTO } from '@pyroscope/util/flamebearer'; 14 15 type Props = { 16 profile?: Profile; 17 dataTestId?: string; 18 vertical?: boolean; 19 timelineEl?: React.ReactNode; 20 diff?: boolean; 21 }; 22 23 export function FlameGraphWrapper(props: Props) { 24 const { colorMode } = useColorMode(); 25 const exportToFlamegraphDotComFn = useExportToFlamegraphDotCom(props.profile); 26 27 const dataFrame = props.profile 28 ? flamebearerToDataFrameDTO( 29 props.profile.flamebearer.levels, 30 props.profile.flamebearer.names, 31 props.profile.metadata.units, 32 Boolean(props.diff) 33 ) 34 : undefined; 35 36 let extraEl = <></>; 37 38 // This is a bit weird but the typing is not great. It seems like flamegraph assumed profile can be undefined 39 // but then ExportData won't work so not sure if the profile === undefined could actually happen. 40 if (props.profile) { 41 extraEl = ( 42 <ExportData 43 flamebearer={props.profile} 44 exportPNG 45 exportJSON 46 exportPprof 47 exportHTML 48 exportFlamegraphDotCom={isExportToFlamegraphDotComEnabled} 49 exportFlamegraphDotComFn={exportToFlamegraphDotComFn} 50 buttonEl={({ onClick }) => { 51 return ( 52 <Tooltip content={'Export Data'}> 53 <Button 54 // Ugly hack to go around globally defined line height messing up sizing of the button. 55 // Not sure why it happens even if everything is display: Block. To override it would 56 // need changes in Flamegraph which would be weird so this seems relatively sensible. 57 style={{ marginTop: -7 }} 58 icon={'download-alt'} 59 size={'sm'} 60 variant={'secondary'} 61 fill={'outline'} 62 onClick={onClick} 63 /> 64 </Tooltip> 65 ); 66 }} 67 /> 68 ); 69 } 70 71 return ( 72 <> 73 {props.timelineEl} 74 <FlameGraph 75 getTheme={() => createTheme({ colors: { mode: colorMode } })} 76 data={dataFrame} 77 extraHeaderElements={extraEl} 78 vertical={props.vertical} 79 disableCollapsing={true} 80 /> 81 </> 82 ); 83 }