-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
fix(browser): Fix missing traces for user feedback #19660
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import * as Sentry from '@sentry/browser'; | ||
| // Import these separately so that generatePlugin can handle them for CDN scenarios | ||
| // eslint-disable-next-line import/no-duplicates | ||
| import { browserProfilingIntegration } from '@sentry/browser'; | ||
| // eslint-disable-next-line import/no-duplicates | ||
| import { feedbackIntegration } from '@sentry/browser'; | ||
|
|
||
| window.Sentry = Sentry; | ||
|
|
||
| Sentry.init({ | ||
| dsn: 'https://public@dsn.ingest.sentry.io/1337', | ||
| integrations: [ | ||
| Sentry.browserTracingIntegration(), | ||
| browserProfilingIntegration(), | ||
| feedbackIntegration({ | ||
| tags: { from: 'integration init' }, | ||
| }), | ||
| ], | ||
| tracesSampleRate: 1.0, | ||
| profilesSampleRate: 1, | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| <!doctype html> | ||
| <html> | ||
| <head> | ||
| <meta charset="utf-8" /> | ||
| </head> | ||
| <body></body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| import { expect } from '@playwright/test'; | ||
| import { sentryTest } from '../../../utils/fixtures'; | ||
| import { | ||
| envelopeRequestParser, | ||
| getEnvelopeType, | ||
| shouldSkipFeedbackTest, | ||
| shouldSkipTracingTest, | ||
| waitForTransactionRequest, | ||
| } from '../../../utils/helpers'; | ||
|
|
||
| sentryTest( | ||
| 'feedback should have trace_id when profiling is enabled and idle span has ended', | ||
| async ({ getLocalTestUrl, page, browserName }) => { | ||
| if (shouldSkipFeedbackTest() || shouldSkipTracingTest() || browserName !== 'chromium') { | ||
| sentryTest.skip(); | ||
| } | ||
|
|
||
| const url = await getLocalTestUrl({ | ||
| testDir: __dirname, | ||
| handleLazyLoadedFeedback: true, | ||
| responseHeaders: { 'Document-Policy': 'js-profiling' }, | ||
| }); | ||
|
|
||
| // Wait for the pageload transaction to be sent (idle span ended) | ||
| const pageloadRequestPromise = waitForTransactionRequest(page, event => event.contexts?.trace?.op === 'pageload'); | ||
|
|
||
| const feedbackRequestPromise = page.waitForResponse(res => { | ||
| const req = res.request(); | ||
| const postData = req.postData(); | ||
| if (!postData) { | ||
| return false; | ||
| } | ||
| try { | ||
| return getEnvelopeType(req) === 'feedback'; | ||
| } catch { | ||
| return false; | ||
| } | ||
| }); | ||
|
|
||
| await page.goto(url); | ||
|
|
||
| // Wait for the idle page load span to finish | ||
| const pageLoadEvent = envelopeRequestParser(await pageloadRequestPromise); | ||
|
|
||
| // Submit feedback after idle span ended — no active span | ||
| await page.getByText('Report a Bug').waitFor({ state: 'visible' }); | ||
| await page.getByText('Report a Bug').click(); | ||
| await page.locator('[name="name"]').fill('Jane Doe'); | ||
| await page.locator('[name="email"]').fill('janedoe@example.org'); | ||
| await page.locator('[name="message"]').fill('feedback after idle span ended'); | ||
| await page.locator('[data-sentry-feedback] .btn--primary').click(); | ||
|
|
||
| const feedbackEvent = envelopeRequestParser((await feedbackRequestPromise).request()); | ||
|
|
||
| expect(feedbackEvent.contexts?.trace?.trace_id).toMatch(/\w{32}/); | ||
| expect(feedbackEvent.contexts?.trace?.span_id).toMatch(/\w{16}/); | ||
|
|
||
| // contexts.trace.data must include thread.id to identify which thread is associated with the transaction | ||
| expect(pageLoadEvent.contexts?.trace?.data?.['thread.id']).toBe('0'); | ||
| expect(pageLoadEvent.contexts?.trace?.data?.['thread.name']).toBe('main'); | ||
|
|
||
| // fixme: figure out why profiler_id is set on feedback and not on pageload transaction | ||
| // todo: rename to `profiler_id` | ||
| expect(feedbackEvent.contexts?.profile?.profile_id).toMatch(/^[a-f\d]{32}$/); | ||
| }, | ||
| ); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1222,7 +1222,7 @@ export abstract class Client<O extends ClientOptions = ClientOptions> { | |
| this.emit('postprocessEvent', evt, hint); | ||
|
|
||
| evt.contexts = { | ||
| trace: getTraceContextFromScope(currentScope), | ||
| trace: { ...evt.contexts?.trace, ...getTraceContextFromScope(currentScope) }, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Trace context merge is overwritten by spread orderMedium Severity The computed merge |
||
| ...evt.contexts, | ||
| }; | ||
|
Comment on lines
1224
to
1227
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: The Suggested FixTo ensure the merged trace context is preserved, move the Prompt for AI AgentDid we get this right? 👍 / 👎 to inform future reviews. |
||
|
|
||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test uses weak unanchored regex for trace assertions
Low Severity
The assertions for
trace_idandspan_iduse/\w{32}/and/\w{16}/— unanchored regexes with\w(which matches underscores and uppercase letters). This is inconsistent with the stricter/^[a-f\d]{32}$/used on line 62 in the same test. Since these are the core assertions validating the fix (that feedback events get proper trace context), they don't thoroughly verify the newly added behavior. A string longer than 32 characters or containing non-hex characters would still pass.Triggered by project rule: PR Review Guidelines for Cursor Bot