import {Fragment, useMemo} from 'react'; import styled from '@emotion/styled'; import color from 'color'; import DateTime from 'sentry/components/dateTime'; import {Tooltip} from 'sentry/components/tooltip'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import type {Event} from 'sentry/types'; import {TraceTimelineTooltip} from 'sentry/views/issueDetails/traceTimeline/traceTimelineTooltip'; import type {TimelineEvent} from './useTraceTimelineEvents'; import {useTraceTimelineEvents} from './useTraceTimelineEvents'; import {getChunkTimeRange, getEventsByColumn} from './utils'; // Adjusting this will change the number of tooltip groups const PARENT_WIDTH = 12; // Adjusting subwidth changes how many dots to render const CHILD_WIDTH = 4; interface TraceTimelineEventsProps { event: Event; width: number; } export function TraceTimelineEvents({event, width}: TraceTimelineEventsProps) { const {startTimestamp, endTimestamp, traceEvents} = useTraceTimelineEvents({event}); let paddedStartTime = startTimestamp; let paddedEndTime = endTimestamp; // Duration is 0, pad both sides, this is how we end up with 1 dot in the middle if (endTimestamp - startTimestamp === 0) { // If the duration is 0, we need to pad the end time paddedEndTime = startTimestamp + 1500; paddedStartTime = startTimestamp - 1500; } const durationMs = paddedEndTime - paddedStartTime; const totalColumns = Math.floor(width / PARENT_WIDTH); const eventsByColumn = useMemo( () => getEventsByColumn(traceEvents, durationMs, totalColumns, paddedStartTime), [durationMs, traceEvents, totalColumns, paddedStartTime] ); const columnSize = width / totalColumns; // If the duration is less than 2 minutes, show seconds const showTimelineSeconds = durationMs < 120 * 1000; const middleTimestamp = paddedStartTime + Math.floor(durationMs / 2); const leftMiddleTimestamp = paddedStartTime + Math.floor(durationMs / 4); const rightMiddleTimestamp = paddedStartTime + Math.floor((durationMs / 4) * 3); return ( {/* Add padding to the total columns, 1 column of padding on each side */} {eventsByColumn.map(([column, colEvents]) => { // Calculate the timestamp range that this column represents const timeRange = getChunkTimeRange( paddedStartTime, column - 1, durationMs / totalColumns ); const hasCurrentEvent = colEvents.some(e => e.id === event.id); return ( ); })} ); } /** * Use grid to create columns that we can place child nodes into. * Leveraging grid for alignment means we don't need to calculate percent offset * nor use position:absolute to lay out items. * * * ... * ... * */ const TimelineColumns = styled('div')` /* Reset defaults for