✨ SSI: Programmatic API, E2E tests, and documentation (Phase 6)#4190
Closed
✨ SSI: Programmatic API, E2E tests, and documentation (Phase 6)#4190
Conversation
|
All contributors have signed the CLA ✍️ ✅ |
Bundles Sizes Evolution
🚀 CPU Performance
🧠 Memory Performance
|
|
✅ Tests 🎉 All green!❄️ No new flaky tests detected 🎯 Code Coverage (details) 🔗 Commit SHA: f44d55f | Docs | Datadog PR Page | Was this helpful? Give us feedback! |
3091386 to
87d1882
Compare
Creates new @datadog/browser-remote-config package with:
- Independent remote configuration fetching and parsing
- Support for dynamic value resolution (cookies, DOM, JS paths)
- Lightweight package with only @datadog/browser-core dependency
- Comprehensive unit and integration tests (67 passing tests)
- Full TypeScript support with strict mode
Removes remote configuration from rum-core:
- Removes remoteConfigurationId and remoteConfigurationProxy from SDK init
- Removes async remote config fetch from bootstrap
- Simplifies SDK initialization flow
- Enables parallel fetching/initialization by customers
Benefits:
- Customers can use remote config independently of RUM SDK
- SDK is simpler and lighter
- Clear separation of concerns
- Enables parallel fetching/initialization strategies
This is a breaking change appropriate for v7 major version.
Customers migrating from v6 to v7:
- Old: datadogRum.init({ remoteConfigurationId: 'xxx' })
- New: const cfg = await fetchRemoteConfiguration(...); datadogRum.init({ ...cfg.value?.rum })
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Create the initial project structure for the CDN bundle generator: - scripts/build/generate-cdn-bundle.ts: CLI entry point with argument parsing - scripts/build/lib/bundleGenerator.ts: Core generator library The generator will download pre-built SDK from CDN and combine it with remote configuration into a single JavaScript bundle. No new dependencies added - uses built-in node:https and node:fs/promises. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
… 5, Tasks 2-4)
Task 2: Config Fetching Implementation
- Use @datadog/browser-remote-config package to fetch remote configuration
- Handle error cases with descriptive messages
- Support site parameter for different Datadog datacenters
Task 3: SDK Bundle Download from CDN
- Download pre-built SDK bundles from Datadog CDN
- Support both 'rum' and 'rum-slim' variants
- Use correct CDN URL format: /{datacenter}/v{majorVersion}/datadog-{variant}.js
- Handle HTTP and network errors with helpful context
- 30-second timeout with proper error handling
Task 4: Code Generation with Template Literals
- Generate combined bundle with IIFE wrapper
- Embed config using deterministic JSON.stringify
- Include auto-initialization code for DD_RUM.init()
- Add comment header with SDK variant and version (no timestamps)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Task 5: CLI Entry Point Verification - CLI validates required arguments (applicationId, configId, variant) - CLI validates variant is 'rum' or 'rum-slim' - CLI outputs to file or stdout - Exit codes: 1 for user error, 2 for runtime error Task 6: Determinism Validation - Verify generateCombinedBundle produces identical output for identical inputs - Verify no timestamps (Date.now, Unix timestamps, ISO dates) in output - Verify no random values (Math.random, randomUUID) in output - Test JSON key ordering consistency - Test edge cases (empty SDK, minimal config, undefined/null values) All 17 tests pass: - generateCombinedBundle: 8 tests - determinism: 5 tests - edge cases: 4 tests Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Add comprehensive tests for the CDN bundle generator: CLI argument validation tests: - --help/-h flag displays usage information - Missing required arguments show helpful error - Invalid variant shows valid options - Accepts both 'rum' and 'rum-slim' variants - Short flags (-a, -c, -v) work correctly Error handling tests: - Invalid config ID provides helpful error message Integration tests: - Generated bundle is valid JavaScript - Generated bundle executes without error in simulated browser Total test coverage: 29 tests across 7 test suites - bundleGenerator.spec.ts: 17 tests - generate-cdn-bundle.spec.ts: 12 tests Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add high-level generateBundle() function with input validation - Rename low-level GenerateBundleOptions to CombineBundleOptions - Add in-memory SDK cache to downloadSDK() for watch mode perf - Add clearSdkCache() test helper - Add 13 new tests (8 validation + 5 cache behavior) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add embeddedConfig.scenario.ts: SDK loads with embedded config, rum-slim variant, no remote config requests, bundle metadata verification - Add embeddedConfigDynamic.scenario.ts: dynamic value markers (cookie, DOM, JS path) preserved in bundle, mixed static/dynamic values, nested structures - 15 E2E tests passing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Enhance JSDoc on all exports with @internal, @example, @throws - Add SdkVariant type description for rum vs rum-slim - Mark internal APIs (fetchConfig, downloadSDK, generateCombinedBundle) - Create bundleGenerator.README.md with API reference, build tool integration examples (Node.js, webpack, Vite), and troubleshooting Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tting - Fix SDK cache key to include datacenter (prevents cross-region cache hits) - Replace non-null assertion with discriminated union return type on fetchConfig - Restore RemoteConfiguration type instead of `unknown` in E2E test framework - Add 30s timeout to config fetch via Promise.race - Replace `as any` with targeted type assertion in buildEndpoint - Fix ~30 lint errors (unused imports, JSDoc ordering, guard-for-in, string concat) - Run formatter across all files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Generator Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add type narrowing in remote-config spec tests for discriminated union - Fix .ts extensions in endpoint/src/index.ts for Node native TS - Add endpoint package to tsconfig project references - Update CLI and spec imports to use source paths - Use node instead of npx tsx in CLI test subprocess Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add endpoint tsconfig to ESLint parserOptions.project - Disable browser-specific lint rules in Node.js build tool files (disallow-side-effects, enforce-prod-deps-imports) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The endpoint package is a Node.js build tool, not a browser SDK package. Point main/types to source files instead of compiled output, skip the standard browser build pipeline which doesn't support Node.js features. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Disable no-new-func/no-implied-eval for Function constructor in tests - Remove unused imports and variables - Fix curly brace style and JSDoc indentation in CLI - Fix import ordering in E2E scenario files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Exclude packages/endpoint from Karma glob pattern to prevent Node.js-only spec files from being bundled for browser tests - Fix no-useless-escape in jsonPathParser.spec.ts - Remove unused imports (monitorError, interceptRequests) in preStartRum.ts and preStartRum.spec.ts - Add packages/rum/src/types/profiling.ts to ESLint ignores (auto-generated file with intentional eslint-disable) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ntroller guard - Remove unused RemoteConfiguration import from mock.ts (leftover from rebase conflict resolution where param type became unknown) - Change static import of @datadog/browser-remote-config in bundleGenerator.ts to a lazy dynamic import inside fetchConfig(); the static import caused script-tests to fail because cjs/index.js is not available until packages are built, even though the tests only exercise generateCombinedBundle which has no such dependency - AbortController pending() guard already committed in previous fix Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Add packages/endpoint/.npmignore so check-packages.ts validates the package correctly (script scans all browser-sdk packages) - Add "type": "module" to packages/endpoint/package.json to declare ESM intent; without it Node.js fails with "exports is not defined in ES module scope" when e2e tests import endpoint source files - Unify error output in generate-cdn-bundle.ts catch block with consistent "Error: ..." prefix so the script-tests assertion (stdout includes 'Error') passes regardless of error type Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Make downloadSDK import lazy in bundleGenerator.ts so importing generateCombinedBundle does not pull in sdkDownloader.ts (which uses Node.js-only APIs: node:https, import.meta.url). The e2e test imports only generateCombinedBundle from browser-sdk-endpoint and was crashing with "exports is not defined in ES module scope" - Remove "type": "module" from endpoint package.json — it caused the opposite problem: CJS-compiled output (exports.xxx) would fail when loaded as ESM - Add packages/remote-config/.npmignore matching the pattern of other packages; without it npm pack excludes cjs/ and esm/ (gitignored) so check-packages fails with "File esm/index.js is missing" Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The e2e test imports generateCombinedBundle from @datadog/browser-sdk-endpoint. index.ts statically re-exported downloadSDK/clearSdkCache from sdkDownloader.ts which uses Node.js-only APIs (node:https, import.meta.url), causing "exports is not defined in ES module scope" in the Playwright test runner. Remove the sdkDownloader re-exports from index.ts — these are internal Node.js utilities that don't belong in the package's public API. Update generate-cdn-bundle.ts to import downloadSDK directly from the source file instead. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
87d1882 to
27be749
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Phase 6 of the SSI (Server-Side Instrumentation) CDN bundle generator project. This adds the programmatic API so build tools (webpack, Vite, Node.js scripts) can integrate the bundle generator directly, adds E2E tests proving the embedded config approach works, creates documentation, and extracts remote configuration into a standalone package with architectural improvements.
Builds on Phase 5 (Core Generator) which implemented the CLI tool and library for generating bundled SDK + config.
Changes
Wave 1: Programmatic API + SDK Caching
generateBundle()API — high-level async function that orchestrates fetch config → download SDK → generate bundle with full input validationdownloadSDK()— avoids re-fetching the same SDK variant during watch mode (<5ms cache hit vs ~500ms network)GenerateBundleOptions→CombineBundleOptions(low-level) + newGenerateBundleOptions(high-level API)Wave 2: E2E Tests
embeddedConfig.scenario.ts— 8 tests: SDK loads with embedded config, rum-slim variant, no remote config requests, bundle validationembeddedConfigDynamic.scenario.ts— 7 tests: dynamic value markers (cookie, DOM, JS path) preserved in bundle, mixed static/dynamic valuesWave 3: Documentation
@internal,@example,@throwsbundleGenerator.README.md— API reference, build tool integration examples (Node.js, webpack, Vite), troubleshootingWave 4: Review Fixes
datacenterin cache key to prevent cross-region cache hitsconfigResult.value!with proper discriminated union return typeRemoteConfigurationtype instead ofunknownin E2E test frameworkPromise.raceto prevent hanging buildsas anyassertion — replace with targeted type assertion inbuildEndpointWave 5: Architecture Improvements
@datadog/browser-corebuildSiteHost(site?)extraction — new lightweight function for site-to-host resolution without requiring fullInitConfiguration.buildEndpointHostdelegates to it for the common case.@datadog/browser-remote-configRemoteConfigResultdiscriminated union —{ ok: true; value } | { ok: false; error }for proper TypeScript narrowing (eliminates non-null assertions across all consumers)AbortSignalsupport —fetchRemoteConfigurationnow accepts optionalsignalfor request cancellation and timeoutsbuildSiteHostdecoupling — uses the newbuildSiteHostinstead ofbuildEndpointHost, removing the type assertion hackNew:
@datadog/browser-sdk-endpointgenerateBundle()API into a proper published Node.js packagebundleGenerator.ts(orchestration) andsdkDownloader.ts(CDN download + caching) for single-responsibility@datadog/browser-remote-config(no more dynamic import workaround)AbortSignal.timeout(30_000)for config fetch (clean cancellation)generate-cdn-bundle.ts) rewired to import from the new packagescripts/build/lib/bundleGenerator.tsdeletedNew Packages
@datadog/browser-sdk-endpointNode.js package for build-time SDK bundle generation with embedded remote configuration.
Public API:
generateBundle(options)— high-level orchestratorfetchConfig(options)— fetch remote configuration (with 30s timeout)downloadSDK(options)— download SDK from CDN (with caching)generateCombinedBundle(options)— combine SDK + config into IIFE bundleclearSdkCache()— testing utilityTest instructions
Checklist
🤖 Generated with Claude Code