Client-side observability

Overview

This topic explains options for enabling client-side observability through the SDK observability plugins. It is only applicable for client-side JavaScript-based SDKs.

The LaunchDarkly observability plugins are designed for use in conjunction with the JavaScript client-side SDK. They collect and send observability data to LaunchDarkly, so you can review error monitoring, session replay, and more from within the LaunchDarkly UI.

To get started with the observability plugins, read the reference guides for the Observability plugin and Session replay plugin.

The following sections describe supported options and features of LaunchDarkly’s client-side observability in more detail.

Plugin options

The observability and session replay plugins support the following options. For additional information on any of the options described below, read HighlightOptions.

Privacy

When you configure the plugin options for the observability plugin or the session replay plugin, you can choose from the following privacy settings:

  • set privacySetting to default to obfuscate all inputs and any text that matches commonly used regex expressions for personally identifiable information (PII).
  • set privacySetting to strict to obfuscate all HTML DOM text and images.
  • set privacySetting to none if you don’t want to obfuscate anything.

By default, strict privacy mode is enabled. This provides the safest option as no PII should be captured, but may limit session replay usability.

With default privacy mode, the plugin obfuscates all inputs and any text that matches commonly used regex expressions for personally identifiable information (PII). This functionality offers a base level protection from recording info such as addresses, phone numbers, social security numbers, and more. It does not obfuscate any images or media content. It may obfuscate other, non-PII text if that text matches the expressions that the plugin is using.

Here are the regex expressions that the plugins use when privacySetting is set to default:

Regex obfuscated when 'privacySetting' is 'default'
Email: '[a-zA-Z0-9.!#$%&'*+=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*'
SSN: '[0-9]{3}-?[0-9]{2}-?[0-9]{4}'
Phone number: '[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,6}'
Credit card: '[0-9]{4}-?[0-9]{4}-?[0-9]{4}-?[0-9]{4}'
Unformatted SSN, phone number, credit card: '[0-9]{9,16}'
Address: '[0-9]{1,5}.?[0-9]{0,3}\s[a-zA-Z]{2,30}\s[a-zA-Z]{2,15}'
IP address: '(?:[0-9]{1,3}.){3}[0-9]{1,3}'

In addition to setting the privacySetting for the plugins, you can also make adjustments at the HTML element level:

  • Add class="highlight-block" to elements that should be ignored. When the session recording is replayed, an empty placeholder replaces the content.
  • Add class="highlight-mask" to obfuscate specific HTML elements.
  • Add class="highlight-ignore" to input elements to preserve the styling of the input element, but ignore all end user input. This class is only available for <input> elements.
  • When privacySetting is default, you can override obfuscation on a per HTML element basis by adding the data-hl-record="true" attribute to the recorded HTML tag.

Recording network requests and WebSocket events

By default, the observability plugin shows you all the network request durations, response codes, and sizes for a session.

You can configure the options for the observability plugin to additionally record the headers and bodies of network requests and responses.

Here’s how:

Plugin options, JS SDK v3.7+
1const client = initialize('client-side-id-123abc', context, {
2 plugins: [
3 new Observability(OBSERVABILITY_PROJECT_ID, {
4 networkRecording: {
5 enabled: true,
6 recordHeadersAndBody: true
7 }
8 }),
9 new SessionReplay(OBSERVABILITY_PROJECT_ID)
10 ]
11});

By default, the plugins do not record the following headers:

  • Authorization
  • Cookie
  • Proxy-Authorization

To redact other headers, set networkRecording.networkHeadersToRedact. To redact specific keys in the request/response body, set networkRecording.networkBodyKeysToRedact. Alternatively, you can use an allowlist, and set networkRecording.headerKeysToRecord and networkRecording.bodyKeysToRecord.

By default, the plugins do not record the following URLs:

  • https://www.googleapis.com/identitytoolkit
  • https://securetoken.googleapis.com

To redact other URLs, for example if you have APIs that you know will always return secrets in their headers, body, or both, add the option urlBlocklist to your plugin options and set it to a list of URLs:

Plugin options, JS SDK v3.7+
1const client = initialize('client-side-id-123abc', context, {
2 plugins: [
3 new Observability(OBSERVABILITY_PROJECT_ID, {
4 networkRecording: {
5 enabled: true,
6 recordHeadersAndBody: true
7 },
8 urlBlocklist: [
9 'https://salted-passwords.com',
10 ]
11 }),
12 new SessionReplay(OBSERVABILITY_PROJECT_ID)
13 ]
14});

If none of these options are specific enough, you can write your own method to sanitize network responses. Define a networkRecording.requestResponseSanitizer function that receives a request/response pair and returns either null, if you want to drop the request entirely, or a sanitized request/response pair. We do not recommend dropping requests completely unless absolutely necessary, as it can cause issues with debugging due to the missing requests. Instead, we recommend deleting or redacting header and body fields in your requestResponseSanitizer function.

When networkRecording.recordHeadersAndBody is true, the plugins record all of the WebSocket events in your sessions, including opening a connection, sending and receiving messages, receiving an error, and closing a connection.

To disable WebSocket events, but keep recording the headers and bodies of network requests, set networkRecording.disableWebSocketEventRecordings to true.

Console messages

By default, the plugins show the console messages that were logged during a session.

To disable console recording, set disableConsoleRecording to true when you configure the plugin options for the observability plugin or the session replay plugin.

To specify which console methods to record, set consoleMethodsToRecord.

Canvas and WebGL

When you configure the plugin options for the observability plugin or the session replay plugin, you can set up recording of <canvas> elements. This includes <canvas> elements that use WebGL.

Here’s how:

Recording options, JS SDK v3.7+
1const client = initialize('client-side-id-123abc', context, {
2 plugins: [
3 new SessionReplay(OBSERVABILITY_PROJECT_ID, {
4 enableCanvasRecording: true, // enable canvas recording
5 samplingStrategy: {
6 canvasManualSnapshot: 2, // snapshot at 2 fps
7 canvasMaxSnapshotDimension: 480, // snapshot at a max 480p resolution
8 },
9 })
10 ]
11});

The samplingStrategy options include the following:

  • samplingStrategy.canvas is the frame per second rate used to record the HTML canvas. We recommend using a value of less than 5 to ensure the recording is not too large and does not have issues with playback.
  • samplingStrategy.canvasManualSnapshot is the frame per second rate used in manual snapshotting mode.
  • samplingStrategy.canvasFactor is the resolution scaling factor applied to both dimensions of the canvas.
  • samplingStrategy.canvasMaxSnapshotDimension is the maximum recording resolution of the largest dimension of the canvas.
  • samplingStrategy.canvasClearWebGLBuffer disables WebGL buffer clearing when set to false. This may help if the canvas flickers when recording.
  • samplingStrategy.canvasInitialSnapshotDelay is the time in milliseconds to wait before the initial snapshot of canvas/video elements.

Working with iframes

You can record <canvas> elements within an <iframe>. However, you should be aware of the following caveats:

  • The iframe will not load if the source’s origin has a restrictive X-Frame-Options header.
  • If the iframe source becomes invalid after some time, or does not render content when inserted into a different domain, the session recording will not show the content that the end user saw.

By default, LaunchDarkly only supports recording same-origin iframes. If you can initialize the SDK and observability plugin within the iframe, you can record the events as a separate session.

In some cases, you may need to record a cross-origin iframe. These are <iframe> elements in your application that reference a domain considered to be part of a different origin. When your iframe uses a src tag pointing to a different origin, the iframe is not accessible from the parent page. However, the iframe can still emit messages that the parent page can hear.

To support cross-origin iframes, set the recordCrossOriginIframe option to true when you initialize the SDK in both the parent window and the iframe.

Here’s how:

Plugin options, JS SDK v3.7+
1const client = initialize('client-side-id-123abc', context, {
2 plugins: [
3 new Observability(OBSERVABILITY_PROJECT_ID),
4 new SessionReplay(OBSERVABILITY_PROJECT_ID, {
5 recordCrossOriginIframe: true
6 })
7 ]
8});

If your application is deployed into a cross-origin iframe of a parent application that you do not control, set the recordCrossOriginIframe option to false. This starts the recording for the iframe in standalone mode, and records a session with just the contents of the iframe.

To learn more, read recordCrossOriginIframe in HighlightOptions.

Fullstack mapping

We recommend instrumenting your application so that you can attribute frontend requests with backend errors and logs.

To do this, set following plugin options:

  • tracingOrigins:
    • set to true to include all domains and subdomains of the URL for your frontend application.
    • set to an array of patterns matching the location of your backend if you want to include specific URLs. You’ll need to use this option if your application makes cross-origin requests that you would like to trace.
  • networkRecording:
    • set enabled to true
    • set recordHeadersAndBody to true

Here’s how:

Plugin options, JS SDK v3.7+
1const client = initialize('client-side-id-123abc', context, {
2 plugins: [
3 new Observability(OBSERVABILITY_PROJECT_ID, {
4 tracingOrigins: true,
5 networkRecording: {
6 enabled: true,
7 recordHeadersAndBody: true
8 }
9 })
10 ]
11});

Versioning sessions and errors

When you configure the plugin options for the observability plugin or the session replay plugin, you can optionally set a version field. The version is then included in the error and session views in the LaunchDarkly UI.

This version field is configured manually, and is separate from any versions that may be set if you configure automatic environment attributes in the LaunchDarkly SDK.

Monkey patches

When the observability plugins run, they monkey patch browser APIs in order to record errors, console messages, network requests, and changes on the page.

Browser APIs subject to monkey patching

Here is a list of the browser APIs that the LaunchDarkly observability plugins may monkey patch:

  • window.sessionStorage.setItem
  • window.sessionStorage.getItem
  • window.sessionStorage.removeItem
  • window.onerror
  • window.fetch
  • window.FontFace
  • window.scroll
  • window.scrollTo
  • window.scrollBy
  • window.scrollIntoView
  • window.WebGLRenderingContext
  • window.WebGL2RenderingContext
  • window.CanvasRenderingContext2D
  • window.HTMLCanvasElement
  • window.CSSStyleSheet.prototype.insertRule
  • window.CSSStyleSheet.prototype.deleteRule
  • window.CSSGroupingRule
  • window.CSSMediaRule
  • window.CSSConditionRule
  • window.CSSSupportsRule
  • window.CSSStyleDeclaration.prototype.setProperty
  • window.CSSStyleDeclaration.prototype.removeProperty
  • history.pushState
  • history.replaceState
  • XMLHttpRequest.prototype.open
  • XMLHttpRequest.prototype.setRequestHeader
  • XMLHttpRequest.prototype.send
  • console.assert
  • console.clear
  • console.count
  • console.countReset
  • console.debug
  • console.dir
  • console.dirxml
  • console.error
  • console.group
  • console.groupCollapsed
  • console.groupEnd
  • console.info
  • console.log
  • console.table
  • console.time
  • console.timeEnd
  • console.timeLog
  • console.trace
  • console.warn

Plugin features

The observability plugin supports recording errors, creating and sending logs, adding tracing spans, and recording metrics. To learn more, read Explore supported features in the Observability plugin topic.

The session replay plugin supports recording the canvas in your application, starting and stopping session recording, and getting session information. To learn more, read Explore supported features in the Session replay plugin topic.