Skip to content

Commit 362dead

Browse files
committed
bundle
1 parent 4fb0584 commit 362dead

File tree

4 files changed

+48
-121
lines changed

4 files changed

+48
-121
lines changed

bun.lock

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"@commaai/qdl": "git+https://github.com/commaai/qdl.js.git#21d7be79fa5178f253d32a0879bd8bdd4fa37e30",
99
"@fontsource-variable/inter": "^5.2.5",
1010
"@fontsource-variable/jetbrains-mono": "^5.2.5",
11+
"@sentry/react": "^10.32.1",
1112
"posthog-js": "^1.310.1",
1213
"react": "^18.3.1",
1314
"react-dom": "^18.3.1",
@@ -216,6 +217,20 @@
216217

217218
"@rollup/rollup-win32-x64-msvc": ["@rollup/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-JRpZUhCfhZ4keB5v0fe02gQJy05GqboPOaxvjugW04RLSYYoB/9t2lx2u/tMs/Na/1NXfY8QYjgRljRpN+MjTQ=="],
218219

220+
"@sentry-internal/browser-utils": ["@sentry-internal/[email protected]", "", { "dependencies": { "@sentry/core": "10.32.1" } }, "sha512-sjLLep1es3rTkbtAdTtdpc/a6g7v7bK5YJiZJsUigoJ4NTiFeMI5uIDCxbH/tjJ1q23YE1LzVn7T96I+qBRjHA=="],
221+
222+
"@sentry-internal/feedback": ["@sentry-internal/[email protected]", "", { "dependencies": { "@sentry/core": "10.32.1" } }, "sha512-O24G8jxbfBY1RE/v2qFikPJISVMOrd/zk8FKyl+oUVYdOxU2Ucjk2cR3EQruBFlc7irnL6rT3GPfRZ/kBgLkmQ=="],
223+
224+
"@sentry-internal/replay": ["@sentry-internal/[email protected]", "", { "dependencies": { "@sentry-internal/browser-utils": "10.32.1", "@sentry/core": "10.32.1" } }, "sha512-KKmLUgIaLRM0VjrMA1ByQTawZyRDYSkG2evvEOVpEtR9F0sumidAQdi7UY71QEKE1RYe/Jcp/3WoaqsMh8tbnQ=="],
225+
226+
"@sentry-internal/replay-canvas": ["@sentry-internal/[email protected]", "", { "dependencies": { "@sentry-internal/replay": "10.32.1", "@sentry/core": "10.32.1" } }, "sha512-/XGTzWNWVc+B691fIVekV2KeoHFEDA5KftrLFAhEAW7uWOwk/xy3aQX4TYM0LcPm2PBKvoumlAD+Sd/aXk63oA=="],
227+
228+
"@sentry/browser": ["@sentry/[email protected]", "", { "dependencies": { "@sentry-internal/browser-utils": "10.32.1", "@sentry-internal/feedback": "10.32.1", "@sentry-internal/replay": "10.32.1", "@sentry-internal/replay-canvas": "10.32.1", "@sentry/core": "10.32.1" } }, "sha512-NPNCXTZ05ZGTFyJdKNqjykpFm+urem0ebosILQiw3C4BxNVNGH4vfYZexyl6prRhmg91oB6GjVNiVDuJiap1gg=="],
229+
230+
"@sentry/core": ["@sentry/[email protected]", "", {}, "sha512-PH2ldpSJlhqsMj2vCTyU0BI2Fx1oIDhm7Izo5xFALvjVCS0gmlqHt1udu6YlKn8BtpGH6bGzssvv5APrk+OdPQ=="],
231+
232+
"@sentry/react": ["@sentry/[email protected]", "", { "dependencies": { "@sentry/browser": "10.32.1", "@sentry/core": "10.32.1", "hoist-non-react-statics": "^3.3.2" }, "peerDependencies": { "react": "^16.14.0 || 17.x || 18.x || 19.x" } }, "sha512-/tX0HeACbAmVP57x8txTrGk/U3fa9pDBaoAtlOrnPv5VS/aC5SGkehXWeTGSAa+ahlOWwp3IF8ILVXRiOoG/Vg=="],
233+
219234
"@tailwindcss/typography": ["@tailwindcss/[email protected]", "", { "dependencies": { "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg=="],
220235

221236
"@testing-library/dom": ["@testing-library/[email protected]", "", { "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", "aria-query": "5.3.0", "dom-accessibility-api": "^0.5.9", "lz-string": "^1.5.0", "picocolors": "1.1.1", "pretty-format": "^27.0.2" } }, "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg=="],
@@ -412,6 +427,8 @@
412427

413428
"hasown": ["[email protected]", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
414429

430+
"hoist-non-react-statics": ["[email protected]", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="],
431+
415432
"html-encoding-sniffer": ["[email protected]", "", { "dependencies": { "whatwg-encoding": "^3.1.1" } }, "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ=="],
416433

417434
"http-proxy-agent": ["[email protected]", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
@@ -538,7 +555,7 @@
538555

539556
"react-dom": ["[email protected]", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="],
540557

541-
"react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
558+
"react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
542559

543560
"react-refresh": ["[email protected]", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="],
544561

@@ -694,6 +711,8 @@
694711

695712
"postcss-nested/postcss-selector-parser": ["[email protected]", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="],
696713

714+
"pretty-format/react-is": ["[email protected]", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
715+
697716
"readdirp/picomatch": ["[email protected]", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
698717

699718
"strip-literal/js-tokens": ["[email protected]", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
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",
1920
"posthog-js": "^1.310.1",
2021
"react": "^18.3.1",
2122
"react-dom": "^18.3.1",

src/main.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import '@fontsource-variable/jetbrains-mono'
99
import './index.css'
1010
import App from './app'
1111

12-
// Initialize PostHog
12+
// init PostHog
1313
posthog.init('phc_O4kXIsdyB2cm9Wne1pwJkj5jk9Ua51ABVPAhtSuYQ4V', {
1414
api_host: 'https://us.i.posthog.com',
1515
capture_pageview: false, // We'll track manually
1616
persistence: 'memory', // Don't persist across sessions
1717
})
1818

19-
// Initialize Sentry (no-op if DSN unset)
19+
// init sentry
2020
initSentry()
2121

2222
// Explicitly load fonts before rendering to prevent FOUT

src/utils/telemetry.js

Lines changed: 25 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,145 +1,52 @@
1-
// Lightweight Sentry integration (CDN-based, no-op if DSN unset)
2-
// - Loads Sentry browser bundle at runtime if a DSN is provided
3-
// - Exposes helpers to set tags, add breadcrumbs, and send a final session event
4-
5-
let sentryInited = false
6-
let sentryInitPromise = null
7-
8-
function loadScript(src) {
9-
return new Promise((resolve, reject) => {
10-
const script = document.createElement('script')
11-
script.src = src
12-
script.crossOrigin = 'anonymous'
13-
script.async = true
14-
script.onload = () => resolve()
15-
script.onerror = () => reject(new Error(`Failed to load ${src}`))
16-
document.head.appendChild(script)
17-
})
18-
}
19-
20-
// Best-effort CDN load for Sentry + Replay. If already present, skips.
21-
async function ensureSentryBundle() {
22-
if (window.Sentry) return
23-
// Use a stable recent v7 bundle that includes tracing + replay
24-
// If you want to pin a newer version later, update this URL.
25-
const url = 'https://browser.sentry-cdn.com/7.114.0/bundle.tracing.replay.min.js'
26-
await loadScript(url)
27-
}
1+
import * as Sentry from '@sentry/react'
282

293
const SENTRY_DSN = 'https://[email protected]/4510604761825280'
304

31-
/** Initialize Sentry */
32-
export async function initSentry(options = {}) {
33-
if (sentryInited || sentryInitPromise) return sentryInitPromise
34-
35-
sentryInitPromise = (async () => {
36-
const dsn = SENTRY_DSN
37-
try {
38-
await ensureSentryBundle()
39-
if (!window.Sentry) return false
40-
41-
const release = import.meta.env.VITE_PUBLIC_GIT_SHA || 'dev'
42-
const environment = import.meta.env.MODE || 'development'
43-
44-
// Default to replay only on error to keep costs down; can be tuned.
45-
window.Sentry.init({
46-
dsn,
47-
release,
48-
environment,
49-
// Breadcrumbs already capture console by default; keep it.
50-
// Limit traces by default; you can increase later if desired.
51-
tracesSampleRate: options.tracesSampleRate ?? 0.0,
52-
replaysSessionSampleRate: options.replaysSessionSampleRate ?? 0.0,
53-
replaysOnErrorSampleRate: options.replaysOnErrorSampleRate ?? 1.0,
54-
maxBreadcrumbs: options.maxBreadcrumbs ?? 100,
55-
integrations: [new window.Sentry.Replay({
56-
maskAllText: true,
57-
blockAllMedia: true,
58-
})],
59-
})
60-
61-
sentryInited = true
62-
return true
63-
} catch (e) {
64-
// Swallow init errors to avoid breaking the app
65-
// eslint-disable-next-line no-console
66-
console.warn('[Sentry] init failed:', e)
67-
sentryInited = false
68-
return false
69-
}
70-
})()
71-
72-
return sentryInitPromise
73-
}
74-
75-
// Safe no-op wrappers if Sentry isn’t available
76-
function withSentry(cb) {
77-
if (!sentryInited || !window.Sentry) return
78-
try { cb(window.Sentry) } catch { /* no-op */ }
5+
export function initSentry() {
6+
Sentry.init({
7+
dsn: SENTRY_DSN,
8+
sendDefaultPii: true,
9+
})
7910
}
8011

8112
export function setTags(tags = {}) {
82-
withSentry((S) => S.setTags(tags))
13+
Sentry.setTags(tags)
8314
}
8415

8516
export function setTag(key, value) {
86-
withSentry((S) => S.setTag(key, value))
17+
Sentry.setTag(key, value)
8718
}
8819

8920
export function setContext(key, context) {
90-
withSentry((S) => S.setContext(key, context))
21+
Sentry.setContext(key, context)
9122
}
9223

9324
export function addBreadcrumb({ category, message, level = 'info', data }) {
94-
withSentry((S) => S.addBreadcrumb({ category, message, level, data }))
25+
Sentry.addBreadcrumb({ category, message, level, data })
9526
}
9627

97-
/**
98-
* Send a compact session summary event with pass/fail and optional console tail.
99-
* To keep payloads small, logs are placed in `extra.console_tail` and truncated.
100-
*/
10128
export function captureSessionSummary({
10229
sessionId,
103-
result, // 'pass' | 'fail' | 'abort'
30+
result,
10431
errorCode,
10532
step,
10633
meta = {},
107-
consoleTail = [], // Array<{ time, level, message }>
34+
consoleTail = [],
10835
}) {
109-
withSentry((S) => {
110-
const level = result === 'pass' ? 'info' : 'error'
111-
112-
// Attach tags for easier filtering
113-
S.setTags({
114-
session_id: sessionId,
115-
result,
116-
error_code: typeof errorCode === 'number' ? String(errorCode) : (errorCode || 'none'),
117-
last_step: typeof step === 'number' ? String(step) : (step || 'unknown'),
118-
})
36+
const level = result === 'pass' ? 'info' : 'error'
11937

120-
// Try to attach full logs if the SDK supports attachments (v7+ feature; guarded)
121-
let usedAttachment = false
122-
try {
123-
const hasAddAttachment = !!S.addAttachment
124-
if (hasAddAttachment && consoleTail && consoleTail.length) {
125-
const blob = new Blob([JSON.stringify(consoleTail)], { type: 'application/json' })
126-
// Some SDKs attach to current scope and include on next captured event
127-
S.addAttachment({ filename: 'console_tail.json', data: blob, contentType: 'application/json' })
128-
usedAttachment = true
129-
}
130-
} catch { /* ignore */ }
38+
Sentry.setTags({
39+
session_id: sessionId,
40+
result,
41+
error_code: typeof errorCode === 'number' ? String(errorCode) : (errorCode || 'none'),
42+
last_step: typeof step === 'number' ? String(step) : (step || 'unknown'),
43+
})
13144

132-
// Always include a compact tail in extras as a fallback
133-
const safeTail = (consoleTail || []).slice(-200)
134-
S.captureMessage('flash_session', {
135-
level,
136-
tags: undefined, // tags set via setTags above
137-
extra: {
138-
usedAttachment,
139-
meta,
140-
console_tail: safeTail,
141-
},
142-
})
45+
Sentry.captureMessage('flash_session', {
46+
level,
47+
extra: {
48+
meta,
49+
console_tail: consoleTail.slice(-200),
50+
},
14351
})
14452
}
145-

0 commit comments

Comments
 (0)