123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- import countBy from 'lodash/countBy';
- import {ROW_HEIGHT} from 'sentry/components/performance/waterfall/constants';
- import {DurationPill, RowRectangle} from 'sentry/components/performance/waterfall/rowBar';
- import {
- ConnectorBar,
- TOGGLE_BORDER_BOX,
- TreeConnector,
- } from 'sentry/components/performance/waterfall/treeConnector';
- import {
- getDurationDisplay,
- getHumanDuration,
- toPercent,
- } from 'sentry/components/performance/waterfall/utils';
- import {t} from 'sentry/locale';
- import {EventTransaction} from 'sentry/types/event';
- import theme from 'sentry/utils/theme';
- import {SpanGroupBar} from './spanGroupBar';
- import {EnhancedSpan, ProcessedSpanType, TreeDepthType} from './types';
- import {
- getSpanGroupBounds,
- getSpanGroupTimestamps,
- getSpanOperation,
- isOrphanSpan,
- isOrphanTreeDepth,
- SpanBoundsType,
- SpanGeneratedBoundsType,
- unwrapTreeDepth,
- } from './utils';
- type Props = {
- continuingTreeDepths: Array<TreeDepthType>;
- event: Readonly<EventTransaction>;
- generateBounds: (bounds: SpanBoundsType) => SpanGeneratedBoundsType;
- generateContentSpanBarRef: () => (instance: HTMLDivElement | null) => void;
- onWheel: (deltaX: number) => void;
- span: Readonly<ProcessedSpanType>;
- spanGrouping: EnhancedSpan[];
- spanNumber: number;
- toggleSpanGroup: () => void;
- treeDepth: number;
- };
- export function SpanDescendantGroupBar(props: Props) {
- const {
- continuingTreeDepths,
- event,
- generateBounds,
- span,
- spanGrouping,
- spanNumber,
- toggleSpanGroup,
- onWheel,
- generateContentSpanBarRef,
- } = props;
- function renderGroupSpansTitle() {
- if (spanGrouping.length === 0) {
- return '';
- }
- const operationCounts = countBy(spanGrouping, enhancedSpan =>
- getSpanOperation(enhancedSpan.span)
- );
- const hasOthers = Object.keys(operationCounts).length > 1;
- const [mostFrequentOperationName] = Object.entries(operationCounts).reduce(
- (acc, [operationNameKey, count]) => {
- if (count > acc[1]) {
- return [operationNameKey, count];
- }
- return acc;
- }
- );
- return (
- <strong>{`${t('Autogrouped ')}\u2014 ${mostFrequentOperationName}${
- hasOthers ? t(' and more') : ''
- }`}</strong>
- );
- }
- function renderSpanTreeConnector() {
- const {treeDepth: spanTreeDepth} = props;
- const connectorBars: Array<React.ReactNode> = continuingTreeDepths.map(treeDepth => {
- const depth: number = unwrapTreeDepth(treeDepth);
- if (depth === 0) {
- // do not render a connector bar at depth 0,
- // if we did render a connector bar, this bar would be placed at depth -1
- // which does not exist.
- return null;
- }
- const left = ((spanTreeDepth - depth) * (TOGGLE_BORDER_BOX / 2) + 2) * -1;
- return (
- <ConnectorBar
- style={{left}}
- key={`span-group-${depth}`}
- orphanBranch={isOrphanTreeDepth(treeDepth)}
- />
- );
- });
- connectorBars.push(
- <ConnectorBar
- style={{
- right: '15px',
- height: `${ROW_HEIGHT / 2}px`,
- bottom: `-${ROW_HEIGHT / 2 + 1}px`,
- top: 'auto',
- }}
- key="collapsed-span-group-row-bottom"
- orphanBranch={false}
- />
- );
- return (
- <TreeConnector isLast hasToggler orphanBranch={isOrphanSpan(span)}>
- {connectorBars}
- </TreeConnector>
- );
- }
- function renderSpanRectangles() {
- const bounds = getSpanGroupBounds(spanGrouping, generateBounds);
- const durationDisplay = getDurationDisplay(bounds);
- const {startTimestamp, endTimestamp} = getSpanGroupTimestamps(spanGrouping);
- const duration = Math.abs(endTimestamp - startTimestamp);
- const durationString = getHumanDuration(duration);
- return (
- <RowRectangle
- spanBarHatch={false}
- style={{
- backgroundColor: theme.blue300,
- left: `min(${toPercent(bounds.left || 0)}, calc(100% - 1px))`,
- width: toPercent(bounds.width || 0),
- }}
- >
- <DurationPill
- durationDisplay={durationDisplay}
- showDetail={false}
- spanBarHatch={false}
- >
- {durationString}
- </DurationPill>
- </RowRectangle>
- );
- }
- return (
- <SpanGroupBar
- data-test-id="span-descendant-group-bar"
- event={event}
- span={span}
- spanGrouping={spanGrouping}
- treeDepth={props.treeDepth}
- spanNumber={spanNumber}
- generateBounds={generateBounds}
- toggleSpanGroup={toggleSpanGroup}
- renderSpanTreeConnector={renderSpanTreeConnector}
- renderGroupSpansTitle={renderGroupSpansTitle}
- renderSpanRectangles={renderSpanRectangles}
- onWheel={onWheel}
- generateContentSpanBarRef={generateContentSpanBarRef}
- />
- );
- }
|