Skip to content

[RUM-17903] Integrate tracing sample rate - #193

Draft
cdn34dd wants to merge 1 commit into
mainfrom
carlosnogueira/RUM-17903/add-trace-sample-rate
Draft

[RUM-17903] Integrate tracing sample rate#193
cdn34dd wants to merge 1 commit into
mainfrom
carlosnogueira/RUM-17903/add-trace-sample-rate

Conversation

@cdn34dd

@cdn34dd cdn34dd commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Motivation

The Electron SDK did not expose trace sampling, so main-process HTTP and IPC tracing was effectively all-or-nothing.

This change adds session-based trace sampling consistent with the existing session replay and profiling sampling model. It reduces APM volume and distributed trace propagation while preserving native HTTP requests as RUM resources, even when tracing is sampled out.

Changes

  • Added an optional traceSampleRate configuration option, defaulting to 100.
  • Applied it as a child of sessionSampleRate using deterministic session-based sampling.
  • Added trace_sample_rate to _dd.configuration on RUM events.
  • For trace-sampled sessions:
    • Creates and delivers HTTP and IPC spans.
    • Injects distributed tracing headers into outgoing HTTP requests.
    • Links RUM resources to their corresponding traces.
  • For sessions sampled out of tracing:
    • Skips IPC span creation.
    • Does not inject HTTP trace headers.
    • Drops HTTP spans from APM delivery.
    • Continues producing unlinked HTTP RUM resources.
  • Omits the SPANS transport when traceSampleRate is 0 as an idle-work optimization.
  • Added session-expiration and renewal handling so the decision remains stable for each RUM session.
  • Updated public and architecture documentation.
  • Added tests covering configuration validation, deterministic sampling, session renewal, instrumentation, RUM resource preservation, and transport setup.

Test instructions

Checklist

  • Tested locally (playground)
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.
  • Updated related documentation.
  • Agentic code review findings addressed or explicitly dismissed.

@cdn34dd

cdn34dd commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review — Score: 4.7 / 5

This is a well-designed trace sampling feature that mirrors the existing session replay and profiling child-rate model. The split between fast instrumentation gates (isTraceSampled) and the span assembly hook safety net is sound, session renewal/expiry handling is correct, and preserving unlinked HTTP RUM resources when tracing is sampled out is the right product behavior. I would approve this PR.

Why 4.7: Deterministic session-based sampling with correctedChildSampleRate, cross-bundle global state for the instrument bundle, thorough unit coverage (config validation, instrumentation, span assembly, transport), and clear architecture documentation. The SKIPPED/DISCARDED hook inversion in TraceSampling correctly composes with existing session/view enrichment hooks.

Why not 5: Two small, intentional tradeoffs remain: (1) isTraceSampled() defaults to true before init() completes, so a brief pre-init startup window may still trace even when traceSampleRate is 0; (2) HTTP instrumentation still creates local dd-trace spans for RUM resource timing when a session is trace-sampled out — documented, but it means some tracing overhead remains on unsampled sessions.


Findings

  • [Nit] Pre-init tracing defaultisTraceSampled() returns true until TraceSampling runs, so very early main-process traffic may trace briefly even with traceSampleRate: 0.

Architectural flow

sequenceDiagram
    participant App as App code
    participant Inst as Instrumentation
    participant TS as TraceSampling
    participant SP as SpanProcessor
    participant Hooks as FormatHooks
    participant Transport as Transport

    Note over TS: init sets per-session trace decision
    TS->>Inst: setTraceSampled

    App->>Inst: HTTP or IPC call
    Inst->>Inst: isTraceSampled check
    alt trace sampled
        Inst->>Inst: create span and inject HTTP headers
    else not trace sampled
        Inst->>Inst: skip IPC spans and header injection
        Note over Inst: HTTP keeps local span for RUM timing
    end

    Inst->>SP: dd-trace export
    SP->>Hooks: triggerSpan by startTime
    alt hooks DISCARDED
        SP->>SP: drop APM span
        SP->>SP: emit unlinked HTTP RUM resource
    else hooks pass
        SP->>Transport: linked span envelope
    end
Loading

Before: All sampled RUM sessions produced main-process HTTP/IPC spans, injected distributed tracing headers, and linked RUM resources to traces.

After: traceSampleRate gates tracing as a child of sessionSampleRate. Trace-sampled sessions behave as before. Non-trace-sampled sessions skip IPC spans and HTTP header injection, discard APM spans at assembly time, and still emit unlinked HTTP RUM resources. The SPANS transport is omitted when traceSampleRate is 0 as an idle-work optimization.

Open in Web View Automation 

Sent by Cursor Automation: electron-sdk reviews


function getState(): TraceSamplingState {
const store = globalThis as unknown as Record<symbol, TraceSamplingState | undefined>;
return (store[TRACE_SAMPLING_STATE] ??= { sampled: true });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-init default (sampled: true) — This preserves pre-init() backward compatibility (also covered by the unit test), but it means a narrow startup window can still trace/inject headers even when the user configures traceSampleRate: 0. If that window ever shows up in the field, consider initializing from config in the instrument prelude; for now the tradeoff seems reasonable.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1d6ae4ed66

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// so it is authoritative for the rates reported on every RUM event.
const ddConfiguration = {
session_sample_rate: configuration.sessionSampleRate,
trace_sample_rate: configuration.traceSampleRate,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid overriding renderer trace sampling config

When a renderer uses the Browser SDK with its own tracing configuration and Electron init sets traceSampleRate differently (for example 0 to disable only main-process HTTP/IPC tracing), this value is applied to renderer RUM events too. RendererPipeline merges hook overrides over the renderer event, so the renderer’s own _dd.configuration.trace_sample_rate is replaced even though the new config is documented as controlling main-process requests and IPC operations. This makes renderer RUM metadata report the wrong trace sampling decision; keep this field main-only or preserve the renderer-provided value for renderer events.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant