Skip to content

Commit 1969e1a

Browse files
feat: add addSessionProperties to RecordSDK (#247)
1 parent 97c72db commit 1969e1a

File tree

5 files changed

+102
-0
lines changed

5 files changed

+102
-0
lines changed

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,42 @@ export default function Root() {
305305
>
306306
LDObserve.stop()
307307
</button>
308+
<div
309+
style={{
310+
marginTop: 8,
311+
padding: 12,
312+
border: '1px solid #ddd',
313+
borderRadius: 6,
314+
maxWidth: 720,
315+
}}
316+
>
317+
<h3>Session Properties</h3>
318+
<p>
319+
Add custom session-level attributes via{' '}
320+
<code>LDRecord.addSessionProperties</code>.
321+
</p>
322+
<textarea
323+
style={{
324+
width: '100%',
325+
minHeight: 120,
326+
fontFamily: 'monospace',
327+
}}
328+
defaultValue='{"plan":"pro","favoriteColor":"seafoam"}'
329+
placeholder='{"key":"value"}'
330+
/>
331+
<div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
332+
<button
333+
onClick={() => {
334+
const value =
335+
document.querySelector('textarea')?.value ?? ''
336+
337+
LDRecord.addSessionProperties(JSON.parse(value))
338+
}}
339+
>
340+
Apply session properties
341+
</button>
342+
</div>
343+
</div>
308344
</div>
309345
)
310346
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { beforeEach, describe, expect, it, vi } from 'vitest'
2+
3+
vi.mock('../client/workers/highlight-client-worker?worker&inline', () => {
4+
class FakeWorker {
5+
onmessage = (_e: any) => {}
6+
postMessage = vi.fn((_message: any) => null)
7+
}
8+
return { default: FakeWorker }
9+
})
10+
11+
import { RecordSDK } from '../sdk/record'
12+
import { LDRecord } from '../sdk/LDRecord'
13+
import { MessageType } from '../client/workers/types'
14+
15+
describe('Record addSessionProperties', () => {
16+
let recordImpl: RecordSDK
17+
18+
beforeEach(() => {
19+
recordImpl = new RecordSDK({
20+
organizationID: '1',
21+
environment: 'test',
22+
sessionSecureID: 'test-session',
23+
})
24+
})
25+
26+
it('posts Properties message with session type to the worker', () => {
27+
const postSpy = vi.spyOn((recordImpl as any)._worker, 'postMessage')
28+
29+
const props = { plan: 'pro', count: 1, active: true }
30+
recordImpl.addSessionProperties(props)
31+
32+
expect(postSpy).toHaveBeenCalled()
33+
const call = postSpy.mock.calls[0]?.[0] as any
34+
expect(call?.message?.type).toBe(MessageType.Properties)
35+
expect(call?.message?.propertyType).toEqual({ type: 'session' })
36+
expect(call?.message?.propertiesObject).toMatchObject(props)
37+
})
38+
39+
it('LDRecord proxies addSessionProperties to implementation', () => {
40+
// Load the implementation into the LDRecord buffered proxy
41+
LDRecord.load(recordImpl)
42+
43+
const spy = vi.spyOn(recordImpl, 'addSessionProperties')
44+
const props = { foo: 'bar' }
45+
LDRecord.addSessionProperties(props)
46+
47+
expect(spy).toHaveBeenCalledWith(props)
48+
})
49+
})

sdk/highlight-run/src/api/record.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ export interface Record {
1414
* Stop the session recording.
1515
*/
1616
stop: () => void
17+
/**
18+
* Add custom session-level properties. These are attached to the current session
19+
* and are searchable, but do not create timeline Track events.
20+
*/
21+
addSessionProperties: (properties: { [key: string]: any }) => void
1722
/**
1823
* Snapshot an HTML <canvas> element in WebGL manual snapshotting mode.
1924
* See {@link https://www.highlight.io/docs/getting-started/browser/replay-configuration/canvas#manual-snapshotting}

sdk/highlight-run/src/sdk/LDRecord.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ class _LDRecord extends BufferedClass<Record> implements Record {
2020
return this._sdk.stop()
2121
}
2222

23+
addSessionProperties(properties: { [key: string]: any }) {
24+
return this._bufferCall('addSessionProperties', [properties])
25+
}
26+
2327
getRecordingState() {
2428
return this._isLoaded
2529
? this._bufferCall('getRecordingState', [])

sdk/highlight-run/src/sdk/record.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,14 @@ export class RecordSDK implements Record {
403403
})
404404
}
405405

406+
/**
407+
* Add custom session-level properties. These are attached to the current session
408+
* and are searchable, but do not create timeline Track events.
409+
*/
410+
addSessionProperties(properties: { [key: string]: any }) {
411+
this.addProperties(properties, { type: 'session' })
412+
}
413+
406414
async start(options?: StartOptions) {
407415
if (
408416
navigator?.userAgent?.includes('Googlebot') ||

0 commit comments

Comments
 (0)