Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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/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
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
2 changes: 1 addition & 1 deletion e2e/react-router/src/routes/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { useEffect, useRef, useState } from 'react'
// import { LD } from '@launchdarkly/browser'

const client = init(
export const client = init(

Check warning on line 8 in e2e/react-router/src/routes/root.tsx

View workflow job for this annotation

GitHub Actions / Build Yarn Turborepo

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
'66d9d3c255856f0fa8fd62d0',
{ key: 'unknown' },
{
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