Unsampled pageload span is profiled when profileLifecycle is 'trace' (browser UI profiling)
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 82/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- javascript, typescript
- Lĩnh vực
- frontend, performance
Hướng nghiên cứu
Bắt đầu với packages/browser/src/profiling/UIProfiler.ts và so sánh notifyRootSpanActive() với listener spanStart trong _setupTraceLifecycleListeners(). Kiểm tra các bài kiểm thử profiling hiện có để xem chúng đã bao phủ trường hợp span gốc đang hoạt động và không được lấy mẫu tại thời điểm thiết lập hay chưa. Công việc hoàn tất khi trường hợp đó không khởi động profiler hoặc gửi một phần dữ liệu profile, trong khi các span gốc được lấy mẫu vẫn khởi động profiling.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Is there an existing issue for this?
- I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
- I have reviewed the documentation https://docs.sentry.io/
- I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases
How do you use Sentry?
Sentry Saas (sentry.io)
Which SDK are you using?
@sentry/browser
SDK Version
@sentry/browser 11.8.0 (also reproduced on 11.4.0; UIProfiler.ts on develop is unchanged as of 2026-10-19)
Framework Version
No response
Link to Sentry event
No response
Reproduction Example/SDK Setup
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: '<dsn>',
integrations: [Sentry.browserTracingIntegration(), Sentry.browserProfilingIntegration()],
tracesSampleRate: 0, // pageload span NOT sampled -> expect NO profiling
profileSessionSampleRate: 1,
profileLifecycle: 'trace',
});
The page is served with Document-Policy: js-profiling.
Steps to Reproduce
- Initialize the SDK with
profileLifecycle: 'trace',profileSessionSampleRate: 1andtracesSampleRate: 0(see SDK setup above). - Load the page. The pageload span is not sampled (
isRecording() === false,traceFlags === 0). - Observe that
new Profiler(...)is called once and aprofile_chunkenvelope is sent when the pageload span ends.
Expected Result
The pageload span is not sampled, so trace lifecycle profiling should not start. This is how root spans started after setup are already handled.
Actual Result
The profiler starts for the unsampled pageload span and a profile_chunk is sent.
I checked this in Chromium with a window.Profiler stub that counts constructor calls and an in-memory transport:
tracesSampleRate: 0,profileSessionSampleRate: 1: profiler started once,profile_chunksenttracesSampleRate: 0,profileSessionSampleRate: 0: profiler not started (control)tracesSampleRate: 1,profileSessionSampleRate: 1: profiler started once,profile_chunkand the pageload span sent (expected)tracesSampleRate: 0,profileSessionSampleRate: 1, pageload instrumentation off, an unsampled root span started afterinit: profiler not started
The last case shows that only the root span that is already active at setup skips the sampling check.
Additional Context
Root cause (source walkthrough)
In packages/browser/src/profiling/integration.ts (develop):
- After
profiler.initialize(client), setup callsprofiler.notifyRootSpanActive(rootSpan)for the active root span. The comment says "If there is an active, sampled root span already, notify the profiler". - Setup calls it again in a
setTimeout(0). This is the path that picks up the pageload span thatbrowserTracingIntegrationstarts inafterAllSetup.
In packages/browser/src/profiling/UIProfiler.ts:
- The
spanStartlistener registered by_setupTraceLifecycleListeners()returns early when!span.isRecording()("Only count sampled root spans"). notifyRootSpanActive()only checks the lifecycle mode and_sessionSampled. It then registers the span and calls_beginProfiling()without checkingrootSpan.isRecording().
So an unsampled root span that is already active at setup starts the profiler. The unsampled span still emits spanEnd, so the profile runs for the length of the pageload.
#17619, which added the trace lifecycle, describes it as "Starts when the first sampled root span starts".
Impact
With profileSessionSampleRate: 1, unsampled pageload spans can still start UI profiling in supported browsers. Reducing tracesSampleRate, even to 0, does not prevent this startup path. This can add unintended profiling overhead and profile usage, without a sampled pageload span to correlate with the resulting chunks.
Related
#22927 was the same kind of gap in the Node trace lifecycle, there for the session sampling decision.
Suggested fix
Return early in notifyRootSpanActive() when !rootSpan.isRecording(), matching the spanStart listener. Happy to open a PR.
- Ngôn ngữ chính
- TypeScript
- Star
- 8.8k
- Fork
- 1.9k
- Merge trung bình
- 1 ngày 11 giờ
- Pull request đã merge (30 ngày)
- 578
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của getsentry/sentry-javascript
-
Hapi: `route.method.toUpperCase is not a function` for routes registered with an array of methodsCó thể đã có người làm @itisrmk đã nhận 1 ngày trước. Đang mởBug Hapi Waiting for: Product Owner
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
getsentry/sentry-javascript#25481 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
node:http client span never ends when the response is destroyed without an error (res.destroy())Có thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mởBug Node.js Waiting for: Product Owner
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
getsentry/sentry-javascript#25469 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Core Feature: Typescript Meta: Breaking
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
getsentry/sentry-javascript#25286 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 80/100
getsentry/sentry-javascript#24860 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
javascript
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
getsentry/sentry-javascript#24200 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của getsentry/sentry-javascript
Issue tương tự
-
Admin search throws for permissions added through Admin.generalIndexItems('permissions', ...)Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Koenkk/zigbee-herdsman-converters#13540 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Add: Tequila Music TV RO SDĐang mởcheck:passed streams:add
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
iptv-org/iptv#55821 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area/busola/ux
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
kyma-project/busola#5442 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
vercel-labs/wterm#246 ·
Maintainer thường phản hồi trong vòng 1 ngày