Skip to content

Commit 7e56d5f

Browse files
add sentry logging (#186)
1 parent 4e577e1 commit 7e56d5f

File tree

4 files changed

+105
-4
lines changed

4 files changed

+105
-4
lines changed

bun.lock

Lines changed: 45 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
"@commaai/qdl": "git+https://github.com/commaai/qdl.js.git#21d7be79fa5178f253d32a0879bd8bdd4fa37e30",
1717
"@fontsource-variable/inter": "^5.2.5",
1818
"@fontsource-variable/jetbrains-mono": "^5.2.5",
19+
"@sentry/react": "^10.32.1",
20+
"posthog-js": "^1.310.1",
1921
"react": "^18.3.1",
2022
"react-dom": "^18.3.1",
2123
"xz-decompress": "^0.2.2"

src/app/Flash.jsx

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { useEffect, useRef, useState } from 'react'
2+
import posthog from 'posthog-js'
3+
import * as Sentry from '@sentry/react'
24

35
import { FlashManager, StepCode, ErrorCode, DeviceType } from '../utils/manager'
46
import { useImageManager } from '../utils/image'
@@ -38,9 +40,9 @@ function ImagePreloader() {
3840
)
3941
}
4042

41-
// Capture console logs for debug reports
43+
// Capture console logs for debug reports and telemetry
4244
const consoleLogs = []
43-
const MAX_LOGS = 100
45+
const MAX_LOGS = 500
4446
const originalConsole = { log: console.log, warn: console.warn, error: console.error, info: console.info, debug: console.debug }
4547
;['log', 'warn', 'error', 'info', 'debug'].forEach(level => {
4648
console[level] = (...args) => {
@@ -622,6 +624,7 @@ export default function Flash() {
622624
const [serial, setSerial] = useState(null)
623625
const [selectedDevice, setSelectedDevice] = useState(null)
624626
const [wizardScreen, setWizardScreen] = useState('landing') // 'landing', 'device', 'zadig', 'connect', 'unbind', 'webusb', 'flash'
627+
const reportSentRef = useRef(false)
625628

626629
const qdlManager = useRef(null)
627630
const imageManager = useImageManager()
@@ -643,7 +646,7 @@ export default function Flash() {
643646
onProgressChange: setProgress,
644647
onErrorChange: setError,
645648
onConnectionChange: setConnected,
646-
onSerialChange: setSerial
649+
onSerialChange: setSerial,
647650
})
648651

649652
// Initialize the manager
@@ -655,6 +658,45 @@ export default function Flash() {
655658
})
656659
}, [config, imageManager.current])
657660

661+
// Helper to send a single pass/fail summary
662+
function sendSessionSummary(result) {
663+
if (reportSentRef.current) return
664+
reportSentRef.current = true
665+
666+
const errorName = Object.keys(ErrorCode).find(k => ErrorCode[k] === error) || 'NONE'
667+
const stepName = Object.keys(StepCode).find(k => StepCode[k] === step) || 'UNKNOWN'
668+
669+
// PostHog
670+
posthog.capture('flash_session', {
671+
result,
672+
serial,
673+
device_type: selectedDevice,
674+
error_code: errorName,
675+
step: stepName,
676+
})
677+
678+
// Sentry
679+
Sentry.captureMessage('flash_session', {
680+
level: result === 'pass' ? 'info' : 'error',
681+
tags: { result, serial, device_type: selectedDevice, error_code: errorName, step: stepName },
682+
extra: { console_tail: consoleLogs.slice(-200) },
683+
})
684+
}
685+
686+
// Send report on failure
687+
useEffect(() => {
688+
if (error !== ErrorCode.NONE && !reportSentRef.current) {
689+
sendSessionSummary('fail')
690+
}
691+
}, [error])
692+
693+
// Send report on success
694+
useEffect(() => {
695+
if (step === StepCode.DONE && error === ErrorCode.NONE && !reportSentRef.current) {
696+
sendSessionSummary('pass')
697+
}
698+
}, [step, error])
699+
658700
// Transition to flash screen when connected
659701
useEffect(() => {
660702
if (connected && wizardScreen === 'webusb') {

src/main.jsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
import React from 'react'
22
import ReactDOM from 'react-dom/client'
3+
import posthog from 'posthog-js'
4+
import * as Sentry from '@sentry/react'
35

46
import '@fontsource-variable/inter'
57
import '@fontsource-variable/jetbrains-mono'
68

79
import './index.css'
810
import App from './app'
911

12+
posthog.init('phc_O4kXIsdyB2cm9Wne1pwJkj5jk9Ua51ABVPAhtSuYQ4V', {
13+
api_host: 'https://us.i.posthog.com',
14+
capture_pageview: false,
15+
persistence: 'memory',
16+
})
17+
18+
Sentry.init({
19+
dsn: 'https://acb8cfad1992fafc3dc90ab1bfa3d07f@o33823.ingest.us.sentry.io/4510604761825280',
20+
sendDefaultPii: true,
21+
})
22+
1023
// Explicitly load fonts before rendering to prevent FOUT
1124
async function loadFonts() {
1225
await Promise.all([

0 commit comments

Comments
 (0)