Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/light-regions-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'highlight.run': patch
'@launchdarkly/observability': patch
'@launchdarkly/session-replay': patch
---

remove verbosity of user instrumentation events by default.
only reports click, input, and submit window events as spans unless `otel.eventNames` is provided.
1 change: 1 addition & 0 deletions e2e/angular/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{
"compileOnSave": false,
"compilerOptions": {
"skipLibCheck": true,
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,
Expand Down
1 change: 1 addition & 0 deletions e2e/react-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@launchdarkly/observability": "workspace:*",
"@launchdarkly/session-replay": "workspace:*",
"launchdarkly-js-client-sdk": "^3.7.0",
"launchdarkly-react-client-sdk": "^3.7.0",
"localforage": "^1.10.0",
"match-sorter": "^6.3.1",
"react": "^19.0.0",
Expand Down
33 changes: 33 additions & 0 deletions e2e/react-router/src/ldclient.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// import { initialize as init } from '@launchdarkly/js-client-sdk'
import { initialize as init } from 'launchdarkly-js-client-sdk'
import Observability from '@launchdarkly/observability'
import SessionReplay from '@launchdarkly/session-replay'
// import { LD } from '@launchdarkly/browser'

export const client = init(
'66d9d3c255856f0fa8fd62d0',
{ key: 'unknown' },
{
// Not including plugins at all would be equivalent to the current LaunchDarkly SDK.
plugins: [
new Observability('1', {
networkRecording: {
enabled: true,
recordHeadersAndBody: true,
},
serviceName: 'ryan-test',
backendUrl: 'https://pub.observability.ld-stg.launchdarkly.com',
otel: {
otlpEndpoint:
'https://otel.observability.ld-stg.launchdarkly.com',
},
}),
new SessionReplay('1', {
debug: { clientInteractions: true, domRecording: true },
privacySetting: 'none',
serviceName: 'ryan-test',
backendUrl: 'https://pub.observability.ld-stg.launchdarkly.com',
}), // Could be omitted for customers who cannot use session replay.
],
},
)
24 changes: 14 additions & 10 deletions e2e/react-router/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
useRouteError,
} from 'react-router-dom'
import Root from './routes/root'
import Welcome from './routes/welcome'

function rootAction() {
const contact = { name: 'hello' }
Expand Down Expand Up @@ -41,17 +42,20 @@ export function ErrorPage() {

const router = createBrowserRouter(
createRoutesFromElements(
<Route
path="/"
element={<Root />}
loader={rootLoader}
action={rootAction}
ErrorBoundary={ErrorPage}
>
<Route>
<Route index element={<Root />} />
<>
<Route
path="/"
element={<Root />}
loader={rootLoader}
action={rootAction}
ErrorBoundary={ErrorPage}
>
<Route>
<Route index element={<Root />} />
</Route>
</Route>
</Route>,
<Route path={'/welcome'} element={<Welcome />} />
</>,
),
)

Expand Down
36 changes: 3 additions & 33 deletions e2e/react-router/src/routes/root.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,7 @@
// import { initialize as init } from '@launchdarkly/js-client-sdk'
import { initialize as init } from 'launchdarkly-js-client-sdk'
import Observability, { LDObserve } from '@launchdarkly/observability'
import SessionReplay, { LDRecord } from '@launchdarkly/session-replay'
import { LDObserve } from '@launchdarkly/observability'
import { LDRecord } from '@launchdarkly/session-replay'
import { useEffect, useRef, useState } from 'react'
// import { LD } from '@launchdarkly/browser'

const client = init(
'66d9d3c255856f0fa8fd62d0',
{ key: 'unknown' },
{
// Not including plugins at all would be equivalent to the current LaunchDarkly SDK.
plugins: [
new Observability('1', {
networkRecording: {
enabled: true,
recordHeadersAndBody: true,
},
serviceName: 'ryan-test',
backendUrl: 'https://pub.observability.ld-stg.launchdarkly.com',
otel: {
otlpEndpoint:
'https://otel.observability.ld-stg.launchdarkly.com',
},
}),
new SessionReplay('1', {
debug: { clientInteractions: true, domRecording: true },
privacySetting: 'none',
serviceName: 'ryan-test',
backendUrl: 'https://pub.observability.ld-stg.launchdarkly.com',
}), // Could be omitted for customers who cannot use session replay.
],
},
)
import { client } from '../ldclient'

export default function Root() {
const fillColor = 'lightblue'
Expand Down
34 changes: 34 additions & 0 deletions e2e/react-router/src/routes/welcome.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useEffect } from 'react'
import { useFlags, useLDClient } from 'launchdarkly-react-client-sdk'
import Observability from '@launchdarkly/observability'
import SessionReplay from '@launchdarkly/session-replay'

function Welcome() {
const { devTestFlag, observabilityEnabled } = useFlags()
const client = useLDClient()

useEffect(() => {
if (observabilityEnabled && client) {
const plugins = [
new Observability('<observability-id>'),
new SessionReplay('<observability-id>'),
]
plugins.forEach((plugin) =>
plugin.register(client, {
sdk: { name: '', version: '' },
clientSideId: '<launchdarkly-client-side-id>',
}),
)
}
}, [observabilityEnabled, client])

return (
<p>
welcome to this page!
<br />
{devTestFlag ? <b>Flag on</b> : <b>Flag off</b>}
</p>
)
}

export default Welcome
1 change: 1 addition & 0 deletions sdk/highlight-run/src/client/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ export class Highlight {
serviceName:
this.options?.serviceName ?? 'highlight-browser',
instrumentations: this.options?.otel?.instrumentations,
eventNames: this.options?.otel?.eventNames,
getIntegrations: () => [...this._integrations],
},
sampler,
Expand Down
8 changes: 7 additions & 1 deletion sdk/highlight-run/src/client/otel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import { LD_METRIC_NAME_DOCUMENT_LOAD } from '../../integrations/launchdarkly'

import { ExportSampler } from './sampling/ExportSampler'
import { getPersistentSessionSecureID } from '../utils/sessionStorage/highlightSession'
import type { EventName } from '@opentelemetry/instrumentation-user-interaction'
export type Callback = (span?: Span) => any

export type BrowserTracingConfig = {
Expand All @@ -69,6 +70,7 @@ export type BrowserTracingConfig = {
serviceName?: string
tracingOrigins?: boolean | (string | RegExp)[]
urlBlocklist?: string[]
eventNames?: EventName[]
instrumentations?: OtelInstrumentatonOptions
getIntegrations?: () => IntegrationClient[]
}
Expand Down Expand Up @@ -184,7 +186,11 @@ export const setupBrowserTracing = (
'@opentelemetry/instrumentation-user-interaction'
]
if (userInteractionConfig !== false) {
instrumentations.push(new UserInteractionInstrumentation())
instrumentations.push(
new UserInteractionInstrumentation({
eventNames: config.eventNames,
}),
)
}

if (config.networkRecordingOptions?.enabled) {
Expand Down
9 changes: 7 additions & 2 deletions sdk/highlight-run/src/client/otel/user-interaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { AsyncTask } from '@opentelemetry/instrumentation-user-interaction/build

const ZONE_CONTEXT_KEY = 'OT_ZONE_CONTEXT'
const EVENT_NAVIGATION_NAME = 'Navigation:'
const DEFAULT_EVENT_NAMES = ['click', 'input', 'submit'] as const

function defaultShouldPreventSpanCreation() {
return false
Expand All @@ -40,6 +41,7 @@ export class UserInteractionInstrumentation extends InstrumentationBase {
Event,
api.Span
>()
private _eventNames: Set<EventName>
private _shouldPreventSpanCreation: ShouldPreventSpanCreation

constructor(config: UserInteractionInstrumentationConfig = {}) {
Expand All @@ -48,6 +50,9 @@ export class UserInteractionInstrumentation extends InstrumentationBase {
UserInteractionInstrumentation.version,
config,
)
this._eventNames = new Set(
(config?.eventNames ?? DEFAULT_EVENT_NAMES) as EventName[],
)
this._shouldPreventSpanCreation =
typeof config?.shouldPreventSpanCreation === 'function'
? config.shouldPreventSpanCreation
Expand Down Expand Up @@ -81,8 +86,8 @@ export class UserInteractionInstrumentation extends InstrumentationBase {
/**
* Controls whether or not to create a span, based on the event type.
*/
protected _allowEventName(_: EventName): boolean {
return true
protected _allowEventName(eventName: EventName): boolean {
return this._eventNames.has(eventName)
}

/**
Expand Down
2 changes: 2 additions & 0 deletions sdk/highlight-run/src/client/types/client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { RequestResponsePair } from '../listeners/network-listener/utils/models'
import type { EventName } from '@opentelemetry/instrumentation-user-interaction'

export const ALL_CONSOLE_METHODS = [
'assert',
Expand Down Expand Up @@ -140,6 +141,7 @@ export type NetworkRecordingOptions = {

export type OtelOptions = {
instrumentations?: OtelInstrumentatonOptions
eventNames?: EventName[]
}

export type OtelInstrumentatonOptions = {
Expand Down
6 changes: 6 additions & 0 deletions sdk/highlight-run/src/client/types/observe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
OtelOptions,
} from './client'
import type { CommonOptions } from './types'
import type { EventName } from '@opentelemetry/instrumentation-user-interaction'

export type ObserveOptions = CommonOptions & {
/**
Expand Down Expand Up @@ -60,5 +61,10 @@ export type ObserveOptions = CommonOptions & {
* OTLP HTTP endpoint for OpenTelemetry tracing.
*/
otlpEndpoint?: string
/**
* User interaction instrumentation event names to record.
* Defaults to 'click', 'input', 'submit' window events.
*/
eventNames?: EventName[]
}
}
1 change: 1 addition & 0 deletions sdk/highlight-run/src/plugins/observe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export class Observe extends Plugin<ObserveOptions> implements LDPlugin {
tracingOrigins: options?.tracingOrigins,
serviceName: options?.serviceName ?? 'browser',
instrumentations: options?.otel?.instrumentations,
eventNames: options?.otel?.eventNames,
}
this.observe = new ObserveSDK(clientOptions)
LDObserve.load(this.observe)
Expand Down
17 changes: 16 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -25426,7 +25426,7 @@ __metadata:
languageName: unknown
linkType: soft

"hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1":
"hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2":
version: 3.3.2
resolution: "hoist-non-react-statics@npm:3.3.2"
dependencies:
Expand Down Expand Up @@ -29024,6 +29024,20 @@ __metadata:
languageName: node
linkType: hard

"launchdarkly-react-client-sdk@npm:^3.7.0":
version: 3.7.0
resolution: "launchdarkly-react-client-sdk@npm:3.7.0"
dependencies:
hoist-non-react-statics: "npm:^3.3.2"
launchdarkly-js-client-sdk: "npm:^3.7.0"
lodash.camelcase: "npm:^4.3.0"
peerDependencies:
react: ^16.6.3 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0
checksum: 10/bff2dea3e49d7e99062f605727f991445a7e321debd6a52a567b5935c0eeb18de8511914547f0b49178a6d032424e5614b74c361c134e64cfc50a354dd0c26c7
languageName: node
linkType: hard

"less-loader@npm:12.2.0":
version: 12.2.0
resolution: "less-loader@npm:12.2.0"
Expand Down Expand Up @@ -35611,6 +35625,7 @@ __metadata:
eslint-plugin-react-hooks: "npm:^4.6.0"
eslint-plugin-react-refresh: "npm:^0.4.1"
launchdarkly-js-client-sdk: "npm:^3.7.0"
launchdarkly-react-client-sdk: "npm:^3.7.0"
localforage: "npm:^1.10.0"
match-sorter: "npm:^6.3.1"
react: "npm:^19.0.0"
Expand Down
Loading