Skip to content

Commit 38e5fa8

Browse files
committed
ref(replay): Make session a POJO
To trim down bundle size a bit.
1 parent 3ccbc8a commit 38e5fa8

File tree

9 files changed

+71
-90
lines changed

9 files changed

+71
-90
lines changed

packages/replay/src/session/Session.ts

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { isSampled } from '../util/isSampled';
55

66
type Sampled = false | 'session' | 'error';
77

8-
export interface SessionObject {
8+
export interface Session {
99
id: string;
1010

1111
/**
@@ -24,52 +24,34 @@ export interface SessionObject {
2424
segmentId: number;
2525

2626
/**
27-
* Is the session sampled? `null` if the sampled, otherwise, `session` or `error`
27+
* The ID of the previous session.
28+
* If this is empty, there was no previous session.
29+
*/
30+
previousSessionId?: string;
31+
32+
/**
33+
* Is the session sampled? `false` if not sampled, otherwise, `session` or `error`
2834
*/
2935
sampled: Sampled;
3036
}
3137

3238
/**
33-
* A wrapper for the session object that handles sampling.
39+
* Get a session with defaults & applied sampling.
3440
*/
35-
export class Session {
36-
/**
37-
* Session ID
38-
*/
39-
public readonly id: string;
40-
41-
/**
42-
* Start time of current session
43-
*/
44-
public started: number;
45-
46-
/**
47-
* Last known activity of the session
48-
*/
49-
public lastActivity: number;
50-
51-
/**
52-
* Sequence ID specific to replay updates
53-
*/
54-
public segmentId: number;
55-
56-
/**
57-
* Previous session ID
58-
*/
59-
public previousSessionId: string | undefined;
60-
61-
/**
62-
* Is the Session sampled?
63-
*/
64-
public readonly sampled: Sampled;
65-
66-
public constructor(session: Partial<SessionObject> = {}, { sessionSampleRate, errorSampleRate }: SampleRates) {
67-
const now = new Date().getTime();
68-
this.id = session.id || uuid4();
69-
this.started = session.started ?? now;
70-
this.lastActivity = session.lastActivity ?? now;
71-
this.segmentId = session.segmentId ?? 0;
72-
this.sampled =
73-
session.sampled ?? (isSampled(sessionSampleRate) ? 'session' : isSampled(errorSampleRate) ? 'error' : false);
74-
}
41+
export function makeSession(session: Partial<Session>, { sessionSampleRate, errorSampleRate }: SampleRates): Session {
42+
const now = new Date().getTime();
43+
const id = session.id || uuid4();
44+
const started = session.started ?? now;
45+
const lastActivity = session.lastActivity ?? now;
46+
const segmentId = session.segmentId ?? 0;
47+
const sampled =
48+
session.sampled ?? (isSampled(sessionSampleRate) ? 'session' : isSampled(errorSampleRate) ? 'error' : false);
49+
50+
return {
51+
id,
52+
started,
53+
lastActivity,
54+
segmentId,
55+
sampled,
56+
};
7557
}

packages/replay/src/session/createSession.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@ import { logger } from '@sentry/utils';
22

33
import { SessionOptions } from '../types';
44
import { saveSession } from './saveSession';
5-
import { Session } from './Session';
5+
import { makeSession, Session } from './Session';
66

77
/**
88
* Create a new session, which in its current implementation is a Sentry event
99
* that all replays will be saved to as attachments. Currently, we only expect
1010
* one of these Sentry events per "replay session".
1111
*/
1212
export function createSession({ sessionSampleRate, errorSampleRate, stickySession = false }: SessionOptions): Session {
13-
const session = new Session(undefined, {
14-
errorSampleRate,
15-
sessionSampleRate,
16-
});
13+
const session = makeSession(
14+
{},
15+
{
16+
errorSampleRate,
17+
sessionSampleRate,
18+
},
19+
);
1720

1821
__DEBUG_BUILD__ && logger.log(`[Replay] Creating new session: ${session.id}`);
1922

packages/replay/src/session/fetchSession.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { REPLAY_SESSION_KEY, WINDOW } from '../constants';
22
import { SampleRates } from '../types';
3-
import { Session } from './Session';
3+
import { makeSession, Session } from './Session';
44

55
/**
66
* Fetches a session from storage
@@ -22,7 +22,7 @@ export function fetchSession({ sessionSampleRate, errorSampleRate }: SampleRates
2222

2323
const sessionObj = JSON.parse(sessionStringFromStorage);
2424

25-
return new Session(sessionObj, { sessionSampleRate, errorSampleRate });
25+
return makeSession(sessionObj, { sessionSampleRate, errorSampleRate });
2626
} catch {
2727
return null;
2828
}

packages/replay/test/unit/session/Session.test.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jest.mock('@sentry/utils', () => {
2626
import * as Sentry from '@sentry/browser';
2727

2828
import { WINDOW } from '../../../src/constants';
29-
import { Session } from '../../../src/session/Session';
29+
import { makeSession } from '../../../src/session/Session';
3030

3131
type CaptureEventMockType = jest.MockedFunction<typeof Sentry.captureEvent>;
3232

@@ -39,34 +39,43 @@ afterEach(() => {
3939
});
4040

4141
it('does not sample', function () {
42-
const newSession = new Session(undefined, {
43-
sessionSampleRate: 0.0,
44-
errorSampleRate: 0.0,
45-
});
42+
const newSession = makeSession(
43+
{},
44+
{
45+
sessionSampleRate: 0.0,
46+
errorSampleRate: 0.0,
47+
},
48+
);
4649

4750
expect(newSession.sampled).toBe(false);
4851
});
4952

5053
it('samples using `sessionSampleRate`', function () {
51-
const newSession = new Session(undefined, {
52-
sessionSampleRate: 1.0,
53-
errorSampleRate: 0.0,
54-
});
54+
const newSession = makeSession(
55+
{},
56+
{
57+
sessionSampleRate: 1.0,
58+
errorSampleRate: 0.0,
59+
},
60+
);
5561

5662
expect(newSession.sampled).toBe('session');
5763
});
5864

5965
it('samples using `errorSampleRate`', function () {
60-
const newSession = new Session(undefined, {
61-
sessionSampleRate: 0,
62-
errorSampleRate: 1.0,
63-
});
66+
const newSession = makeSession(
67+
{},
68+
{
69+
sessionSampleRate: 0,
70+
errorSampleRate: 1.0,
71+
},
72+
);
6473

6574
expect(newSession.sampled).toBe('error');
6675
});
6776

6877
it('does not run sampling function if existing session was sampled', function () {
69-
const newSession = new Session(
78+
const newSession = makeSession(
7079
{
7180
sampled: 'session',
7281
},

packages/replay/test/unit/session/fetchSession.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { REPLAY_SESSION_KEY, WINDOW } from '../../../src/constants';
22
import { fetchSession } from '../../../src/session/fetchSession';
3-
import { sessionToJSON } from '../../utils/sessionToJson';
43

54
const oldSessionStorage = WINDOW.sessionStorage;
65

@@ -27,7 +26,7 @@ it('fetches a valid and sampled session', function () {
2726
'{"id":"fd09adfc4117477abc8de643e5a5798a","sampled": true,"started":1648827162630,"lastActivity":1648827162658}',
2827
);
2928

30-
expect(sessionToJSON(fetchSession(SAMPLE_RATES)!)).toEqual({
29+
expect(fetchSession(SAMPLE_RATES)).toEqual({
3130
id: 'fd09adfc4117477abc8de643e5a5798a',
3231
lastActivity: 1648827162658,
3332
segmentId: 0,

packages/replay/test/unit/session/getSession.test.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ import * as CreateSession from '../../../src/session/createSession';
33
import * as FetchSession from '../../../src/session/fetchSession';
44
import { getSession } from '../../../src/session/getSession';
55
import { saveSession } from '../../../src/session/saveSession';
6-
import { Session } from '../../../src/session/Session';
7-
import { sessionToJSON } from '../../utils/sessionToJson';
6+
import { makeSession } from '../../../src/session/Session';
87

98
jest.mock('@sentry/utils', () => {
109
return {
@@ -19,7 +18,7 @@ const SAMPLE_RATES = {
1918
};
2019

2120
function createMockSession(when: number = new Date().getTime()) {
22-
return new Session(
21+
return makeSession(
2322
{
2423
id: 'test_session_id',
2524
segmentId: 0,
@@ -53,7 +52,7 @@ it('creates a non-sticky session when one does not exist', function () {
5352
expect(FetchSession.fetchSession).not.toHaveBeenCalled();
5453
expect(CreateSession.createSession).toHaveBeenCalled();
5554

56-
expect(sessionToJSON(session)).toEqual({
55+
expect(session).toEqual({
5756
id: 'test_session_id',
5857
segmentId: 0,
5958
lastActivity: expect.any(Number),
@@ -85,7 +84,7 @@ it('creates a non-sticky session, when one is expired', function () {
8584
expiry: 1000,
8685
stickySession: false,
8786
...SAMPLE_RATES,
88-
currentSession: new Session(
87+
currentSession: makeSession(
8988
{
9089
id: 'old_session_id',
9190
lastActivity: new Date().getTime() - 1001,
@@ -116,7 +115,7 @@ it('creates a sticky session when one does not exist', function () {
116115
expect(FetchSession.fetchSession).toHaveBeenCalled();
117116
expect(CreateSession.createSession).toHaveBeenCalled();
118117

119-
expect(sessionToJSON(session)).toEqual({
118+
expect(session).toEqual({
120119
id: 'test_session_id',
121120
segmentId: 0,
122121
lastActivity: expect.any(Number),
@@ -125,7 +124,7 @@ it('creates a sticky session when one does not exist', function () {
125124
});
126125

127126
// Should not have anything in storage
128-
expect(sessionToJSON(FetchSession.fetchSession(SAMPLE_RATES)!)).toEqual({
127+
expect(FetchSession.fetchSession(SAMPLE_RATES)).toEqual({
129128
id: 'test_session_id',
130129
segmentId: 0,
131130
lastActivity: expect.any(Number),
@@ -148,7 +147,7 @@ it('fetches an existing sticky session', function () {
148147
expect(FetchSession.fetchSession).toHaveBeenCalled();
149148
expect(CreateSession.createSession).not.toHaveBeenCalled();
150149

151-
expect(sessionToJSON(session)).toEqual({
150+
expect(session).toEqual({
152151
id: 'test_session_id',
153152
segmentId: 0,
154153
lastActivity: now,
@@ -181,7 +180,7 @@ it('fetches a non-expired non-sticky session', function () {
181180
expiry: 1000,
182181
stickySession: false,
183182
...SAMPLE_RATES,
184-
currentSession: new Session(
183+
currentSession: makeSession(
185184
{
186185
id: 'test_session_id_2',
187186
lastActivity: +new Date() - 500,

packages/replay/test/unit/session/saveSession.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { REPLAY_SESSION_KEY, WINDOW } from '../../../src/constants';
22
import { saveSession } from '../../../src/session/saveSession';
3-
import { Session } from '../../../src/session/Session';
3+
import { makeSession } from '../../../src/session/Session';
44

55
beforeAll(() => {
66
WINDOW.sessionStorage.clear();
@@ -11,7 +11,7 @@ afterEach(() => {
1111
});
1212

1313
it('saves a valid session', function () {
14-
const session = new Session(
14+
const session = makeSession(
1515
{
1616
id: 'fd09adfc4117477abc8de643e5a5798a',
1717
segmentId: 0,

packages/replay/test/unit/util/isSessionExpired.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Session } from '../../../src/session/Session';
1+
import { makeSession } from '../../../src/session/Session';
22
import { isSessionExpired } from '../../../src/util/isSessionExpired';
33

44
function createSession(extra?: Record<string, any>) {
5-
return new Session(
5+
return makeSession(
66
{
77
started: 0,
88
lastActivity: 0,

packages/replay/test/utils/sessionToJson.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)