@@ -14,6 +14,7 @@ import {
14
14
isTerminalState ,
15
15
} from './Trace'
16
16
import type { TraceManager } from './TraceManager'
17
+ import type { ComputedRenderSpan , ComputedSpan } from './traceRecordingTypes'
17
18
import type {
18
19
RelationSchemasBase ,
19
20
TraceContext ,
@@ -559,6 +560,14 @@ function getStateStyle(state: string) {
559
560
560
561
const TRACE_HISTORY_LIMIT = 15
561
562
563
+ // Helper to safely get a value from a possibly empty object
564
+ function getFromRecord < T > (
565
+ record : Record < string , T > | undefined ,
566
+ key : string ,
567
+ ) : T | undefined {
568
+ return record && Object . hasOwn ( record , key ) ? record [ key ] : undefined
569
+ }
570
+
562
571
// TraceAttributes component to display attributes as chips
563
572
function TraceAttributes ( {
564
573
attributes,
@@ -754,6 +763,57 @@ function RequiredSpansList<RelationSchemasT>({
754
763
)
755
764
}
756
765
766
+ // Helper to render ComputedSpan nicely
767
+ function RenderComputedSpan ( { value } : { value : ComputedSpan } ) {
768
+ if ( ! value ) return null
769
+ return (
770
+ < span style = { { marginLeft : 8 , color : '#1976d2' } } >
771
+ start: { value . startOffset . toFixed ( 2 ) } ms, duration:{ ' ' }
772
+ { value . duration . toFixed ( 2 ) } ms
773
+ </ span >
774
+ )
775
+ }
776
+
777
+ // Helper to render ComputedRenderSpan nicely
778
+ function RenderComputedRenderSpan ( { value } : { value : ComputedRenderSpan } ) {
779
+ if ( ! value ) return null
780
+ return (
781
+ < span style = { { marginLeft : 8 , color : '#1976d2' } } >
782
+ start: { value . startOffset . toFixed ( 2 ) } ms, loading:{ ' ' }
783
+ { value . firstRenderTillLoading . toFixed ( 2 ) } ms, data:{ ' ' }
784
+ { value . firstRenderTillData . toFixed ( 2 ) } ms, content:{ ' ' }
785
+ { value . firstRenderTillContent . toFixed ( 2 ) } ms, renders: { value . renderCount } ,
786
+ total: { value . sumOfRenderDurations . toFixed ( 2 ) } ms
787
+ </ span >
788
+ )
789
+ }
790
+
791
+ // Helper to render ComputedRenderBeaconSpans nicely
792
+ function RenderComputedRenderBeaconSpans ( {
793
+ computedRenderBeaconSpans,
794
+ } : {
795
+ computedRenderBeaconSpans : Record < string , ComputedRenderSpan >
796
+ } ) {
797
+ if (
798
+ ! computedRenderBeaconSpans ||
799
+ Object . keys ( computedRenderBeaconSpans ) . length === 0
800
+ )
801
+ return null
802
+ return (
803
+ < div style = { styles . section } >
804
+ < div style = { styles . sectionTitle } > Computed Render Beacon Spans:</ div >
805
+ < ul style = { { listStyle : 'none' , margin : 0 , padding : 0 } } >
806
+ { Object . entries ( computedRenderBeaconSpans ) . map ( ( [ name , value ] ) => (
807
+ < li key = { name } style = { styles . listItem } >
808
+ { name }
809
+ < RenderComputedRenderSpan value = { value } />
810
+ </ li >
811
+ ) ) }
812
+ </ ul >
813
+ </ div >
814
+ )
815
+ }
816
+
757
817
// Function to download trace recording as a JSON file
758
818
function downloadTraceRecording <
759
819
RelationSchemasT extends RelationSchemasBase < RelationSchemasT > ,
@@ -819,7 +879,11 @@ function TraceItem<
819
879
if ( trace . traceContext && trace . finalTransition ) {
820
880
return getComputedResults ( trace . traceContext , trace . finalTransition )
821
881
}
822
- return { computedSpans : { } , computedValues : { } }
882
+ return {
883
+ computedSpans : { } ,
884
+ computedValues : { } ,
885
+ computedRenderBeaconSpans : { } ,
886
+ }
823
887
} , [ trace . traceContext , trace . finalTransition ] )
824
888
825
889
// Handle download button click without triggering the expand/collapse
@@ -1003,16 +1067,14 @@ function TraceItem<
1003
1067
< div style = { styles . sectionTitle } > Computed Spans:</ div >
1004
1068
< ul style = { { listStyle : 'none' , margin : 0 , padding : 0 } } >
1005
1069
{ ( trace . computedSpans ?? [ ] ) . map ( ( name ) => {
1006
- const value = computedResults . computedSpans ?. [ name ]
1070
+ const value = getFromRecord ( computedResults . computedSpans , name )
1007
1071
return (
1008
1072
< li key = { name } style = { styles . listItem } >
1009
1073
{ name }
1010
1074
{ trace . state === 'complete' ||
1011
1075
trace . state === 'interrupted' ? (
1012
1076
value ? (
1013
- < span style = { { marginLeft : 8 , color : '#1976d2' } } >
1014
- { JSON . stringify ( value ) }
1015
- </ span >
1077
+ < RenderComputedSpan value = { value } />
1016
1078
) : (
1017
1079
< span
1018
1080
style = { {
@@ -1030,27 +1092,39 @@ function TraceItem<
1030
1092
} ) }
1031
1093
</ ul >
1032
1094
</ div >
1095
+ { 'computedRenderBeaconSpans' in computedResults &&
1096
+ computedResults . computedRenderBeaconSpans &&
1097
+ Object . keys ( computedResults . computedRenderBeaconSpans ) . length > 0 ? (
1098
+ < RenderComputedRenderBeaconSpans
1099
+ computedRenderBeaconSpans = {
1100
+ computedResults . computedRenderBeaconSpans
1101
+ }
1102
+ />
1103
+ ) : null }
1033
1104
< div style = { styles . section } >
1034
1105
< div style = { styles . sectionTitle } > Computed Values:</ div >
1035
1106
< ul style = { { listStyle : 'none' , margin : 0 , padding : 0 } } >
1036
- { ( trace . computedValues ?? [ ] ) . map ( ( name ) => (
1037
- < li key = { name } style = { styles . listItem } >
1038
- { name }
1039
- { trace . state === 'complete' || trace . state === 'interrupted'
1040
- ? ( ( ) => {
1041
- const value = computedResults . computedValues ?. [ name ]
1042
- if ( value !== undefined ) {
1043
- return (
1044
- < span style = { { marginLeft : 8 , color : '#1976d2' } } >
1045
- { String ( value ) }
1046
- </ span >
1047
- )
1048
- }
1049
- return null
1050
- } ) ( )
1051
- : null }
1052
- </ li >
1053
- ) ) }
1107
+ { ( trace . computedValues ?? [ ] ) . map ( ( name ) => {
1108
+ const value = getFromRecord < string | number | boolean > (
1109
+ computedResults . computedValues as Record <
1110
+ string ,
1111
+ string | number | boolean
1112
+ > ,
1113
+ name ,
1114
+ )
1115
+ return (
1116
+ < li key = { name } style = { styles . listItem } >
1117
+ { name }
1118
+ { trace . state === 'complete' || trace . state === 'interrupted'
1119
+ ? value !== undefined && (
1120
+ < span style = { { marginLeft : 8 , color : '#1976d2' } } >
1121
+ { String ( value ) }
1122
+ </ span >
1123
+ )
1124
+ : null }
1125
+ </ li >
1126
+ )
1127
+ } ) }
1054
1128
</ ul >
1055
1129
</ div >
1056
1130
{ /* Definition modifications details */ }
0 commit comments