Datadog Browser SDK

repository·main·Indexed 18 days ago

https://github.com/datadog/browser-sdk

A collection of tools for collecting and transmitting browser-side telemetry, including logs and Real User Monitoring (RUM) data, to the Datadog platform. Includes specialized packages for browser logs, a live debugger for runtime data and function snapshots, and an Angular plugin for RUM. The SDK also provides a Chrome developer extension for investigating integrations, filtering RUM events, and modifying configurations on the fly.

Tokens
42.4K
Snippets
116
Records
175
Agent score
64%

What's inside datadog-browser-sdk

  1. Overview of Salesforce Integration for Datadog RUM

    main

    The Datadog RUM Salesforce bundle allows you to instrument Salesforce Lightning Apps and Experience Cloud sites with Real User Monitoring (RUM).

    Supported deployment paths include:

    • Lightning Apps
    • Experience Cloud Head Markup
    • Experience Cloud components

    Important: You must use only one deployment path per Salesforce app or Experience Cloud site to avoid conflicts.

  2. Overview of the RUM Shopify package

    main

    The @datadog/browser-rum-shopify package is a specialized bundle designed for Shopify's Custom Pixel sandbox. It combines the RUM slim package (which excludes Session Replay and Real User Profiling) with specific bindings that translate Shopify Web Pixel events into RUM API calls.

    Key characteristics:

    • Single Script Loading: Optimized for the Shopify sandbox environment.
    • API Surface: Exposes window.DD_RUM, which follows the same public API as @datadog/browser-rum-slim.
    • View Tracking: The trackViewsManually: true option is applied by default. This means page views are driven by the Shopify page_viewed pixel event rather than automatic URL-based tracking.
  3. Overview of Datadog Browser SDK capabilities

    main

    The Datadog Browser SDK allows you to collect and send browser data to Datadog. Its primary capabilities include:

    • Log Collection: Forward logs from your browser application to Datadog.
    • Real User Monitoring (RUM): Send RUM data (performance, errors, user sessions) from your browser application to Datadog.
  4. Manage time and durations in @datadog/js-core

    main

    The @datadog/js-core package provides utilities for handling different types of time representations used within the Datadog SDKs. It distinguishes between:

    • TimeStamp: Epoch time (absolute time).
    • RelativeTime: Time relative to the navigation start of the page.
    • Duration: A span of time in milliseconds.
    • ServerDuration: A span of time in nanoseconds.

    Key utilities allow you to convert between these types, calculate elapsed time, and manage clock drift.

  5. Use the RUM Browser Monitoring slim package

    main

    The browser-rum-slim package provides Real User Monitoring (RUM) capabilities similar to the standard RUM package, but it is optimized for environments where you do not require Session Replay recording.

    Key differences from the standard RUM package:

    • No Session Replay: It does not support Session Replay recording.
    • Limited Configuration: It does not support the compressIntakeRequests initialization parameter.

    For full setup instructions, refer to the standard RUM package documentation.

  6. Use @datadog/js-core with caution

    main

    The @datadog/js-core package contains runtime-agnostic core utilities shared across various Datadog JavaScript SDKs.

    Warning: This is an internal package. It is intended for use by Datadog SDKs only and is not designed for direct consumption by end users. APIs within this package may change without notice outside of official Datadog SDK releases.

  7. How sessions are expanded or renewed

    main

    The expandOrRenew() operation is used to transition a session from an inactive or expired state back into an active state.

    When expandOrRenew() is called, the SDK performs the following logic:

    1. Transitions:
      • If the state is Expired, it calls renew().
      • If the state is Tracked or NotTracked, it calls extend().
      • If the state is NotStarted, no transition occurs.
    2. Re-evaluation: The SDK calls computeTrackingType() to determine if the session should be Tracked or NotTracked.

    Note: Because computeTrackingType() runs during every expandOrRenew(), it is theoretically possible for a session to switch between Tracked and NotTracked states, though this is not expected in typical usage.

  8. Design APIs with dependency injection

    main

    When building modules that depend on other domain-specific modules, favor passing dependencies as parameters during initialization rather than using static imports. This pattern improves:

    • Readability: Dependencies are explicitly visible in the function signature.
    • Testability: You can easily pass mock dependencies during testing.
    • Extensibility: You can swap dependencies with different implementations that share the same signature.

    Avoid statically retrieving or exposing parts of a dependency within a module. Instead, initialize dependencies at a 'boot' level and pass them into your module's entry point.

    // OK: Dependencies are passed as parameters
    // boot.ts
    const myDependency = startMyDependency()
    const myOtherDependency = getOrCreateMyDependency()
    const myModule = startMyModule(myDependency, myOtherDependency)
    
    // myModule.ts
    function startMyModule(myDependency, myOtherDependency) {
      myDependency.interact()
      myOtherDependency.interact()
    }
    
    // KO: Statically retrieving dependencies inside the module
    import { getOrCreateMyDependency } from './myDependency'
    
    function startMyModule() {
      const myDependency = getOrCreateMyDependency()
      myDependency.interact()
    }
  9. Configure the version for source-aware resolution

    main

    The version parameter in datadogDebugger.init() should match the immutable identifier of your deployed browser build. This enables source map uploads and browser build resolution.

    If you use the Datadog Live Debugger build plugin, init().version automatically defaults to the liveDebugger.version metadata injected into your bundle at build time.

    Note: If you provide an explicit version in init() that differs from the build-time injected version, the SDK will prioritize the init() value and log a warning.

  10. How route tracking and view normalization works

    main

    The DatadogPagesRouter and DatadogAppRouter components automatically detect route changes and normalize dynamic route segments into parameterized view names. This prevents a single route with many IDs from appearing as thousands of unique views in Datadog.

    Normalization Examples:

    • /about $\rightarrow$ /about
    • /users/123 $\rightarrow$ /users/[id]
    • /users/123/posts/456 $\rightarrow$ /users/[userId]/posts/[postId]
    • /docs/a/b/c $\rightarrow$ /docs/[...slug]
  11. How RUM SDK data processing works

    main

    The Real User Monitoring (RUM) SDK follows a linear data processing pipeline to transform web interactions into enriched events sent to Datadog. The lifecycle follows these stages:

    1. Boot (startRum): Triggered during SDK initialization to start all event collection processes.
    2. Collection: Modules listen to or instrument web APIs to create raw RUM events (such as views, actions, resources, and errors).
    3. Assembly: Raw events are enriched with common attributes, including applicationId, service, version, view context, and customer context.
    4. Batching: Enriched events are moved into an in-memory buffer for efficient transport.
  12. Optimize bundle size by favoring functions over classes

    main

    To minimize the final bundle size, prefer using closures and plain functions over the class syntax. Class syntax does not minify as effectively as functions, even when transpiled.

    Using a factory function that returns an object with methods (a closure) results in smaller minified code compared to a standard class definition.

    // PREFERRED: Factory function/closure (smaller minified size)
    function createBatch() {
      const pendingMessages = []
      return {
        add(message) {
          pendingMessages.push(message)
        },
      }
    }
    
    // DISCOURAGED: Class syntax (larger minified size)
    class Batch {
      pendingMessages = []
      add(message) {
        this.pendingMessages.push(message)
      }
    }