github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/packages/pyroscope-flamegraph/src/Tooltip/TableTooltip.tsx (about)

     1  import React, { useCallback, RefObject, Dispatch, SetStateAction } from 'react';
     2  import { Units } from '@pyroscope/models/src/units';
     3  
     4  import type { FlamegraphPalette } from '../FlameGraph/FlameGraphComponent/colorPalette';
     5  import { Tooltip, TooltipData } from './Tooltip';
     6  import { formatDouble } from './FlamegraphTooltip';
     7  import { getFormatter } from '../format/format';
     8  
     9  export interface TableTooltipProps {
    10    tableBodyRef: RefObject<HTMLTableSectionElement>;
    11    numTicks: number;
    12    sampleRate: number;
    13    units: Units;
    14    palette: FlamegraphPalette;
    15  }
    16  
    17  export default function TableTooltip({
    18    numTicks,
    19    sampleRate,
    20    units,
    21    tableBodyRef,
    22    palette,
    23  }: TableTooltipProps) {
    24    const formatter = getFormatter(numTicks, sampleRate, units);
    25    const totalFlamebearer = formatter.format(numTicks, sampleRate);
    26  
    27    const setTooltipContent = useCallback(
    28      (
    29        setContent: Dispatch<
    30          SetStateAction<{
    31            title: {
    32              text: string;
    33              diff: {
    34                text: string;
    35                color: string;
    36              };
    37            };
    38            tooltipData: TooltipData[];
    39          }>
    40        >,
    41        onMouseOut: () => void,
    42        e: MouseEvent
    43      ) => {
    44        const tableRowElementData = (e.target as Element).closest('tr')?.dataset
    45          .row;
    46  
    47        if (!tableRowElementData) {
    48          onMouseOut();
    49          return;
    50        }
    51        const [format, functionName, ...rowValues] =
    52          tableRowElementData.split(';');
    53  
    54        switch (format) {
    55          case 'single': {
    56            const [self, total] = rowValues;
    57            const selfFormatted = formatter.format(
    58              parseInt(self, 10),
    59              sampleRate
    60            );
    61            const totalFormated = formatter.format(
    62              parseInt(total, 10),
    63              sampleRate
    64            );
    65            // todo: i think it will be good to decrease number of calculations here
    66            const totalFlamebearerSplitted = totalFlamebearer.split(' ');
    67            const totalFlamebearerNoUnitsValue =
    68              totalFlamebearerSplitted[0] === '<'
    69                ? totalFlamebearerSplitted[1]
    70                : totalFlamebearerSplitted[0];
    71  
    72            const selfSplitted = selfFormatted.split(' ');
    73            const selfNoUnitsValue =
    74              selfSplitted[0] === '<' ? selfSplitted[1] : selfSplitted[0];
    75  
    76            const totalSplitted = totalFormated.split(' ');
    77            const totalNoUnitsValue =
    78              totalSplitted[0] === '<' ? totalSplitted[1] : totalSplitted[0];
    79  
    80            const newContent: TooltipData = {
    81              units,
    82              self: `${selfFormatted}(${(
    83                (parseFloat(selfNoUnitsValue) /
    84                  parseFloat(totalFlamebearerNoUnitsValue)) *
    85                100
    86              ).toFixed(2)}%)`,
    87              total: `${totalFormated}(${(
    88                (parseFloat(totalNoUnitsValue) /
    89                  parseFloat(totalFlamebearerNoUnitsValue)) *
    90                100
    91              ).toFixed(2)}%)`,
    92              tooltipType: 'table',
    93            };
    94  
    95            setContent({
    96              title: {
    97                text: functionName,
    98                diff: {
    99                  text: '',
   100                  color: '',
   101                },
   102              },
   103              tooltipData: [newContent],
   104            });
   105            break;
   106          }
   107          case 'double': {
   108            const [totalLeft, leftTicks, totalRight, rightTicks] = rowValues;
   109            const d = formatDouble(
   110              {
   111                formatter,
   112                sampleRate,
   113                totalLeft: parseInt(totalLeft, 10),
   114                leftTicks: parseInt(leftTicks, 10),
   115                totalRight: parseInt(totalRight, 10),
   116                rightTicks: parseInt(rightTicks, 10),
   117                title: functionName,
   118                units,
   119              },
   120              palette
   121            );
   122  
   123            setContent({
   124              title: d.title,
   125              tooltipData: d.tooltipData,
   126            });
   127  
   128            break;
   129          }
   130          default:
   131            break;
   132        }
   133      },
   134      [tableBodyRef, numTicks, formatter, sampleRate]
   135    );
   136  
   137    return (
   138      <Tooltip
   139        dataSourceRef={tableBodyRef}
   140        shouldShowTitle={false}
   141        clickInfoSide="left"
   142        setTooltipContent={setTooltipContent}
   143      />
   144    );
   145  }