11import { useEffect , useRef , useState } from 'react'
2- import { tracker } from '../main '
2+ import { addBreadcrumb , setTags , setTag , setContext , captureSessionSummary } from '../utils/telemetry '
33
44import { FlashManager , StepCode , ErrorCode , DeviceType } from '../utils/manager'
55import { useImageManager } from '../utils/image'
@@ -51,6 +51,41 @@ const originalConsole = { log: console.log, warn: console.warn, error: console.e
5151 }
5252} )
5353
54+ // Unique per-page session id for correlating events
55+ const SESSION_ID = ( crypto && 'randomUUID' in crypto ) ? crypto . randomUUID ( ) : String ( Math . random ( ) ) . slice ( 2 )
56+
57+ // Helper for building environment metadata
58+ function buildEnvMeta ( ) {
59+ const ua = navigator . userAgent
60+ let os = 'Unknown'
61+ if ( ua . includes ( 'Windows NT 10.0' ) ) os = 'Windows 10/11'
62+ else if ( ua . includes ( 'Windows NT 6.3' ) ) os = 'Windows 8.1'
63+ else if ( ua . includes ( 'Windows NT 6.2' ) ) os = 'Windows 8'
64+ else if ( ua . includes ( 'Windows NT 6.1' ) ) os = 'Windows 7'
65+ else if ( ua . includes ( 'Mac OS X' ) ) {
66+ const match = ua . match ( / M a c O S X ( \d + [ . _ ] \d + [ . _ ] ? \d * ) / )
67+ os = match ? `macOS ${ match [ 1 ] . replace ( / _ / g, '.' ) } ` : 'macOS'
68+ } else if ( ua . includes ( 'Linux' ) ) {
69+ os = 'Linux'
70+ if ( ua . includes ( 'Ubuntu' ) ) os += ' (Ubuntu)'
71+ else if ( ua . includes ( 'Fedora' ) ) os += ' (Fedora)'
72+ else if ( ua . includes ( 'Debian' ) ) os += ' (Debian)'
73+ } else if ( ua . includes ( 'CrOS' ) ) os = 'ChromeOS'
74+
75+ const sandboxHints = [ ]
76+ if ( ua . includes ( 'snap' ) ) sandboxHints . push ( 'Snap' )
77+ if ( ua . includes ( 'Flatpak' ) ) sandboxHints . push ( 'Flatpak' )
78+ if ( navigator . userAgentData ?. brands ?. some ( b => b . brand . includes ( 'snap' ) ) ) sandboxHints . push ( 'Snap' )
79+
80+ return {
81+ os,
82+ sandbox : sandboxHints . length ? sandboxHints . join ( ', ' ) : 'None detected' ,
83+ browser : navigator . userAgent ,
84+ url : window . location . href ,
85+ version : import . meta. env . VITE_PUBLIC_GIT_SHA || 'dev' ,
86+ }
87+ }
88+
5489// Debug info component for error reporting
5590function DebugInfo ( { error, step, selectedDevice, serial, message, onClose } ) {
5691 const [ copied , setCopied ] = useState ( false )
@@ -640,12 +675,33 @@ export default function Flash() {
640675 . then ( ( programmer ) => {
641676 // Create QDL manager with callbacks that update React state
642677 qdlManager . current = new FlashManager ( programmer , {
643- onStepChange : setStep ,
644- onMessageChange : setMessage ,
645- onProgressChange : setProgress ,
646- onErrorChange : setError ,
647- onConnectionChange : setConnected ,
648- onSerialChange : setSerial ,
678+ onStepChange : ( s ) => {
679+ setStep ( s )
680+ addBreadcrumb ( { category : 'flash' , message : `step:${ s } ` , level : 'info' , data : { step : s } } )
681+ setTag ( 'last_step' , String ( s ) )
682+ } ,
683+ onMessageChange : ( m ) => {
684+ setMessage ( m )
685+ if ( m ) addBreadcrumb ( { category : 'flash' , message : m , level : 'info' } )
686+ } ,
687+ onProgressChange : ( p ) => {
688+ setProgress ( p )
689+ } ,
690+ onErrorChange : ( e ) => {
691+ setError ( e )
692+ if ( e !== ErrorCode . NONE ) {
693+ addBreadcrumb ( { category : 'flash' , message : 'error' , level : 'error' , data : { errorCode : e } } )
694+ setTag ( 'error_code' , String ( e ) )
695+ }
696+ } ,
697+ onConnectionChange : ( c ) => {
698+ setConnected ( c )
699+ addBreadcrumb ( { category : 'flash' , message : c ? 'connected' : 'disconnected' , level : c ? 'info' : 'warning' } )
700+ } ,
701+ onSerialChange : ( sn ) => {
702+ setSerial ( sn )
703+ setTag ( 'serial' , sn )
704+ }
649705 } )
650706
651707 // Initialize the manager
@@ -657,34 +713,59 @@ export default function Flash() {
657713 } )
658714 } , [ config , imageManager . current ] )
659715
660- // OpenReplay: set metadata when device is selected
716+ // Telemetry: set static tags/context once
717+ useEffect ( ( ) => {
718+ setTags ( { session_id : SESSION_ID } )
719+ setContext ( 'env' , buildEnvMeta ( ) )
720+ } , [ ] )
721+
722+ // Telemetry: tag device selection
661723 useEffect ( ( ) => {
662724 if ( selectedDevice ) {
663- tracker . setMetadata ( 'deviceType' , selectedDevice )
725+ setTag ( 'device_type' , selectedDevice )
726+ addBreadcrumb ( { category : 'flash' , message : `device:${ selectedDevice } ` , level : 'info' } )
664727 }
665728 } , [ selectedDevice ] )
666729
667- // OpenReplay: set serial as user ID and metadata
730+ // Telemetry: wizard screen transitions
668731 useEffect ( ( ) => {
669- if ( serial ) {
670- tracker . setUserID ( serial )
671- tracker . setMetadata ( 'serial' , serial )
732+ if ( wizardScreen ) addBreadcrumb ( { category : 'wizard' , message : wizardScreen , level : 'info' } )
733+ } , [ wizardScreen ] )
734+
735+ // Helper to send a single pass/fail summary
736+ function sendSessionSummary ( result ) {
737+ if ( reportSentRef . current ) return
738+ reportSentRef . current = true
739+ const meta = {
740+ ...buildEnvMeta ( ) ,
741+ selectedDevice,
742+ connected,
743+ serial,
744+ step,
745+ message,
672746 }
673- } , [ serial ] )
747+ const tail = consoleLogs . slice ( - 200 )
748+ captureSessionSummary ( {
749+ sessionId : SESSION_ID ,
750+ result,
751+ errorCode : error ,
752+ step,
753+ meta,
754+ consoleTail : tail ,
755+ } )
756+ }
674757
675- // OpenReplay: track session result
758+ // Send report on failure
676759 useEffect ( ( ) => {
677760 if ( error !== ErrorCode . NONE && ! reportSentRef . current ) {
678- reportSentRef . current = true
679- const errorName = Object . keys ( ErrorCode ) . find ( k => ErrorCode [ k ] === error ) || 'UNKNOWN'
680- tracker . event ( 'flash_result' , { result : 'fail' , errorCode : error , errorName, step, serial } )
761+ sendSessionSummary ( 'fail' )
681762 }
682763 } , [ error ] )
683764
765+ // Send report on success
684766 useEffect ( ( ) => {
685767 if ( step === StepCode . DONE && error === ErrorCode . NONE && ! reportSentRef . current ) {
686- reportSentRef . current = true
687- tracker . event ( 'flash_result' , { result : 'pass' , serial } )
768+ sendSessionSummary ( 'pass' )
688769 }
689770 } , [ step , error ] )
690771
0 commit comments