Skip to content

feat(browser): send SDK lifecycle telemetry - #444

Merged
btthomas merged 7 commits into
mainfrom
blake.thomas/sdk-telemetry
Nov 3, 2026
Merged

btthomas merged 7 commits into
mainfrom
blake.thomas/sdk-telemetry

Conversation

@btthomas

@btthomas btthomas commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Send browser SDK startup results and configuration-fetch errors to Datadog. These reports support SDK setup and troubleshooting. The event format matches the backend schema from https://github.com/ddoghq/dd-source/pull/98932.

Behavior

DatadogProvider sends diagnostics through the existing /api/v2/flagevaluation JSONL batch. Diagnostics do not require a flag evaluation or RUM. Evaluation, exposure, and RUM tracking settings do not control diagnostics.

Initialization reports use these outcomes:

  • ready: the provider received and accepted a fresh configuration.
  • failed: initialization failed.
  • cached_fallback: the configuration request failed, but the provider can use a cached configuration.
  • incomplete: the page exited or the provider closed before initialization finished.

A pending initialization can send one incomplete report. If the page resumes and initialization finishes, the provider can also send its final result. There is no timed initialization report.

After initialization finishes, the provider can send one provider_error report with CONFIG_FETCH_FAILED. Requests cancelled by a newer context update do not count as errors, including requests cancelled while waiting for cached configuration.

Each initialize-to-close lifecycle sends at most three diagnostic records. Initializing a closed provider starts a new lifecycle with new timings and report limits. Responses from a closed lifecycle do not complete the new initialization. Evaluation tracking also restarts.

Diagnostics and evaluations share the existing endpoint, batch limits, and page-exit flush. Diagnostic setup, queue, and shutdown failures do not interrupt flag evaluation. Batching can delay delivery. Page-exit delivery is best effort. Missing reports do not prove that the SDK failed.

Data

Reports require env and either applicationId or service. The application ID takes priority when both are set.

Reports contain SDK name and version, application or service identity, environment, timings, and error codes. They exclude flag values, evaluation context, client tokens, and raw errors. There is no instance ID or sequence field. Reports must not be linked to a specific instance by timestamp alone.

Named limits match the backend schema fixture. The 24-hour duration limit validates reports; it does not trigger a report. This PR adds no debug-mode option or diagnostic console logging.

Example event:

{
      "timestamp": "2026-11-03T18:43:17.004Z",
      "event_type": "sdk_initialization",
      "sdk_timestamp": 1793731393740,
      "initialization": {
        "outcome": "ready",
        "started_at_ms": 1793731393701,
        "duration_ms": 38.8999999761581,
        "final": true,
        "milestones": {
          "configuration_received": {
            "elapsed_ms": 38.1999999880791
          },
          "provider_ready": {
            "elapsed_ms": 38.8999999761581
          }
        }
      },
      "sdk_name": "dd-openfeature-browser",
      "sdk_version": "2.3.0-83fedda8f3e4d06f45f5217a2d6cc630d2e0ea53",
      "application_id": "2594e81b-5e57-44fd-92cc-ce0fbb8d0d81",
      "environment": "staging"
}

Validation

Passed locally:

  • 647 browser unit tests across 35 suites.
  • Browser typecheck, repository lint, formatting, and diff checks.
  • Release package builds and 50 packaged Chromium tests. These cover diagnostic uploads, blocked uploads, slow initialization, mixed JSONL batches, page-exit flushing, and existing evaluation and exposure behavior.

Regression tests cover cancellation during cache fallback, provider reuse, fresh error limits, and late responses from a closed lifecycle. Schema tests check diagnostic payloads against the backend contract.

For a manual staging check, run yarn test:browser-install, then run yarn dev in test-app and open /diagnostics.html. Enter staging credentials, initialize the provider, and close it to flush. Check the stored records through the SDK diagnostics API. This branch has not been tested against staging.

Checklist

  • Updated documentation.
  • Tested locally.
  • Tested on staging.
  • Added unit tests.
  • Added browser integration tests.

AI-assisted implementation.

@btthomas
btthomas requested a review from a team as a code owner October 29, 2026 20:35
@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

OpenFeature Browser Provider Bundle Sizes

Measured from the Vite production output after installing packed @datadog/flagging-core and @datadog/openfeature-browser tarballs.

Both scenarios initialize an OpenFeature provider, evaluate a boolean flag, change context, and evaluate again. Telemetry is disabled for DatadogProvider; no tracking hooks are registered for DatadogCoreProvider. DatadogProvider fetches precomputed assignments for each context; DatadogCoreProvider receives rules from fetchRulesConfiguration once and evaluates locally.

Sizes include OpenFeature and the same small scenario harness. Configuration responses are supplied by Playwright and are not bundled. These are complete scenario JS sizes, not configuration payload sizes or isolated provider/Protobuf costs; the difference between rows is not a decoder-only delta.

Scenario HTML JS Assets Raw JS Gzip JS Protobuf Markers
DatadogProvider (precomputed fetching) provider.html 15 107.4 KiB 38.7 KiB no
DatadogCoreProvider + fetchRulesConfiguration core-provider.html 15 196.1 KiB 63.4 KiB yes

Dependency checks passed: no Protobuf markers in default/precomputed scenarios; markers present in rules-based scenarios.

OpenFeature Browser Tracking Hook Bundle Sizes

Synthetic entrypoints import and call tracking hook factories from the packed @datadog/openfeature-browser/rules-based ESM package. Deltas are measured against the no-hook baseline from the same Vite production build.

Scenario HTML JS Assets Raw JS Raw Δ Gzip JS Gzip Δ
tracking hook baseline tracking-baseline.html 5 2.7 KiB 0 B 1.5 KiB 0 B
exposure logging hook tracking-exposure.html 10 71.1 KiB +68.4 KiB 26.4 KiB +24.9 KiB
evaluation logging hook tracking-evaluation.html 11 66.9 KiB +64.2 KiB 24.9 KiB +23.4 KiB
RUM tracking hook tracking-rum.html 8 6.8 KiB +4.1 KiB 3.5 KiB +2.0 KiB
all tracking hooks tracking-all.html 13 75.9 KiB +73.2 KiB 28.5 KiB +27.0 KiB

OpenFeature Node Server Bundle Sizes

Independent Webpack production builds of the installed core and Node SDK tarballs, targeting Node 18 with ESM (module export condition). Node built-ins remain external. OpenFeature, dd-trace, and configuration fixtures are not bundled.

Scenario Raw JS Gzip JS Protobuf Modules
Node provider only 42.1 KiB 13.4 KiB no
SSR helpers only (fetch client rules + serialize) 81.0 KiB 23.5 KiB yes
Node provider + SSR helpers 122.1 KiB 35.7 KiB yes

Adding SSR helpers to the provider adds 80.0 KiB raw / 22.3 KiB gzip in this build. This includes fetching, parsing, and serialization, not just the decoder. SSR helpers fetch rules for the browser, not for configuring that provider (which uses its existing JSON API).

These are bundler sizes, not npm install sizes, unbundled Node require/import costs, payload sizes, or latency. Gzip compares compressed artifacts. The browser scenarios include OpenFeature and a different harness, so their sizes are not directly comparable.

Dependency checks passed: no Protobuf runtime or generated schema modules in the provider-only bundle; present in both SSR bundles (checked using Webpack module statistics).

This report shows current PR artifact sizes only; it does not compare against the base branch.

@leoromanovsky

leoromanovsky commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

FFE reviewer selection

Reviewers: @ethan-romero-dg, @typotter

Why: Guided and observable onboarding — The PR adds a new browser SDK startup and lifecycle telemetry capability. Reviewers come from the matched pod.

🤖 Automated selection.

Selection details

Initiative: project / guided-onboarding

Why this match: The PR adds a new browser SDK startup and lifecycle telemetry capability. It emits bounded sdk_initialization outcomes (ready, failed, cached_fallback or incomplete) with elapsed timings, plus a one-time CONFIG_FETCH_FAILED provider_error, through the existing intake. The stated purpose is onboarding and SDK troubleshooting. This is the catalog's 'SDK startup/lifecycle telemetry' for telling apart provider readiness, configuration received and failure. It is not routine evaluation or exposure transport maintenance.

  • @ethan-romero-dg — primary (sdk-onboarding): Matched pod member. Review requested.
  • @typotter — floating (sdk-onboarding): Coverage and knowledge sharing. Covers: openfeature-architecture. Existing review coverage preserved.

Additional review: openfeature-architecture — The DatadogProvider lifecycle changes in substance. initialize() now creates a shared transport once per provider and records an initialization failure before rethrowing. onClose() stops lifecycle telemetry, then stops and clears the shared transport in a finally block after tracking shutdown. Provider-tracking now takes an injected transport getter. Together these change initialization, re-initialization and shutdown semantics, which this area covers. Coverage: @typotter. Evidence: packages/browser/src/openfeature/provider.ts, packages/browser/src/openfeature/provider-tracking.ts

The PR author was excluded. Existing reviewers and teams were preserved.

Debug or fix a problem

Workflow run · Bits Code session

  • Wrong project or pod? Clarify this PR’s purpose, or correct the reviewer registry and publish the change. Sheet edits take effect after publication.
  • Need another reviewer now? Request them in GitHub. This workflow only adds requests and keeps existing reviewers.
  • Stuck beyond five minutes or failed? Inspect the run’s failed step and available Bits session. After fixing the cause, rerun the workflow with this PR URL and dry_run=false. Unchanged completed runs are skipped. If the receipt says needs_reconciliation or a write outcome is uncertain, ask the workflow owner to reconcile GitHub and the receipt before retrying; do not delete the lock blindly.
  • Report a problem: Comment on the reviewer-routing skill PR with this PR URL, the workflow run link, and the expected initiative or reviewer correction.
Evidence and run details

✅ Complete — reviewer coverage verified. The workflow checked pending requests or submitted reviews on the evaluated head.

Generated asynchronously by the FFE reviewer-routing workflow.

Changed paths: packages/browser/src/openfeature/lifecycleTelemetry.ts, packages/browser/src/openfeature/provider.ts, packages/browser/src/openfeature/flagEvaluationTransport.ts, packages/browser/src/openfeature/flagEvaluations.ts, packages/browser/test/openfeature/lifecycleTelemetry.spec.ts, packages/browser/test/openfeature/provider-diagnostics.spec.ts, test-app/src/diagnostics.ts

Evaluated head: d2f48c608ff4cb931a99e310e63555ff27a1e922

Registry revision: revision:efde5129-b144-41ab-b630-1adf6ad22901

Pinned skill source: 7e3283c602f6b18a7e3e623eecb52d3a9c091a2e

Instructions: workflow-injected snapshot (no plugin loaded)

Instruction snapshot SHA-256: 52ed8cb68675dde1a47addaefe4a9500891c24014abf7dade6dfe38cf836c1d2

@btthomas
btthomas merged commit 4c3f6f0 into main Nov 3, 2026
5 checks passed
@btthomas
btthomas deleted the blake.thomas/sdk-telemetry branch November 3, 2026 19:19
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.

4 participants