Skip to content

Commit 3f513ca

Browse files
authored
remove verbosity of user instrumentation events by default (#66)
## Summary Ensure we do not emit as many span events by default. Introduces a new setting `otel.eventNames` that allows customizing the event list. ## How did you test this change? local deploy default <img width="1534" alt="Screenshot 2025-05-28 at 19 29 59" src="https://github.com/user-attachments/assets/c74af7a0-3c6f-484e-b261-c998b0f34e0a" /> changing `otel.eventNames` to `['mousemove']` <img width="1543" alt="Screenshot 2025-05-28 at 19 24 05" src="https://github.com/user-attachments/assets/cbacf504-dee8-47b6-b58e-adbcdbd9731a" /> ## Are there any deployment considerations? changeset ## Does this work require review from our design team? no
1 parent 951d948 commit 3f513ca

File tree

14 files changed

+134
-47
lines changed

14 files changed

+134
-47
lines changed

.changeset/light-regions-brake.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'highlight.run': patch
3+
'@launchdarkly/observability': patch
4+
'@launchdarkly/session-replay': patch
5+
---
6+
7+
remove verbosity of user instrumentation events by default.
8+
only reports click, input, and submit window events as spans unless `otel.eventNames` is provided.

e2e/angular/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{
33
"compileOnSave": false,
44
"compilerOptions": {
5+
"skipLibCheck": true,
56
"outDir": "./dist/out-tsc",
67
"forceConsistentCasingInFileNames": true,
78
"strict": true,

e2e/react-router/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"@launchdarkly/observability": "workspace:*",
1616
"@launchdarkly/session-replay": "workspace:*",
1717
"launchdarkly-js-client-sdk": "^3.7.0",
18+
"launchdarkly-react-client-sdk": "^3.7.0",
1819
"localforage": "^1.10.0",
1920
"match-sorter": "^6.3.1",
2021
"react": "^19.0.0",

e2e/react-router/src/ldclient.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// import { initialize as init } from '@launchdarkly/js-client-sdk'
2+
import { initialize as init } from 'launchdarkly-js-client-sdk'
3+
import Observability from '@launchdarkly/observability'
4+
import SessionReplay from '@launchdarkly/session-replay'
5+
// import { LD } from '@launchdarkly/browser'
6+
7+
export const client = init(
8+
'66d9d3c255856f0fa8fd62d0',
9+
{ key: 'unknown' },
10+
{
11+
// Not including plugins at all would be equivalent to the current LaunchDarkly SDK.
12+
plugins: [
13+
new Observability('1', {
14+
networkRecording: {
15+
enabled: true,
16+
recordHeadersAndBody: true,
17+
},
18+
serviceName: 'ryan-test',
19+
backendUrl: 'https://pub.observability.ld-stg.launchdarkly.com',
20+
otel: {
21+
otlpEndpoint:
22+
'https://otel.observability.ld-stg.launchdarkly.com',
23+
},
24+
}),
25+
new SessionReplay('1', {
26+
debug: { clientInteractions: true, domRecording: true },
27+
privacySetting: 'none',
28+
serviceName: 'ryan-test',
29+
backendUrl: 'https://pub.observability.ld-stg.launchdarkly.com',
30+
}), // Could be omitted for customers who cannot use session replay.
31+
],
32+
},
33+
)

e2e/react-router/src/main.tsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
useRouteError,
1010
} from 'react-router-dom'
1111
import Root from './routes/root'
12+
import Welcome from './routes/welcome'
1213

1314
function rootAction() {
1415
const contact = { name: 'hello' }
@@ -41,17 +42,20 @@ export function ErrorPage() {
4142

4243
const router = createBrowserRouter(
4344
createRoutesFromElements(
44-
<Route
45-
path="/"
46-
element={<Root />}
47-
loader={rootLoader}
48-
action={rootAction}
49-
ErrorBoundary={ErrorPage}
50-
>
51-
<Route>
52-
<Route index element={<Root />} />
45+
<>
46+
<Route
47+
path="/"
48+
element={<Root />}
49+
loader={rootLoader}
50+
action={rootAction}
51+
ErrorBoundary={ErrorPage}
52+
>
53+
<Route>
54+
<Route index element={<Root />} />
55+
</Route>
5356
</Route>
54-
</Route>,
57+
<Route path={'/welcome'} element={<Welcome />} />
58+
</>,
5559
),
5660
)
5761

e2e/react-router/src/routes/root.tsx

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,7 @@
1-
// import { initialize as init } from '@launchdarkly/js-client-sdk'
2-
import { initialize as init } from 'launchdarkly-js-client-sdk'
3-
import Observability, { LDObserve } from '@launchdarkly/observability'
4-
import SessionReplay, { LDRecord } from '@launchdarkly/session-replay'
1+
import { LDObserve } from '@launchdarkly/observability'
2+
import { LDRecord } from '@launchdarkly/session-replay'
53
import { useEffect, useRef, useState } from 'react'
6-
// import { LD } from '@launchdarkly/browser'
7-
8-
const client = init(
9-
'66d9d3c255856f0fa8fd62d0',
10-
{ key: 'unknown' },
11-
{
12-
// Not including plugins at all would be equivalent to the current LaunchDarkly SDK.
13-
plugins: [
14-
new Observability('1', {
15-
networkRecording: {
16-
enabled: true,
17-
recordHeadersAndBody: true,
18-
},
19-
serviceName: 'ryan-test',
20-
backendUrl: 'https://pub.observability.ld-stg.launchdarkly.com',
21-
otel: {
22-
otlpEndpoint:
23-
'https://otel.observability.ld-stg.launchdarkly.com',
24-
},
25-
}),
26-
new SessionReplay('1', {
27-
debug: { clientInteractions: true, domRecording: true },
28-
privacySetting: 'none',
29-
serviceName: 'ryan-test',
30-
backendUrl: 'https://pub.observability.ld-stg.launchdarkly.com',
31-
}), // Could be omitted for customers who cannot use session replay.
32-
],
33-
},
34-
)
4+
import { client } from '../ldclient'
355

366
export default function Root() {
377
const fillColor = 'lightblue'
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { useEffect } from 'react'
2+
import { useFlags, useLDClient } from 'launchdarkly-react-client-sdk'
3+
import Observability from '@launchdarkly/observability'
4+
import SessionReplay from '@launchdarkly/session-replay'
5+
6+
function Welcome() {
7+
const { devTestFlag, observabilityEnabled } = useFlags()
8+
const client = useLDClient()
9+
10+
useEffect(() => {
11+
if (observabilityEnabled && client) {
12+
const plugins = [
13+
new Observability('<observability-id>'),
14+
new SessionReplay('<observability-id>'),
15+
]
16+
plugins.forEach((plugin) =>
17+
plugin.register(client, {
18+
sdk: { name: '', version: '' },
19+
clientSideId: '<launchdarkly-client-side-id>',
20+
}),
21+
)
22+
}
23+
}, [observabilityEnabled, client])
24+
25+
return (
26+
<p>
27+
welcome to this page!
28+
<br />
29+
{devTestFlag ? <b>Flag on</b> : <b>Flag off</b>}
30+
</p>
31+
)
32+
}
33+
34+
export default Welcome

sdk/highlight-run/src/client/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ export class Highlight {
601601
serviceName:
602602
this.options?.serviceName ?? 'highlight-browser',
603603
instrumentations: this.options?.otel?.instrumentations,
604+
eventNames: this.options?.otel?.eventNames,
604605
getIntegrations: () => [...this._integrations],
605606
},
606607
sampler,

sdk/highlight-run/src/client/otel/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import { LD_METRIC_NAME_DOCUMENT_LOAD } from '../../integrations/launchdarkly'
5757

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

6263
export type BrowserTracingConfig = {
@@ -69,6 +70,7 @@ export type BrowserTracingConfig = {
6970
serviceName?: string
7071
tracingOrigins?: boolean | (string | RegExp)[]
7172
urlBlocklist?: string[]
73+
eventNames?: EventName[]
7274
instrumentations?: OtelInstrumentatonOptions
7375
getIntegrations?: () => IntegrationClient[]
7476
}
@@ -184,7 +186,11 @@ export const setupBrowserTracing = (
184186
'@opentelemetry/instrumentation-user-interaction'
185187
]
186188
if (userInteractionConfig !== false) {
187-
instrumentations.push(new UserInteractionInstrumentation())
189+
instrumentations.push(
190+
new UserInteractionInstrumentation({
191+
eventNames: config.eventNames,
192+
}),
193+
)
188194
}
189195

190196
if (config.networkRecordingOptions?.enabled) {

sdk/highlight-run/src/client/otel/user-interaction.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { AsyncTask } from '@opentelemetry/instrumentation-user-interaction/build
1515

1616
const ZONE_CONTEXT_KEY = 'OT_ZONE_CONTEXT'
1717
const EVENT_NAVIGATION_NAME = 'Navigation:'
18+
const DEFAULT_EVENT_NAMES = ['click', 'input', 'submit'] as const
1819

1920
function defaultShouldPreventSpanCreation() {
2021
return false
@@ -40,6 +41,7 @@ export class UserInteractionInstrumentation extends InstrumentationBase {
4041
Event,
4142
api.Span
4243
>()
44+
private _eventNames: Set<EventName>
4345
private _shouldPreventSpanCreation: ShouldPreventSpanCreation
4446

4547
constructor(config: UserInteractionInstrumentationConfig = {}) {
@@ -48,6 +50,9 @@ export class UserInteractionInstrumentation extends InstrumentationBase {
4850
UserInteractionInstrumentation.version,
4951
config,
5052
)
53+
this._eventNames = new Set(
54+
(config?.eventNames ?? DEFAULT_EVENT_NAMES) as EventName[],
55+
)
5156
this._shouldPreventSpanCreation =
5257
typeof config?.shouldPreventSpanCreation === 'function'
5358
? config.shouldPreventSpanCreation
@@ -81,8 +86,8 @@ export class UserInteractionInstrumentation extends InstrumentationBase {
8186
/**
8287
* Controls whether or not to create a span, based on the event type.
8388
*/
84-
protected _allowEventName(_: EventName): boolean {
85-
return true
89+
protected _allowEventName(eventName: EventName): boolean {
90+
return this._eventNames.has(eventName)
8691
}
8792

8893
/**

0 commit comments

Comments
 (0)