@multiplayer-app/session-recorder-node 2.0.17 → 2.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/eslint.config.js +0 -226
- package/examples/cli/package-lock.json +0 -4260
- package/examples/cli/package.json +0 -56
- package/examples/cli/src/config.ts +0 -47
- package/examples/cli/src/index.ts +0 -43
- package/examples/cli/src/opentelemetry.ts +0 -140
- package/examples/cli/tsconfig.json +0 -39
- package/examples/http-server/package-lock.json +0 -5411
- package/examples/http-server/package.json +0 -48
- package/examples/http-server/src/api.ts +0 -20
- package/examples/http-server/src/config.ts +0 -24
- package/examples/http-server/src/index.ts +0 -46
- package/examples/http-server/src/opentelemetry.ts +0 -140
- package/examples/http-server/tsconfig.json +0 -39
- package/src/config.ts +0 -5
- package/src/helper.ts +0 -13
- package/src/index.ts +0 -6
- package/src/integrations/express.ts +0 -52
- package/src/integrations/index.ts +0 -1
- package/src/services/api.service.ts +0 -230
- package/src/sessionRecorder.ts +0 -285
- package/src/types.ts +0 -27
- package/tsconfig.json +0 -38
package/src/sessionRecorder.ts
DELETED
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
SessionType,
|
|
3
|
-
SessionRecorderSdk,
|
|
4
|
-
SessionRecorderIdGenerator,
|
|
5
|
-
ATTR_MULTIPLAYER_SESSION_RECORDER_VERSION,
|
|
6
|
-
MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH,
|
|
7
|
-
} from '@multiplayer-app/session-recorder-common'
|
|
8
|
-
import { ApiService } from './services/api.service'
|
|
9
|
-
import { ISession } from './types'
|
|
10
|
-
import { getFormattedDate } from './helper'
|
|
11
|
-
import { SESSION_RECORDER_VERSION } from './config'
|
|
12
|
-
|
|
13
|
-
export class SessionRecorder {
|
|
14
|
-
private _isInitialized = false
|
|
15
|
-
|
|
16
|
-
private _shortSessionId: string | boolean = false
|
|
17
|
-
|
|
18
|
-
private _traceIdGenerator: SessionRecorderIdGenerator | undefined
|
|
19
|
-
private _sessionType: SessionType = SessionType.MANUAL
|
|
20
|
-
private _sessionState: 'STARTED' | 'STOPPED' | 'PAUSED' = 'STOPPED'
|
|
21
|
-
private _apiService = new ApiService()
|
|
22
|
-
private _sessionShortIdGenerator = SessionRecorderSdk.getIdGenerator(MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH)
|
|
23
|
-
|
|
24
|
-
private _resourceAttributes: object = {}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Initialize session recorder with default or custom configurations
|
|
28
|
-
*/
|
|
29
|
-
constructor() { }
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @description Initialize the session recorder
|
|
33
|
-
* @param config - Configuration object
|
|
34
|
-
* @param config.apiKey - multiplayer otlp key
|
|
35
|
-
* @param config.traceIdGenerator - multiplayer compatible trace id generator
|
|
36
|
-
* @param config.resourceAttributes - Optional resource attributes
|
|
37
|
-
* @param config.generateSessionShortIdLocally - Optional session short ID generator
|
|
38
|
-
* @param config.apiBaseUrl - Optional base API URL override
|
|
39
|
-
*/
|
|
40
|
-
public init(config: {
|
|
41
|
-
apiKey: string,
|
|
42
|
-
traceIdGenerator: SessionRecorderIdGenerator,
|
|
43
|
-
resourceAttributes?: object,
|
|
44
|
-
generateSessionShortIdLocally?: boolean | (() => string),
|
|
45
|
-
apiBaseUrl?: string
|
|
46
|
-
}): void {
|
|
47
|
-
this._resourceAttributes = config.resourceAttributes || {
|
|
48
|
-
[ATTR_MULTIPLAYER_SESSION_RECORDER_VERSION]: SESSION_RECORDER_VERSION,
|
|
49
|
-
}
|
|
50
|
-
this._isInitialized = true
|
|
51
|
-
|
|
52
|
-
if (typeof config.generateSessionShortIdLocally === 'function') {
|
|
53
|
-
this._sessionShortIdGenerator = config.generateSessionShortIdLocally
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (!config?.apiKey?.length) {
|
|
57
|
-
throw new Error('Api key not provided')
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (!config?.traceIdGenerator?.setSessionId) {
|
|
61
|
-
throw new Error('Incompatible trace id generator')
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
this._traceIdGenerator = config.traceIdGenerator
|
|
65
|
-
this._apiService.init({
|
|
66
|
-
apiKey: config.apiKey,
|
|
67
|
-
apiBaseUrl: config.apiBaseUrl,
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @description Start a new session
|
|
73
|
-
* @param {SessionType} SessionType - the type of session to start
|
|
74
|
-
* @param {ISession} [sessionPayload] - session metadata
|
|
75
|
-
* @returns {Promise<void>}
|
|
76
|
-
*/
|
|
77
|
-
public async start(
|
|
78
|
-
sessionType: SessionType,
|
|
79
|
-
sessionPayload?: Omit<ISession, '_id'>,
|
|
80
|
-
): Promise<void> {
|
|
81
|
-
if (!this._isInitialized) {
|
|
82
|
-
throw new Error(
|
|
83
|
-
'Configuration not initialized. Call init() before performing any actions.',
|
|
84
|
-
)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
sessionPayload?.shortId
|
|
89
|
-
&& sessionPayload?.shortId?.length !== MULTIPLAYER_TRACE_DEBUG_SESSION_SHORT_ID_LENGTH
|
|
90
|
-
) {
|
|
91
|
-
throw new Error('Invalid short session id')
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
sessionPayload = sessionPayload || {}
|
|
95
|
-
|
|
96
|
-
if (this._sessionState !== 'STOPPED') {
|
|
97
|
-
throw new Error('Session should be ended before starting new one.')
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
this._sessionType = sessionType
|
|
101
|
-
|
|
102
|
-
let session: ISession
|
|
103
|
-
|
|
104
|
-
sessionPayload.name = sessionPayload.name
|
|
105
|
-
? sessionPayload.name
|
|
106
|
-
: `Session on ${getFormattedDate(Date.now())}`
|
|
107
|
-
|
|
108
|
-
sessionPayload.resourceAttributes = {
|
|
109
|
-
...this._resourceAttributes,
|
|
110
|
-
...sessionPayload.resourceAttributes,
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (this._sessionType === SessionType.CONTINUOUS) {
|
|
114
|
-
session = await this._apiService.startContinuousSession(sessionPayload)
|
|
115
|
-
} else {
|
|
116
|
-
session = await this._apiService.startSession(sessionPayload)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (!session?.shortId) {
|
|
120
|
-
throw new Error('Failed to start session')
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
this._shortSessionId = session.shortId as string
|
|
124
|
-
|
|
125
|
-
(this._traceIdGenerator as SessionRecorderIdGenerator).setSessionId(
|
|
126
|
-
this._shortSessionId,
|
|
127
|
-
this._sessionType,
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
this._sessionState = 'STARTED'
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* @description Save the continuous session
|
|
135
|
-
* @param {String} [reason]
|
|
136
|
-
* @returns {Promise<void>}
|
|
137
|
-
*/
|
|
138
|
-
static async save(reason?: string) {
|
|
139
|
-
SessionRecorderSdk.saveContinuousSession(reason)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* @description Save the continuous session
|
|
144
|
-
* @param {ISession} [sessionData]
|
|
145
|
-
* @returns {Promise<void>}
|
|
146
|
-
*/
|
|
147
|
-
public async save(
|
|
148
|
-
sessionData?: ISession,
|
|
149
|
-
): Promise<void> {
|
|
150
|
-
try {
|
|
151
|
-
if (!this._isInitialized) {
|
|
152
|
-
throw new Error(
|
|
153
|
-
'Configuration not initialized. Call init() before performing any actions.',
|
|
154
|
-
)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (
|
|
158
|
-
this._sessionState === 'STOPPED'
|
|
159
|
-
|| typeof this._shortSessionId !== 'string'
|
|
160
|
-
) {
|
|
161
|
-
throw new Error('Session should be active or paused')
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (this._sessionType !== SessionType.CONTINUOUS) {
|
|
165
|
-
throw new Error('Invalid session type')
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
await this._apiService.saveContinuousSession(
|
|
169
|
-
this._shortSessionId,
|
|
170
|
-
{
|
|
171
|
-
...(sessionData || {}),
|
|
172
|
-
name: sessionData?.name
|
|
173
|
-
? sessionData.name
|
|
174
|
-
: `Session on ${getFormattedDate(Date.now())}`,
|
|
175
|
-
},
|
|
176
|
-
)
|
|
177
|
-
} catch (e) {
|
|
178
|
-
throw e
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* @description Stop the current session with an optional comment
|
|
184
|
-
* @param {ISession} [sessionData] - user-provided comment to include in session metadata
|
|
185
|
-
* @returns {Promise<void>}
|
|
186
|
-
*/
|
|
187
|
-
public async stop(
|
|
188
|
-
sessionData?: ISession,
|
|
189
|
-
): Promise<void> {
|
|
190
|
-
try {
|
|
191
|
-
if (!this._isInitialized) {
|
|
192
|
-
throw new Error(
|
|
193
|
-
'Configuration not initialized. Call init() before performing any actions.',
|
|
194
|
-
)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (
|
|
198
|
-
this._sessionState === 'STOPPED'
|
|
199
|
-
|| typeof this._shortSessionId !== 'string'
|
|
200
|
-
) {
|
|
201
|
-
throw new Error('Session should be active or paused')
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (this._sessionType !== SessionType.MANUAL) {
|
|
205
|
-
throw new Error('Invalid session type')
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
await this._apiService.stopSession(
|
|
209
|
-
this._shortSessionId,
|
|
210
|
-
sessionData || {},
|
|
211
|
-
)
|
|
212
|
-
} catch (e) {
|
|
213
|
-
throw e
|
|
214
|
-
} finally {
|
|
215
|
-
(this._traceIdGenerator as SessionRecorderIdGenerator).setSessionId('')
|
|
216
|
-
|
|
217
|
-
this._shortSessionId = false
|
|
218
|
-
this._sessionState = 'STOPPED'
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* @description Cancel the current session
|
|
224
|
-
* @returns {Promise<void>}
|
|
225
|
-
*/
|
|
226
|
-
public async cancel(): Promise<void> {
|
|
227
|
-
try {
|
|
228
|
-
if (!this._isInitialized) {
|
|
229
|
-
throw new Error(
|
|
230
|
-
'Configuration not initialized. Call init() before performing any actions.',
|
|
231
|
-
)
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (
|
|
235
|
-
this._sessionState === 'STOPPED'
|
|
236
|
-
|| typeof this._shortSessionId !== 'string'
|
|
237
|
-
) {
|
|
238
|
-
throw new Error('Session should be active or paused')
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (this._sessionType === SessionType.CONTINUOUS) {
|
|
242
|
-
await this._apiService.stopContinuousSession(this._shortSessionId)
|
|
243
|
-
} else if (this._sessionType === SessionType.MANUAL) {
|
|
244
|
-
await this._apiService.cancelSession(this._shortSessionId)
|
|
245
|
-
}
|
|
246
|
-
} catch (e) {
|
|
247
|
-
throw e
|
|
248
|
-
} finally {
|
|
249
|
-
(this._traceIdGenerator as SessionRecorderIdGenerator).setSessionId('')
|
|
250
|
-
|
|
251
|
-
this._shortSessionId = false
|
|
252
|
-
this._sessionState = 'STOPPED'
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* @description Check if continuous session should be started/stopped automatically
|
|
258
|
-
* @param {ISession} [sessionPayload]
|
|
259
|
-
* @returns {Promise<void>}
|
|
260
|
-
*/
|
|
261
|
-
public async checkRemoteContinuousSession(
|
|
262
|
-
sessionPayload?: Omit<ISession, '_id' | 'shortId'>,
|
|
263
|
-
): Promise<void> {
|
|
264
|
-
if (!this._isInitialized) {
|
|
265
|
-
throw new Error(
|
|
266
|
-
'Configuration not initialized. Call init() before performing any actions.',
|
|
267
|
-
)
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
sessionPayload = sessionPayload || {}
|
|
271
|
-
|
|
272
|
-
sessionPayload.resourceAttributes = {
|
|
273
|
-
...(sessionPayload.resourceAttributes || {}),
|
|
274
|
-
...this._resourceAttributes,
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const { state } = await this._apiService.checkRemoteSession(sessionPayload)
|
|
278
|
-
|
|
279
|
-
if (state == 'START' && this._sessionState !== 'STARTED') {
|
|
280
|
-
await this.start(SessionType.CONTINUOUS, sessionPayload)
|
|
281
|
-
} else if (state == 'STOP' && this._sessionState !== 'STOPPED') {
|
|
282
|
-
await this.stop()
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export interface ISession {
|
|
2
|
-
_id?: string
|
|
3
|
-
shortId?: string
|
|
4
|
-
name?: string
|
|
5
|
-
resourceAttributes?: {
|
|
6
|
-
browserInfo?: string,
|
|
7
|
-
cookiesEnabled?: string,
|
|
8
|
-
deviceInfo?: string,
|
|
9
|
-
hardwareConcurrency?: string,
|
|
10
|
-
osInfo?: string,
|
|
11
|
-
pixelRatio?: string,
|
|
12
|
-
screenSize?: string,
|
|
13
|
-
} & any
|
|
14
|
-
sessionAttributes?: {
|
|
15
|
-
userEmail?: string
|
|
16
|
-
userId?: string,
|
|
17
|
-
userName?: string,
|
|
18
|
-
accountId?: string,
|
|
19
|
-
accountName?: string,
|
|
20
|
-
|
|
21
|
-
comment?: string
|
|
22
|
-
} & any
|
|
23
|
-
tags?: {
|
|
24
|
-
key?: string
|
|
25
|
-
value: string
|
|
26
|
-
}[]
|
|
27
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"declaration": true,
|
|
4
|
-
"declarationMap": true,
|
|
5
|
-
"baseUrl": ".",
|
|
6
|
-
"noEmit": false,
|
|
7
|
-
"module": "commonjs",
|
|
8
|
-
"noImplicitAny": false,
|
|
9
|
-
"noUnusedParameters": false,
|
|
10
|
-
"allowJs": false,
|
|
11
|
-
"allowSyntheticDefaultImports": true,
|
|
12
|
-
"esModuleInterop": true,
|
|
13
|
-
"forceConsistentCasingInFileNames": true,
|
|
14
|
-
"isolatedModules": true,
|
|
15
|
-
"moduleResolution": "node",
|
|
16
|
-
"noImplicitReturns": true,
|
|
17
|
-
"noImplicitThis": true,
|
|
18
|
-
"noUnusedLocals": false,
|
|
19
|
-
"preserveConstEnums": true,
|
|
20
|
-
"removeComments": false,
|
|
21
|
-
"resolveJsonModule": true,
|
|
22
|
-
"skipLibCheck": true,
|
|
23
|
-
"sourceMap": true,
|
|
24
|
-
"types": [
|
|
25
|
-
"node"
|
|
26
|
-
],
|
|
27
|
-
"target": "ES2018",
|
|
28
|
-
"downlevelIteration": true,
|
|
29
|
-
"strict": true,
|
|
30
|
-
"composite": true,
|
|
31
|
-
"outDir": "./dist/",
|
|
32
|
-
"rootDir": "./src/",
|
|
33
|
-
"preserveSymlinks": true,
|
|
34
|
-
"paths": {}
|
|
35
|
-
},
|
|
36
|
-
"exclude": ["dist", "examples"],
|
|
37
|
-
"references": []
|
|
38
|
-
}
|