@multiplayer-app/session-recorder-common 1.3.36 → 2.0.17-alpha.10

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.
Files changed (51) hide show
  1. package/dist/esm/sdk/capture-exception.js +3 -3
  2. package/dist/esm/sdk/capture-exception.js.map +1 -1
  3. package/dist/esnext/sdk/capture-exception.js +4 -4
  4. package/dist/esnext/sdk/capture-exception.js.map +1 -1
  5. package/dist/src/sdk/capture-exception.js +3 -3
  6. package/dist/src/sdk/capture-exception.js.map +1 -1
  7. package/package.json +3 -2
  8. package/dist/esm/tsconfig.esm.tsbuildinfo +0 -1
  9. package/dist/esnext/tsconfig.esnext.tsbuildinfo +0 -1
  10. package/docs/img/header-js.png +0 -0
  11. package/src/SessionRecorderIdGenerator.ts +0 -70
  12. package/src/SessionRecorderTraceIdRatioBasedSampler.ts +0 -89
  13. package/src/constants/constants.base.ts +0 -111
  14. package/src/constants/constants.browser.ts +0 -1
  15. package/src/constants/constants.node.ts +0 -5
  16. package/src/exporters/SessionRecorderBrowserTraceExporter.ts +0 -196
  17. package/src/exporters/SessionRecorderGrpcLogsExporter.ts +0 -52
  18. package/src/exporters/SessionRecorderGrpcTraceExporter.ts +0 -50
  19. package/src/exporters/SessionRecorderHttpLogsExporter.ts +0 -58
  20. package/src/exporters/SessionRecorderHttpTraceExporter.ts +0 -68
  21. package/src/exporters/SessionRecorderLogsExporterWrapper.ts +0 -36
  22. package/src/exporters/SessionRecorderTraceExporterWrapper.ts +0 -36
  23. package/src/exporters/index-browser.ts +0 -1
  24. package/src/exporters/index-node.ts +0 -6
  25. package/src/exporters/index.ts +0 -7
  26. package/src/index-browser.ts +0 -6
  27. package/src/index-node.ts +0 -7
  28. package/src/index.ts +0 -7
  29. package/src/instrumentations/SessionRecorderHttpInstrumentationHooksNode.ts +0 -356
  30. package/src/instrumentations/index-node.ts +0 -1
  31. package/src/sdk/capture-exception.ts +0 -102
  32. package/src/sdk/id-generator.ts +0 -17
  33. package/src/sdk/index.ts +0 -8
  34. package/src/sdk/is-gzip.ts +0 -7
  35. package/src/sdk/mask.ts +0 -161
  36. package/src/sdk/save-continuous-deb-session.ts +0 -28
  37. package/src/sdk/schemify.ts +0 -57
  38. package/src/sdk/set-attribute.ts +0 -210
  39. package/src/sdk/set-resource-attributes.ts +0 -9
  40. package/src/type/crash-buffer.ts +0 -64
  41. package/src/type/index.ts +0 -4
  42. package/src/type/session-type.enum.ts +0 -20
  43. package/src/type/session.ts +0 -84
  44. package/src/type/user-type.enum.ts +0 -5
  45. package/tsconfig.base.es5.json +0 -8
  46. package/tsconfig.base.esm.json +0 -7
  47. package/tsconfig.base.esnext.json +0 -10
  48. package/tsconfig.base.json +0 -35
  49. package/tsconfig.esm.json +0 -12
  50. package/tsconfig.esnext.json +0 -12
  51. package/tsconfig.json +0 -25
@@ -1,356 +0,0 @@
1
- import type {
2
- IncomingMessage,
3
- ServerResponse,
4
- ClientRequest,
5
- } from 'http'
6
- import * as zlib from 'zlib'
7
- import type { Span } from '@opentelemetry/api'
8
- import {
9
- ATTR_MULTIPLAYER_HTTP_REQUEST_BODY,
10
- ATTR_MULTIPLAYER_HTTP_REQUEST_HEADERS,
11
- ATTR_MULTIPLAYER_HTTP_RESPONSE_BODY,
12
- ATTR_MULTIPLAYER_HTTP_RESPONSE_HEADERS,
13
- MULTIPLAYER_MAX_HTTP_REQUEST_RESPONSE_SIZE,
14
- ATTR_MULTIPLAYER_HTTP_RESPONSE_BODY_ENCODING,
15
- MULTIPLAYER_TRACE_DEBUG_PREFIX,
16
- } from '../constants/constants.node'
17
- import {
18
- mask,
19
- isGzip,
20
- } from '../sdk'
21
- import {
22
- sensitiveFields,
23
- sensitiveHeaders,
24
- } from '../sdk/mask'
25
-
26
- interface HttpResponseHookOptions {
27
- maxPayloadSizeBytes?: number
28
- uncompressPayload?: boolean
29
-
30
- captureHeaders?: boolean
31
- captureBody?: boolean
32
-
33
- isMaskBodyEnabled?: boolean
34
- isMaskHeadersEnabled?: boolean
35
-
36
- maskBody?: (arg: any, span: Span) => any
37
- maskHeaders?: (arg: any, span: Span) => any
38
-
39
- maskBodyFieldsList?: string[]
40
- maskHeadersList?: string[]
41
-
42
- headersToInclude?: string[]
43
- headersToExclude?: string[]
44
- }
45
-
46
- interface HttpRequestHookOptions {
47
- maxPayloadSizeBytes?: number
48
-
49
- captureHeaders?: boolean
50
- captureBody?: boolean
51
-
52
- isMaskBodyEnabled?: boolean
53
- isMaskHeadersEnabled?: boolean
54
-
55
- maskBody?: (arg: any, span: Span) => any
56
- maskHeaders?: (arg: any, span: Span) => any
57
-
58
- maskBodyFieldsList?: string[]
59
- maskHeadersList?: string[]
60
-
61
- headersToInclude?: string[]
62
- headersToExclude?: string[]
63
- }
64
-
65
- const setDefaultOptions = (
66
- options: HttpResponseHookOptions | HttpResponseHookOptions,
67
- ): Omit<HttpResponseHookOptions & HttpResponseHookOptions, 'maskBody' | 'maskHeaders'>
68
- & {
69
- maskBody: (arg: any, span: Span) => any
70
- maskHeaders: (arg: any, span: Span) => any
71
- captureHeaders: boolean,
72
- captureBody: boolean,
73
- isMaskBodyEnabled: boolean
74
- isMaskHeadersEnabled: boolean
75
- uncompressPayload: boolean,
76
- maxPayloadSizeBytes: number
77
- } => {
78
- options.captureHeaders = 'captureHeaders' in options
79
- ? options.captureHeaders
80
- : true
81
- options.captureBody = 'captureBody' in options
82
- ? options.captureBody
83
- : true
84
- options.isMaskBodyEnabled = 'isMaskBodyEnabled' in options
85
- ? options.isMaskBodyEnabled
86
- : true
87
- options.isMaskHeadersEnabled = 'isMaskHeadersEnabled' in options
88
- ? options.isMaskHeadersEnabled
89
- : true
90
- options.uncompressPayload = 'uncompressPayload' in options
91
- ? options.uncompressPayload
92
- : true
93
- options.maskBody = options.maskBody || mask([
94
- ...(
95
- Array.isArray(options.maskBodyFieldsList)
96
- ? options.maskBodyFieldsList
97
- : sensitiveFields
98
- ),
99
- ...(
100
- Array.isArray(options.maskHeadersList)
101
- ? options.maskHeadersList
102
- : sensitiveHeaders
103
- ),
104
- ])
105
- options.maskHeaders = options.maskHeaders || mask([
106
- ...(
107
- Array.isArray(options.maskBodyFieldsList)
108
- ? options.maskBodyFieldsList
109
- : sensitiveFields
110
- ),
111
- ...(
112
- Array.isArray(options.maskHeadersList)
113
- ? options.maskHeadersList
114
- : sensitiveHeaders
115
- ),
116
- ])
117
- options.maxPayloadSizeBytes = options.maxPayloadSizeBytes || MULTIPLAYER_MAX_HTTP_REQUEST_RESPONSE_SIZE
118
-
119
- return options as Omit<HttpResponseHookOptions & HttpResponseHookOptions, 'maskBody' | 'maskHeaders'>
120
- & {
121
- maskBody: (arg: any, span: Span) => any
122
- maskHeaders: (arg: any, span: Span) => any
123
- captureHeaders: boolean,
124
- captureBody: boolean,
125
- isMaskBodyEnabled: boolean,
126
- isMaskHeadersEnabled: boolean,
127
- uncompressPayload: boolean,
128
- maxPayloadSizeBytes: number
129
- }
130
- }
131
-
132
- export const SessionRecorderHttpInstrumentationHooksNode = {
133
- responseHook: (options: HttpResponseHookOptions = {}) =>
134
- (span: Span, response: IncomingMessage | ServerResponse) => {
135
- try {
136
- const _options = setDefaultOptions(options)
137
-
138
- if (!_options.captureBody && !_options.captureHeaders) {
139
- return
140
- }
141
-
142
- const _response = response as ServerResponse
143
- const traceId = span.spanContext().traceId
144
-
145
- if (_response.setHeader) {
146
- _response.setHeader('X-Trace-Id', traceId)
147
- }
148
-
149
- const [oldWrite, oldEnd] = [_response.write, _response.end]
150
-
151
- const chunks: Buffer[] = []
152
-
153
- if (_options.captureBody) {
154
- (_response.write as unknown) = function (...restArgs: any[]) {
155
- chunks.push(Buffer.from(restArgs[0]))
156
-
157
- // @ts-ignore
158
- oldWrite.apply(_response, restArgs)
159
- }
160
- }
161
-
162
-
163
- // @ts-ignore
164
- _response.end = async function (...restArgs) {
165
- if (_options.captureBody && restArgs[0]) {
166
- chunks.push(Buffer.from(restArgs[0]))
167
- }
168
-
169
- const responseBuffer = Buffer.concat(chunks)
170
-
171
- if (
172
- _options.captureBody
173
- && responseBuffer.byteLength > 0
174
- && responseBuffer.byteLength < _options.maxPayloadSizeBytes
175
- ) {
176
- let responseBody: string
177
- let skipResponseBodyModification = false
178
-
179
- if (isGzip(responseBuffer)) {
180
- if (_options.uncompressPayload) {
181
- const dezippedBuffer = await new Promise((resolve) => zlib
182
- .gunzip(responseBuffer, function (err, dezipped) {
183
- if (err) {
184
- return resolve(Buffer.from(''))
185
- } else {
186
- return resolve(dezipped)
187
- }
188
- })) as Buffer
189
- responseBody = dezippedBuffer.toString('utf-8')
190
- } else {
191
- span.setAttribute(
192
- ATTR_MULTIPLAYER_HTTP_RESPONSE_BODY_ENCODING,
193
- 'gzip',
194
- )
195
-
196
- skipResponseBodyModification = true
197
- responseBody = responseBuffer.toString('hex')
198
- }
199
- } else {
200
- responseBody = responseBuffer.toString('utf-8')
201
- }
202
-
203
- if (responseBody.length) {
204
- responseBody = JSON.parse(JSON.stringify(responseBody))
205
- }
206
-
207
- if (!skipResponseBodyModification) {
208
- if (
209
- traceId.startsWith(MULTIPLAYER_TRACE_DEBUG_PREFIX)
210
- && _options.isMaskBodyEnabled
211
- ) {
212
- responseBody = _options.maskBody(responseBody, span)
213
- } else if (typeof responseBody !== 'string') {
214
- responseBody = JSON.stringify(responseBody)
215
- }
216
- }
217
-
218
- if (responseBody.length) {
219
- span.setAttribute(
220
- ATTR_MULTIPLAYER_HTTP_RESPONSE_BODY,
221
- responseBody,
222
- )
223
- }
224
- }
225
-
226
- if (_options.captureHeaders) {
227
- let _headers = JSON.parse(JSON.stringify(_response.getHeaders() || {}))
228
- if (_options.isMaskHeadersEnabled) {
229
- _headers = _options.maskHeaders(_headers, span)
230
- }
231
-
232
- if (_options.headersToInclude) {
233
- const filteredHeaders: any = {}
234
- for (const headerName of _options.headersToInclude) {
235
- filteredHeaders[headerName] = _headers[headerName]
236
- }
237
- _headers = filteredHeaders
238
- }
239
-
240
- if (_options.headersToExclude?.length) {
241
- for (const headerName of _options.headersToExclude) {
242
- delete _headers[headerName]
243
- }
244
- }
245
-
246
- const stringifiedHeaders = JSON.stringify(_headers)
247
-
248
- if (stringifiedHeaders?.length) {
249
- span.setAttribute(
250
- ATTR_MULTIPLAYER_HTTP_RESPONSE_HEADERS,
251
- stringifiedHeaders,
252
- )
253
- }
254
- }
255
-
256
-
257
- // @ts-ignore
258
- return oldEnd.apply(_response, restArgs)
259
- }
260
- } catch (error) {
261
- // eslint-disable-next-line
262
- console.error('An error occured in multiplayer otlp http responseHook', error)
263
- }
264
- },
265
- requestHook: (options: HttpRequestHookOptions = {}) =>
266
- (span: Span, request: ClientRequest | IncomingMessage) => {
267
- try {
268
- const _options = setDefaultOptions(options)
269
-
270
- if (!_options.captureBody && !_options.captureHeaders) {
271
- return
272
- }
273
-
274
- const traceId = span.spanContext().traceId
275
- const _request = request as IncomingMessage
276
-
277
- if (_options.captureHeaders) {
278
- let _headers = JSON.parse(JSON.stringify(_request.headers || {}))
279
-
280
- if (_options.isMaskHeadersEnabled) {
281
- _headers = _options.maskHeaders(_headers, span)
282
- }
283
-
284
- if (_options.headersToInclude) {
285
- const filteredHeaders: any = {}
286
- for (const headerName of _options.headersToInclude) {
287
- filteredHeaders[headerName] = _headers[headerName]
288
- }
289
- _headers = filteredHeaders
290
- }
291
-
292
- if (_options.headersToExclude?.length) {
293
- for (const headerName of _options.headersToExclude) {
294
- delete _headers[headerName]
295
- }
296
- }
297
-
298
- span.setAttribute(
299
- ATTR_MULTIPLAYER_HTTP_REQUEST_HEADERS,
300
- JSON.stringify(_headers),
301
- )
302
- }
303
-
304
- const contentType = _request?.headers?.['content-type']
305
- if (
306
- _options.captureBody
307
- && contentType?.includes('application/json')
308
- ) {
309
- let body = ''
310
- _request.on('data', (chunk) => {
311
- body += chunk
312
- })
313
- _request.on('end', () => {
314
- try {
315
- const requestBodySizeBytes = Buffer.byteLength(body, 'utf8')
316
-
317
- if (
318
- requestBodySizeBytes === 0
319
- || requestBodySizeBytes > _options.maxPayloadSizeBytes
320
- ) {
321
- return
322
- }
323
-
324
- let requestBody = body
325
- if (!requestBody) return
326
-
327
- requestBody = JSON.parse(JSON.stringify(requestBody))
328
-
329
- if (
330
- traceId.startsWith(MULTIPLAYER_TRACE_DEBUG_PREFIX)
331
- && _options.isMaskBodyEnabled
332
- ) {
333
- requestBody = _options.maskBody(requestBody, span)
334
- } else if (typeof requestBody !== 'string') {
335
- requestBody = JSON.stringify(requestBody)
336
- }
337
-
338
- if (requestBody?.length) {
339
- span.setAttribute(
340
- ATTR_MULTIPLAYER_HTTP_REQUEST_BODY,
341
- requestBody,
342
- )
343
- }
344
- } catch (err) {
345
- // eslint-disable-next-line
346
- console.error('[MULTIPLAYER-HTTP-REQ-HOOK] An error occured in multiplayer otlp http requestHook', err)
347
- }
348
- })
349
- }
350
-
351
- } catch (error) {
352
- // eslint-disable-next-line
353
- console.error('An error occured in multiplayer otlp http requestHook', error)
354
- }
355
- },
356
- }
@@ -1 +0,0 @@
1
- export * from './SessionRecorderHttpInstrumentationHooksNode'
@@ -1,102 +0,0 @@
1
- import { context, trace, SpanStatusCode } from '@opentelemetry/api'
2
- import {
3
- ATTR_EXCEPTION_MESSAGE,
4
- ATTR_EXCEPTION_STACKTRACE,
5
- ATTR_EXCEPTION_TYPE
6
- } from '@opentelemetry/semantic-conventions'
7
- import { getResourceAttributes } from './set-resource-attributes'
8
-
9
- /**
10
- * @description Add error to current span
11
- * @param {Error} error
12
- * @returns {void}
13
- */
14
- export const captureException = (error: Error, errorInfo?: Record<string, any>) => {
15
- if (!error || !shouldCaptureException(error)) {
16
- return
17
- }
18
-
19
- const activeContext = context.active()
20
-
21
- let span = trace.getSpan(activeContext)
22
- let isNewSpan = false
23
-
24
- if (!span || !span.isRecording()) {
25
- span = trace.getTracer('exception').startSpan(error.name || 'Error', {
26
- attributes: {
27
- [ATTR_EXCEPTION_MESSAGE]: error.message,
28
- [ATTR_EXCEPTION_STACKTRACE]: error.stack,
29
- [ATTR_EXCEPTION_TYPE]: error.name,
30
- ...getResourceAttributes()
31
- }
32
- })
33
- trace.setSpan(activeContext, span)
34
- isNewSpan = true
35
- } else {
36
- span.setAttributes({
37
- [ATTR_EXCEPTION_MESSAGE]: error.message,
38
- [ATTR_EXCEPTION_STACKTRACE]: error.stack,
39
- [ATTR_EXCEPTION_TYPE]: error.name
40
- })
41
- }
42
-
43
- if (errorInfo) {
44
- Object.entries(errorInfo).forEach(([key, value]) => {
45
- span.setAttribute(`error_info.${key}`, value)
46
- })
47
- }
48
-
49
- span.recordException(error)
50
- span.setStatus({
51
- code: SpanStatusCode.ERROR,
52
- message: error.message
53
- })
54
-
55
- if (isNewSpan) {
56
- span.end()
57
- }
58
- }
59
-
60
- /**
61
- * Best-effort deduplication of exceptions that fire multiple times
62
- * (e.g. framework handler + global handlers) within a short time window.
63
- */
64
-
65
- const exceptionDedupeWindowMs = 2000
66
- const recentExceptionFingerprints = new Map<string, number>()
67
-
68
- export const shouldCaptureException = (error: Error, _errorInfo?: Record<string, any>): boolean => {
69
- if (!error) return false
70
-
71
- const now = Date.now()
72
-
73
- // Build a fingerprint that is stable enough across repeated emissions
74
- // but not so broad that different errors collapse into one.
75
- const keyParts: string[] = []
76
- keyParts.push(error.name || 'Error')
77
- keyParts.push(error.message || '')
78
-
79
- // First stack line tends to include file/line where it originated.
80
- if (typeof error.stack === 'string') {
81
- const firstFrame = error.stack.split('\n')[1] || ''
82
- keyParts.push(firstFrame.trim())
83
- }
84
-
85
- const fingerprint = keyParts.join('|').slice(0, 500)
86
-
87
- const lastSeen = recentExceptionFingerprints.get(fingerprint)
88
- if (lastSeen && now - lastSeen < exceptionDedupeWindowMs) {
89
- return false
90
- }
91
-
92
- recentExceptionFingerprints.set(fingerprint, now)
93
-
94
- // Cheap cleanup of old entries to avoid unbounded growth.
95
- for (const [key, ts] of recentExceptionFingerprints) {
96
- if (now - ts > exceptionDedupeWindowMs * 5) {
97
- recentExceptionFingerprints.delete(key)
98
- }
99
- }
100
-
101
- return true
102
- }
@@ -1,17 +0,0 @@
1
- const SHARED_CHAR_CODES_ARRAY = Array(32)
2
-
3
- export const getIdGenerator = (bytes: number) => {
4
- return function generateId() {
5
- for (let i = 0; i < bytes * 2; i++) {
6
- SHARED_CHAR_CODES_ARRAY[i] = Math.floor(Math.random() * 16) + 48
7
- // valid hex characters in the range 48-57 and 97-102
8
- if (SHARED_CHAR_CODES_ARRAY[i] >= 58) {
9
- SHARED_CHAR_CODES_ARRAY[i] += 39
10
- }
11
- }
12
- return String.fromCharCode.apply(
13
- null,
14
- SHARED_CHAR_CODES_ARRAY.slice(0, bytes * 2),
15
- )
16
- }
17
- }
package/src/sdk/index.ts DELETED
@@ -1,8 +0,0 @@
1
- export { default as mask, sensitiveFields, sensitiveHeaders } from './mask'
2
- export { default as schemify } from './schemify'
3
- export * from './is-gzip'
4
- export * from './id-generator'
5
- export * from './capture-exception'
6
- export * from './set-attribute'
7
- export * from './save-continuous-deb-session'
8
- export * from './set-resource-attributes'
@@ -1,7 +0,0 @@
1
- export const isGzip = (buf: Buffer | Uint8Array) => {
2
- if (!buf || buf.length < 3) {
3
- return false
4
- }
5
-
6
- return buf[0] === 0x1F && buf[1] === 0x8B && buf[2] === 0x08
7
- }
package/src/sdk/mask.ts DELETED
@@ -1,161 +0,0 @@
1
- import type { Span } from '@opentelemetry/api'
2
- import { MASK_PLACEHOLDER } from '../constants/constants.base'
3
-
4
- const MAX_DEPTH = 8
5
- export const sensitiveFields: string[] = [
6
- 'password',
7
- 'pass',
8
- 'passwd',
9
- 'pwd',
10
- 'token',
11
- 'access_token',
12
- 'accessToken',
13
- 'refresh_token',
14
- 'refreshToken',
15
- 'secret',
16
- 'api_key',
17
- 'apiKey',
18
- 'authorization',
19
- 'auth_token',
20
- 'authToken',
21
- 'jwt',
22
- 'session_id',
23
- 'sessionId',
24
- 'sessionToken',
25
- 'client_secret',
26
- 'clientSecret',
27
- 'private_key',
28
- 'privateKey',
29
- 'public_key',
30
- 'publicKey',
31
- 'key',
32
- 'encryption_key',
33
- 'encryptionKey',
34
- 'credit_card',
35
- 'creditCard',
36
- 'card_number',
37
- 'cardNumber',
38
- 'cvv',
39
- 'cvc',
40
- 'ssn',
41
- 'sin',
42
- 'pin',
43
- 'security_code',
44
- 'securityCode',
45
- 'bank_account',
46
- 'bankAccount',
47
- 'iban',
48
- 'swift',
49
- 'bic',
50
- 'routing_number',
51
- 'routingNumber',
52
- 'license_key',
53
- 'licenseKey',
54
- 'otp',
55
- 'mfa_code',
56
- 'mfaCode',
57
- 'phone_number',
58
- 'phoneNumber',
59
- 'email',
60
- 'address',
61
- 'dob',
62
- 'tax_id',
63
- 'taxId',
64
- 'passport_number',
65
- 'passportNumber',
66
- 'driver_license',
67
- 'driverLicense',
68
-
69
- 'set-cookie',
70
- 'cookie',
71
- 'authorization',
72
- 'proxyAuthorization',
73
- ]
74
-
75
- export const sensitiveHeaders: string[] = [
76
- 'set-cookie',
77
- 'cookie',
78
- 'authorization',
79
- 'proxyAuthorization',
80
- ]
81
-
82
- const maskAll = (value: any, depth = 0) => {
83
- const type = typeof value
84
- const isObject = type === 'object'
85
- let isArray = false
86
-
87
- if (Array.isArray(value)) {
88
- isArray = true
89
- }
90
-
91
- if (depth > MAX_DEPTH && (isObject || isArray)) {
92
- return undefined
93
- }
94
-
95
- if (isArray) {
96
- return value.map((val: any) => maskAll(val, depth + 1), value)
97
- }
98
-
99
- if (isObject) {
100
- for (const key in value) {
101
- value[key] = maskAll(value[key], depth + 1)
102
- }
103
-
104
- return value
105
- }
106
-
107
- if (type === 'string') {
108
- return MASK_PLACEHOLDER
109
- }
110
-
111
- return value
112
- }
113
-
114
- const maskSelected = (value: any, keysToMask: string[]): any => {
115
- const type = typeof value
116
- const isObject = type === 'object'
117
-
118
- const _keysToMask = new Set(keysToMask)
119
-
120
- if (Array.isArray(value)) {
121
- return value.map((val: any) => maskSelected(val, keysToMask), value)
122
- }
123
-
124
- if (isObject) {
125
- for (const key in value) {
126
- if (_keysToMask.has(key)) {
127
- value[key] = MASK_PLACEHOLDER
128
- } else {
129
- value[key] = maskSelected(value[key], keysToMask)
130
- }
131
- }
132
-
133
- return value
134
- }
135
-
136
- if (type === 'string') {
137
- return value
138
- }
139
-
140
- return value
141
- }
142
-
143
- export default (keysToMask: string[] = []) => (value: any, span?: Span): any => {
144
- let payloadJson
145
- try {
146
- payloadJson = JSON.parse(value)
147
- } catch {
148
- payloadJson = value
149
- }
150
- let maskedData
151
- if (keysToMask.length) {
152
- maskedData = maskSelected(payloadJson, keysToMask)
153
- } else {
154
- maskedData = maskAll(payloadJson)
155
- }
156
- if (typeof maskedData !== 'string') {
157
- maskedData = JSON.stringify(maskedData)
158
- }
159
-
160
- return maskedData
161
- }
@@ -1,28 +0,0 @@
1
- import { context, trace } from '@opentelemetry/api'
2
- import {
3
- ATTR_MULTIPLAYER_CONTINUOUS_SESSION_AUTO_SAVE,
4
- ATTR_MULTIPLAYER_CONTINUOUS_SESSION_AUTO_SAVE_REASON,
5
- } from '../constants/constants.base'
6
- /**
7
- * @description Set auto save attribute to span
8
- * @param {String} reason
9
- * @returns {void}
10
- */
11
- export const saveContinuousSession = (
12
- reason?: string,
13
- ) => {
14
- const span = trace.getSpan(context.active())
15
-
16
- if (!span) {
17
- return
18
- // create span
19
- }
20
-
21
- span?.setAttribute(ATTR_MULTIPLAYER_CONTINUOUS_SESSION_AUTO_SAVE, true)
22
-
23
- if (reason?.length) {
24
- span?.addEvent(ATTR_MULTIPLAYER_CONTINUOUS_SESSION_AUTO_SAVE_REASON, {
25
- reason,
26
- })
27
- }
28
- }