@multiplayer-app/session-recorder-common 1.3.26 → 1.3.28

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 (78) hide show
  1. package/dist/esm/SessionRecorderTraceIdRatioBasedSampler.d.ts +2 -1
  2. package/dist/esm/SessionRecorderTraceIdRatioBasedSampler.d.ts.map +1 -1
  3. package/dist/esm/SessionRecorderTraceIdRatioBasedSampler.js +10 -5
  4. package/dist/esm/SessionRecorderTraceIdRatioBasedSampler.js.map +1 -1
  5. package/dist/esm/constants/constants.base.d.ts +1 -1
  6. package/dist/esm/constants/constants.base.js +1 -1
  7. package/dist/esm/constants/constants.base.js.map +1 -1
  8. package/dist/esm/exporters/SessionRecorderBrowserTraceExporter.d.ts +6 -2
  9. package/dist/esm/exporters/SessionRecorderBrowserTraceExporter.d.ts.map +1 -1
  10. package/dist/esm/exporters/SessionRecorderBrowserTraceExporter.js +57 -21
  11. package/dist/esm/exporters/SessionRecorderBrowserTraceExporter.js.map +1 -1
  12. package/dist/esm/sdk/capture-exception.d.ts +1 -1
  13. package/dist/esm/sdk/capture-exception.d.ts.map +1 -1
  14. package/dist/esm/sdk/capture-exception.js +59 -5
  15. package/dist/esm/sdk/capture-exception.js.map +1 -1
  16. package/dist/esm/sdk/index.d.ts +1 -0
  17. package/dist/esm/sdk/index.d.ts.map +1 -1
  18. package/dist/esm/sdk/index.js +1 -0
  19. package/dist/esm/sdk/index.js.map +1 -1
  20. package/dist/esm/sdk/set-resource-attributes.d.ts +3 -0
  21. package/dist/esm/sdk/set-resource-attributes.d.ts.map +1 -0
  22. package/dist/esm/sdk/set-resource-attributes.js +8 -0
  23. package/dist/esm/sdk/set-resource-attributes.js.map +1 -0
  24. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  25. package/dist/esnext/SessionRecorderTraceIdRatioBasedSampler.d.ts +2 -1
  26. package/dist/esnext/SessionRecorderTraceIdRatioBasedSampler.d.ts.map +1 -1
  27. package/dist/esnext/SessionRecorderTraceIdRatioBasedSampler.js +10 -5
  28. package/dist/esnext/SessionRecorderTraceIdRatioBasedSampler.js.map +1 -1
  29. package/dist/esnext/constants/constants.base.d.ts +1 -1
  30. package/dist/esnext/constants/constants.base.js +1 -1
  31. package/dist/esnext/constants/constants.base.js.map +1 -1
  32. package/dist/esnext/exporters/SessionRecorderBrowserTraceExporter.d.ts +6 -2
  33. package/dist/esnext/exporters/SessionRecorderBrowserTraceExporter.d.ts.map +1 -1
  34. package/dist/esnext/exporters/SessionRecorderBrowserTraceExporter.js +57 -20
  35. package/dist/esnext/exporters/SessionRecorderBrowserTraceExporter.js.map +1 -1
  36. package/dist/esnext/sdk/capture-exception.d.ts +1 -1
  37. package/dist/esnext/sdk/capture-exception.d.ts.map +1 -1
  38. package/dist/esnext/sdk/capture-exception.js +30 -5
  39. package/dist/esnext/sdk/capture-exception.js.map +1 -1
  40. package/dist/esnext/sdk/index.d.ts +1 -0
  41. package/dist/esnext/sdk/index.d.ts.map +1 -1
  42. package/dist/esnext/sdk/index.js +1 -0
  43. package/dist/esnext/sdk/index.js.map +1 -1
  44. package/dist/esnext/sdk/set-resource-attributes.d.ts +3 -0
  45. package/dist/esnext/sdk/set-resource-attributes.d.ts.map +1 -0
  46. package/dist/esnext/sdk/set-resource-attributes.js +8 -0
  47. package/dist/esnext/sdk/set-resource-attributes.js.map +1 -0
  48. package/dist/esnext/tsconfig.esnext.tsbuildinfo +1 -1
  49. package/dist/src/SessionRecorderTraceIdRatioBasedSampler.d.ts +2 -1
  50. package/dist/src/SessionRecorderTraceIdRatioBasedSampler.d.ts.map +1 -1
  51. package/dist/src/SessionRecorderTraceIdRatioBasedSampler.js +8 -2
  52. package/dist/src/SessionRecorderTraceIdRatioBasedSampler.js.map +1 -1
  53. package/dist/src/constants/constants.base.d.ts +1 -1
  54. package/dist/src/constants/constants.base.js +1 -1
  55. package/dist/src/constants/constants.base.js.map +1 -1
  56. package/dist/src/exporters/SessionRecorderBrowserTraceExporter.d.ts +6 -2
  57. package/dist/src/exporters/SessionRecorderBrowserTraceExporter.d.ts.map +1 -1
  58. package/dist/src/exporters/SessionRecorderBrowserTraceExporter.js +56 -19
  59. package/dist/src/exporters/SessionRecorderBrowserTraceExporter.js.map +1 -1
  60. package/dist/src/sdk/capture-exception.d.ts +1 -1
  61. package/dist/src/sdk/capture-exception.d.ts.map +1 -1
  62. package/dist/src/sdk/capture-exception.js +30 -5
  63. package/dist/src/sdk/capture-exception.js.map +1 -1
  64. package/dist/src/sdk/index.d.ts +1 -0
  65. package/dist/src/sdk/index.d.ts.map +1 -1
  66. package/dist/src/sdk/index.js +1 -0
  67. package/dist/src/sdk/index.js.map +1 -1
  68. package/dist/src/sdk/set-resource-attributes.d.ts +3 -0
  69. package/dist/src/sdk/set-resource-attributes.d.ts.map +1 -0
  70. package/dist/src/sdk/set-resource-attributes.js +13 -0
  71. package/dist/src/sdk/set-resource-attributes.js.map +1 -0
  72. package/package.json +1 -1
  73. package/src/SessionRecorderTraceIdRatioBasedSampler.ts +29 -4
  74. package/src/constants/constants.base.ts +1 -1
  75. package/src/exporters/SessionRecorderBrowserTraceExporter.ts +57 -24
  76. package/src/sdk/capture-exception.ts +49 -4
  77. package/src/sdk/index.ts +1 -0
  78. package/src/sdk/set-resource-attributes.ts +9 -0
@@ -1,11 +1,11 @@
1
1
  import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base'
2
- import { ExportResult } from '@opentelemetry/core'
3
2
 
4
3
  import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
5
4
  import {
6
5
  MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,
7
6
  MULTIPLAYER_TRACE_DEBUG_PREFIX,
8
7
  MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX,
8
+ MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX,
9
9
  } from '../constants/constants.base'
10
10
 
11
11
  export interface SessionRecorderBrowserTraceExporterConfig {
@@ -67,50 +67,52 @@ export class SessionRecorderBrowserTraceExporter implements SpanExporter {
67
67
 
68
68
  this.exporter = this._createExporter()
69
69
  }
70
-
71
- export(spans: ReadableSpan[], resultCallback: (result: { code: number }) => void): void {
72
- // Filter spans to only include those with Multiplayer trace prefixes
73
- const filteredSpans = spans.filter((span) => {
74
- const traceId = span.spanContext().traceId
75
- return (
76
- traceId.startsWith(MULTIPLAYER_TRACE_DEBUG_PREFIX) ||
77
- traceId.startsWith(MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX)
78
- )
79
- })
80
-
70
+ _export(spans: ReadableSpan[], resultCallback: (result: { code: number }) => void): void {
81
71
  // Only proceed if there are filtered spans
82
- if (filteredSpans.length === 0) {
72
+ if (spans.length === 0) {
83
73
  resultCallback({ code: 0 })
84
74
  return
85
75
  }
86
76
 
87
77
  if (this.usePostMessage) {
88
- this.exportViaPostMessage(filteredSpans, resultCallback)
78
+ this.exportViaPostMessage(spans, resultCallback)
89
79
  return
90
80
  }
91
81
 
92
- this.exporter.export(filteredSpans, (result) => {
82
+ this.exporter.export(spans, (result) => {
93
83
  if (result.code === 0) {
94
84
  resultCallback(result)
95
85
  } else if (this.config.usePostMessageFallback) {
96
86
  this.usePostMessage = true
97
- this.exportViaPostMessage(filteredSpans, resultCallback)
87
+ this.exportViaPostMessage(spans, resultCallback)
98
88
  } else {
99
89
  resultCallback(result)
100
90
  }
101
91
  })
102
92
  }
103
93
 
104
- shutdown(): Promise<void> {
105
- return this.exporter.shutdown()
94
+ export(spans: ReadableSpan[], resultCallback: (result: { code: number }) => void): void {
95
+ // Filter spans to only include those with Multiplayer trace prefixes
96
+ const filteredSpans = spans.filter((span) => {
97
+ const traceId = span.spanContext().traceId
98
+ return (
99
+ traceId.startsWith(MULTIPLAYER_TRACE_DEBUG_PREFIX) ||
100
+ traceId.startsWith(MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX)
101
+ )
102
+ })
103
+ this._export(filteredSpans, resultCallback)
106
104
  }
107
105
 
108
- exportBuffer(spans: ReadableSpan[]): Promise<ExportResult | undefined> {
109
- return new Promise((resolve) => {
110
- this.exporter.export(spans, (result) => {
111
- resolve(result)
112
- })
106
+ exportBuffer(spans: ReadableSpan[], resultCallback: (result: { code: number }) => void): void {
107
+ const filteredSpans = spans.filter((span) => {
108
+ const traceId = span.spanContext().traceId
109
+ return traceId.startsWith(MULTIPLAYER_TRACE_SESSION_CACHE_PREFIX)
113
110
  })
111
+ this._export(filteredSpans, resultCallback)
112
+ }
113
+
114
+ shutdown(): Promise<void> {
115
+ return this.exporter.shutdown()
114
116
  }
115
117
 
116
118
  private exportViaPostMessage(spans: ReadableSpan[], resultCallback: (result: { code: number }) => void): void {
@@ -136,9 +138,40 @@ export class SessionRecorderBrowserTraceExporter implements SpanExporter {
136
138
 
137
139
  serializeSpan(span: ReadableSpan): any {
138
140
  const spanContext = span.spanContext()
141
+ const instrumentationScope: any =
142
+ // OTel SDK (modern)
143
+ (span as any).instrumentationScope ||
144
+ // Older SDKs
145
+ (span as any).instrumentationLibrary || { name: 'unknown', version: undefined, schemaUrl: undefined }
146
+
147
+ const normalizedScope = {
148
+ name: instrumentationScope?.name || 'unknown',
149
+ version: instrumentationScope?.version,
150
+ schemaUrl: instrumentationScope?.schemaUrl,
151
+ }
139
152
  return {
140
- ...span,
141
153
  _spanContext: spanContext,
154
+ traceId: spanContext.traceId,
155
+ spanId: spanContext.spanId,
156
+ name: span.name,
157
+ kind: span.kind,
158
+ links: span.links,
159
+ ended: span.ended,
160
+ events: span.events,
161
+ status: span.status,
162
+ endTime: span.endTime,
163
+ startTime: span.startTime,
164
+ duration: span.duration,
165
+ attributes: span.attributes,
166
+ parentSpanId: span.parentSpanContext?.spanId,
167
+ droppedAttributesCount: span.droppedAttributesCount,
168
+ droppedEventsCount: span.droppedEventsCount,
169
+ droppedLinksCount: span.droppedLinksCount,
170
+ instrumentationScope: normalizedScope,
171
+ resource: {
172
+ attributes: span.resource.attributes,
173
+ asyncAttributesPending: span.resource.asyncAttributesPending,
174
+ },
142
175
  }
143
176
  }
144
177
 
@@ -1,19 +1,64 @@
1
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'
2
8
 
3
9
  /**
4
10
  * @description Add error to current span
5
11
  * @param {Error} error
6
12
  * @returns {void}
7
13
  */
8
- export const captureException = (error: Error) => {
9
- if (!error) return
14
+ export const captureException = (
15
+ error: Error,
16
+ errorInfo?: Record<string, any>,
17
+ ) => {
18
+ if (!error) {
19
+ return
20
+ }
10
21
 
11
- const span = trace.getSpan(context.active())
12
- if (!span) return
22
+ const activeContext = context.active()
23
+
24
+ let span = trace.getSpan(activeContext)
25
+ let isNewSpan = false
26
+
27
+ if (!span || !span.isRecording()) {
28
+ span = trace.getTracer('exception').startSpan(
29
+ error.name || 'Error',
30
+ {
31
+ attributes: {
32
+ [ATTR_EXCEPTION_MESSAGE]: error.message,
33
+ [ATTR_EXCEPTION_STACKTRACE]: error.stack,
34
+ [ATTR_EXCEPTION_TYPE]: error.name,
35
+ ...getResourceAttributes(),
36
+ },
37
+ },
38
+ )
39
+ trace.setSpan(activeContext, span)
40
+ isNewSpan = true
41
+ } else {
42
+ span.setAttributes({
43
+ [ATTR_EXCEPTION_MESSAGE]: error.message,
44
+ [ATTR_EXCEPTION_STACKTRACE]: error.stack,
45
+ [ATTR_EXCEPTION_TYPE]: error.name,
46
+ })
47
+ }
48
+
49
+ if (errorInfo) {
50
+ Object.entries(errorInfo).forEach(([key, value]) => {
51
+ span.setAttribute(`error_info.${key}`, value)
52
+ })
53
+ }
13
54
 
14
55
  span.recordException(error)
15
56
  span.setStatus({
16
57
  code: SpanStatusCode.ERROR,
17
58
  message: error.message,
18
59
  })
60
+
61
+ if (isNewSpan) {
62
+ span.end()
63
+ }
19
64
  }
package/src/sdk/index.ts CHANGED
@@ -5,3 +5,4 @@ export * from './id-generator'
5
5
  export * from './capture-exception'
6
6
  export * from './set-attribute'
7
7
  export * from './save-continuous-deb-session'
8
+ export * from './set-resource-attributes'
@@ -0,0 +1,9 @@
1
+ let resourceAttributes: Record<string, any> = {}
2
+
3
+ export const setResourceAttributes = (attributes: Record<string, any>) => {
4
+ resourceAttributes = attributes
5
+ }
6
+
7
+ export const getResourceAttributes = () => {
8
+ return resourceAttributes
9
+ }