@@ -295,7 +295,8 @@ function TraceView({ run, trace, maximumLiveReloadingSetting, resizable }: Loade
295295 return < > </ > ;
296296 }
297297
298- const { events, parentRunFriendlyId, duration, rootSpanStatus, rootStartedAt } = trace ;
298+ const { events, parentRunFriendlyId, duration, rootSpanStatus, rootStartedAt, queuedDuration } =
299+ trace ;
299300 const shouldLiveReload = events . length <= maximumLiveReloadingSetting ;
300301
301302 const changeToSpan = useDebounce ( ( selectedSpan : string ) => {
@@ -345,6 +346,7 @@ function TraceView({ run, trace, maximumLiveReloadingSetting, resizable }: Loade
345346 totalDuration = { duration }
346347 rootSpanStatus = { rootSpanStatus }
347348 rootStartedAt = { rootStartedAt ? new Date ( rootStartedAt ) : undefined }
349+ queuedDuration = { queuedDuration }
348350 environmentType = { run . environment . type }
349351 shouldLiveReload = { shouldLiveReload }
350352 maximumLiveReloadingSetting = { maximumLiveReloadingSetting }
@@ -472,6 +474,7 @@ type TasksTreeViewProps = {
472474 totalDuration : number ;
473475 rootSpanStatus : "executing" | "completed" | "failed" ;
474476 rootStartedAt : Date | undefined ;
477+ queuedDuration : number | undefined ;
475478 environmentType : RuntimeEnvironmentType ;
476479 shouldLiveReload : boolean ;
477480 maximumLiveReloadingSetting : number ;
@@ -491,6 +494,7 @@ function TasksTreeView({
491494 totalDuration,
492495 rootSpanStatus,
493496 rootStartedAt,
497+ queuedDuration,
494498 environmentType,
495499 shouldLiveReload,
496500 maximumLiveReloadingSetting,
@@ -502,12 +506,14 @@ function TasksTreeView({
502506 const [ errorsOnly , setErrorsOnly ] = useState ( false ) ;
503507 const [ showDebug , setShowDebug ] = useState ( false ) ;
504508 const [ showDurations , setShowDurations ] = useState ( true ) ;
509+ const [ showQueueTime , setShowQueueTime ] = useState ( false ) ;
505510 const [ scale , setScale ] = useState ( 0 ) ;
506511 const parentRef = useRef < HTMLDivElement > ( null ) ;
507512 const treeScrollRef = useRef < HTMLDivElement > ( null ) ;
508513 const timelineScrollRef = useRef < HTMLDivElement > ( null ) ;
509514
510515 const displayEvents = showDebug ? events : events . filter ( ( event ) => ! event . data . isDebug ) ;
516+ const queuedTime = showQueueTime ? undefined : queuedDuration ;
511517
512518 const {
513519 nodes,
@@ -556,6 +562,12 @@ function TasksTreeView({
556562 onCheckedChange = { ( e ) => setShowDebug ( e . valueOf ( ) ) }
557563 />
558564 ) }
565+ < Switch
566+ variant = "small"
567+ label = "Queue time"
568+ checked = { showQueueTime }
569+ onCheckedChange = { ( e ) => setShowQueueTime ( e . valueOf ( ) ) }
570+ />
559571 < Switch
560572 variant = "small"
561573 label = "Errors only"
@@ -692,6 +704,7 @@ function TasksTreeView({
692704 events = { events }
693705 rootSpanStatus = { rootSpanStatus }
694706 rootStartedAt = { rootStartedAt }
707+ queuedDuration = { queuedTime }
695708 parentRef = { parentRef }
696709 timelineScrollRef = { timelineScrollRef }
697710 nodes = { nodes }
@@ -754,7 +767,7 @@ function TasksTreeView({
754767
755768type TimelineViewProps = Pick <
756769 TasksTreeViewProps ,
757- "totalDuration" | "rootSpanStatus" | "events" | "rootStartedAt"
770+ "totalDuration" | "rootSpanStatus" | "events" | "rootStartedAt" | "queuedDuration"
758771> & {
759772 scale : number ;
760773 parentRef : React . RefObject < HTMLDivElement > ;
@@ -785,27 +798,32 @@ function TimelineView({
785798 toggleNodeSelection,
786799 showDurations,
787800 treeScrollRef,
801+ queuedDuration,
788802} : TimelineViewProps ) {
789- const isAdmin = useHasAdminAccess ( ) ;
790803 const timelineContainerRef = useRef < HTMLDivElement > ( null ) ;
791804 const initialTimelineDimensions = useInitialDimensions ( timelineContainerRef ) ;
792805 const minTimelineWidth = initialTimelineDimensions ?. width ?? 300 ;
793806 const maxTimelineWidth = minTimelineWidth * 10 ;
794807
795808 //we want to live-update the duration if the root span is still executing
796- const [ duration , setDuration ] = useState ( totalDuration ) ;
809+ const [ duration , setDuration ] = useState ( queueAdjustedNs ( totalDuration , queuedDuration ) ) ;
797810 useEffect ( ( ) => {
798811 if ( rootSpanStatus !== "executing" || ! rootStartedAt ) {
799- setDuration ( totalDuration ) ;
812+ setDuration ( queueAdjustedNs ( totalDuration , queuedDuration ) ) ;
800813 return ;
801814 }
802815
803816 const interval = setInterval ( ( ) => {
804- setDuration ( millisecondsToNanoseconds ( Date . now ( ) - rootStartedAt . getTime ( ) ) ) ;
817+ setDuration (
818+ queueAdjustedNs (
819+ millisecondsToNanoseconds ( Date . now ( ) - rootStartedAt . getTime ( ) ) ,
820+ queuedDuration
821+ )
822+ ) ;
805823 } , 500 ) ;
806824
807825 return ( ) => clearInterval ( interval ) ;
808- } , [ totalDuration , rootSpanStatus ] ) ;
826+ } , [ totalDuration , rootSpanStatus , queuedDuration , rootStartedAt ] ) ;
809827
810828 return (
811829 < div
@@ -820,7 +838,11 @@ function TimelineView({
820838 maxWidth = { maxTimelineWidth }
821839 >
822840 { /* Follows the cursor */ }
823- < CurrentTimeIndicator totalDuration = { duration } rootStartedAt = { rootStartedAt } />
841+ < CurrentTimeIndicator
842+ totalDuration = { duration }
843+ rootStartedAt = { rootStartedAt }
844+ queuedDurationNs = { queuedDuration }
845+ />
824846
825847 < Timeline . Row className = "grid h-full grid-rows-[2rem_1fr]" >
826848 { /* The duration labels */ }
@@ -941,7 +963,9 @@ function TimelineView({
941963 eventIndex === 0 ? (
942964 < Timeline . Point
943965 key = { eventIndex }
944- ms = { nanosecondsToMilliseconds ( event . offset ) }
966+ ms = { nanosecondsToMilliseconds (
967+ queueAdjustedNs ( event . offset , queuedDuration )
968+ ) }
945969 >
946970 { ( ms ) => (
947971 < motion . div
@@ -956,7 +980,9 @@ function TimelineView({
956980 ) : (
957981 < Timeline . Point
958982 key = { eventIndex }
959- ms = { nanosecondsToMilliseconds ( event . offset ) }
983+ ms = { nanosecondsToMilliseconds (
984+ queueAdjustedNs ( event . offset , queuedDuration )
985+ ) }
960986 className = "z-10"
961987 >
962988 { ( ms ) => (
@@ -975,7 +1001,9 @@ function TimelineView({
9751001 node . data . timelineEvents [ 0 ] &&
9761002 node . data . timelineEvents [ 0 ] . offset < node . data . offset ? (
9771003 < Timeline . Span
978- startMs = { nanosecondsToMilliseconds ( node . data . timelineEvents [ 0 ] . offset ) }
1004+ startMs = { nanosecondsToMilliseconds (
1005+ queueAdjustedNs ( node . data . timelineEvents [ 0 ] . offset , queuedDuration )
1006+ ) }
9791007 durationMs = { nanosecondsToMilliseconds (
9801008 node . data . offset - node . data . timelineEvents [ 0 ] . offset
9811009 ) }
@@ -988,7 +1016,9 @@ function TimelineView({
9881016 ) : null }
9891017 < SpanWithDuration
9901018 showDuration = { state . selected ? true : showDurations }
991- startMs = { nanosecondsToMilliseconds ( node . data . offset ) }
1019+ startMs = { nanosecondsToMilliseconds (
1020+ queueAdjustedNs ( node . data . offset , queuedDuration )
1021+ ) }
9921022 durationMs = {
9931023 node . data . duration
9941024 ? nanosecondsToMilliseconds ( node . data . duration )
@@ -998,7 +1028,11 @@ function TimelineView({
9981028 />
9991029 </ >
10001030 ) : (
1001- < Timeline . Point ms = { nanosecondsToMilliseconds ( node . data . offset ) } >
1031+ < Timeline . Point
1032+ ms = { nanosecondsToMilliseconds (
1033+ queueAdjustedNs ( node . data . offset , queuedDuration )
1034+ ) }
1035+ >
10021036 { ( ms ) => (
10031037 < motion . div
10041038 className = { cn (
@@ -1027,6 +1061,14 @@ function TimelineView({
10271061 ) ;
10281062}
10291063
1064+ function queueAdjustedNs ( timeNs : number , queuedDurationNs : number | undefined ) {
1065+ if ( queuedDurationNs ) {
1066+ return timeNs - queuedDurationNs ;
1067+ }
1068+
1069+ return timeNs ;
1070+ }
1071+
10301072function NodeText ( { node } : { node : TraceEvent } ) {
10311073 const className = "truncate" ;
10321074 return (
@@ -1220,9 +1262,11 @@ const edgeBoundary = 0.17;
12201262function CurrentTimeIndicator ( {
12211263 totalDuration,
12221264 rootStartedAt,
1265+ queuedDurationNs,
12231266} : {
12241267 totalDuration : number ;
12251268 rootStartedAt : Date | undefined ;
1269+ queuedDurationNs : number | undefined ;
12261270} ) {
12271271 return (
12281272 < Timeline . FollowCursor >
@@ -1235,7 +1279,11 @@ function CurrentTimeIndicator({
12351279 offset = lerp ( 0.5 , 1 , ( ratio - ( 1 - edgeBoundary ) ) / edgeBoundary ) ;
12361280 }
12371281
1238- const currentTime = rootStartedAt ? new Date ( rootStartedAt . getTime ( ) + ms ) : undefined ;
1282+ const currentTime = rootStartedAt
1283+ ? new Date (
1284+ rootStartedAt . getTime ( ) + ms + nanosecondsToMilliseconds ( queuedDurationNs ?? 0 )
1285+ )
1286+ : undefined ;
12391287 const currentTimeComponent = currentTime ? < DateTimeShort date = { currentTime } /> : < > </ > ;
12401288
12411289 return (
0 commit comments