UNPKG

5.05 kBJavaScriptView Raw
1Object.defineProperty(exports, '__esModule', { value: true });
2
3const utils = require('@sentry/utils');
4
5/**
6 * Creates a new `Session` object by setting certain default parameters. If optional @param context
7 * is passed, the passed properties are applied to the session object.
8 *
9 * @param context (optional) additional properties to be applied to the returned session object
10 *
11 * @returns a new `Session` object
12 */
13function makeSession(context) {
14 // Both timestamp and started are in seconds since the UNIX epoch.
15 const startingTime = utils.timestampInSeconds();
16
17 const session = {
18 sid: utils.uuid4(),
19 init: true,
20 timestamp: startingTime,
21 started: startingTime,
22 duration: 0,
23 status: 'ok',
24 errors: 0,
25 ignoreDuration: false,
26 toJSON: () => sessionToJSON(session),
27 };
28
29 if (context) {
30 updateSession(session, context);
31 }
32
33 return session;
34}
35
36/**
37 * Updates a session object with the properties passed in the context.
38 *
39 * Note that this function mutates the passed object and returns void.
40 * (Had to do this instead of returning a new and updated session because closing and sending a session
41 * makes an update to the session after it was passed to the sending logic.
42 * @see BaseClient.captureSession )
43 *
44 * @param session the `Session` to update
45 * @param context the `SessionContext` holding the properties that should be updated in @param session
46 */
47// eslint-disable-next-line complexity
48function updateSession(session, context = {}) {
49 if (context.user) {
50 if (!session.ipAddress && context.user.ip_address) {
51 session.ipAddress = context.user.ip_address;
52 }
53
54 if (!session.did && !context.did) {
55 session.did = context.user.id || context.user.email || context.user.username;
56 }
57 }
58
59 session.timestamp = context.timestamp || utils.timestampInSeconds();
60
61 if (context.ignoreDuration) {
62 session.ignoreDuration = context.ignoreDuration;
63 }
64 if (context.sid) {
65 // Good enough uuid validation. — Kamil
66 session.sid = context.sid.length === 32 ? context.sid : utils.uuid4();
67 }
68 if (context.init !== undefined) {
69 session.init = context.init;
70 }
71 if (!session.did && context.did) {
72 session.did = `${context.did}`;
73 }
74 if (typeof context.started === 'number') {
75 session.started = context.started;
76 }
77 if (session.ignoreDuration) {
78 session.duration = undefined;
79 } else if (typeof context.duration === 'number') {
80 session.duration = context.duration;
81 } else {
82 const duration = session.timestamp - session.started;
83 session.duration = duration >= 0 ? duration : 0;
84 }
85 if (context.release) {
86 session.release = context.release;
87 }
88 if (context.environment) {
89 session.environment = context.environment;
90 }
91 if (!session.ipAddress && context.ipAddress) {
92 session.ipAddress = context.ipAddress;
93 }
94 if (!session.userAgent && context.userAgent) {
95 session.userAgent = context.userAgent;
96 }
97 if (typeof context.errors === 'number') {
98 session.errors = context.errors;
99 }
100 if (context.status) {
101 session.status = context.status;
102 }
103}
104
105/**
106 * Closes a session by setting its status and updating the session object with it.
107 * Internally calls `updateSession` to update the passed session object.
108 *
109 * Note that this function mutates the passed session (@see updateSession for explanation).
110 *
111 * @param session the `Session` object to be closed
112 * @param status the `SessionStatus` with which the session was closed. If you don't pass a status,
113 * this function will keep the previously set status, unless it was `'ok'` in which case
114 * it is changed to `'exited'`.
115 */
116function closeSession(session, status) {
117 let context = {};
118 if (status) {
119 context = { status };
120 } else if (session.status === 'ok') {
121 context = { status: 'exited' };
122 }
123
124 updateSession(session, context);
125}
126
127/**
128 * Serializes a passed session object to a JSON object with a slightly different structure.
129 * This is necessary because the Sentry backend requires a slightly different schema of a session
130 * than the one the JS SDKs use internally.
131 *
132 * @param session the session to be converted
133 *
134 * @returns a JSON object of the passed session
135 */
136function sessionToJSON(session) {
137 return utils.dropUndefinedKeys({
138 sid: `${session.sid}`,
139 init: session.init,
140 // Make sure that sec is converted to ms for date constructor
141 started: new Date(session.started * 1000).toISOString(),
142 timestamp: new Date(session.timestamp * 1000).toISOString(),
143 status: session.status,
144 errors: session.errors,
145 did: typeof session.did === 'number' || typeof session.did === 'string' ? `${session.did}` : undefined,
146 duration: session.duration,
147 attrs: {
148 release: session.release,
149 environment: session.environment,
150 ip_address: session.ipAddress,
151 user_agent: session.userAgent,
152 },
153 });
154}
155
156exports.closeSession = closeSession;
157exports.makeSession = makeSession;
158exports.updateSession = updateSession;
159//# sourceMappingURL=session.js.map