@multiplayer-app/session-recorder-common 1.0.1-alpha.1 → 1.0.1-alpha.3
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/dist/esm/SessionRecorderIdGenerator.d.ts +6 -3
- package/dist/esm/SessionRecorderIdGenerator.d.ts.map +1 -1
- package/dist/esm/SessionRecorderIdGenerator.js +26 -41
- package/dist/esm/SessionRecorderIdGenerator.js.map +1 -1
- package/dist/esm/exporters/SessionRecorderBrowserTraceExporter.d.ts +15 -3
- package/dist/esm/exporters/SessionRecorderBrowserTraceExporter.d.ts.map +1 -1
- package/dist/esm/exporters/SessionRecorderBrowserTraceExporter.js +26 -126
- package/dist/esm/exporters/SessionRecorderBrowserTraceExporter.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/esnext/SessionRecorderIdGenerator.d.ts +6 -3
- package/dist/esnext/SessionRecorderIdGenerator.d.ts.map +1 -1
- package/dist/esnext/SessionRecorderIdGenerator.js +21 -19
- package/dist/esnext/SessionRecorderIdGenerator.js.map +1 -1
- package/dist/esnext/exporters/SessionRecorderBrowserTraceExporter.d.ts +15 -3
- package/dist/esnext/exporters/SessionRecorderBrowserTraceExporter.d.ts.map +1 -1
- package/dist/esnext/exporters/SessionRecorderBrowserTraceExporter.js +27 -76
- package/dist/esnext/exporters/SessionRecorderBrowserTraceExporter.js.map +1 -1
- package/dist/esnext/tsconfig.esnext.tsbuildinfo +1 -1
- package/dist/src/SessionRecorderIdGenerator.d.ts +6 -3
- package/dist/src/SessionRecorderIdGenerator.d.ts.map +1 -1
- package/dist/src/SessionRecorderIdGenerator.js +21 -19
- package/dist/src/SessionRecorderIdGenerator.js.map +1 -1
- package/dist/src/exporters/SessionRecorderBrowserTraceExporter.d.ts +15 -3
- package/dist/src/exporters/SessionRecorderBrowserTraceExporter.d.ts.map +1 -1
- package/dist/src/exporters/SessionRecorderBrowserTraceExporter.js +27 -76
- package/dist/src/exporters/SessionRecorderBrowserTraceExporter.js.map +1 -1
- package/package.json +3 -3
- package/src/SessionRecorderIdGenerator.ts +26 -23
- package/src/exporters/SessionRecorderBrowserTraceExporter.ts +55 -94
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base'
|
|
2
|
-
import {
|
|
3
|
-
OTLPExporterConfigBase,
|
|
4
|
-
OTLPExporterBase,
|
|
5
|
-
} from '@opentelemetry/otlp-exporter-base'
|
|
6
|
-
import {
|
|
7
|
-
createLegacyOtlpBrowserExportDelegate,
|
|
8
|
-
} from '@opentelemetry/otlp-exporter-base/browser-http'
|
|
2
|
+
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
|
|
9
3
|
import {
|
|
10
4
|
MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,
|
|
11
5
|
MULTIPLAYER_TRACE_DEBUG_PREFIX,
|
|
12
6
|
MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX,
|
|
13
7
|
} from '../constants/constants.base'
|
|
14
8
|
|
|
15
|
-
export interface SessionRecorderBrowserTraceExporterConfig
|
|
16
|
-
|
|
9
|
+
export interface SessionRecorderBrowserTraceExporterConfig {
|
|
10
|
+
/** URL for the OTLP endpoint. Defaults to Multiplayer's default traces endpoint. */
|
|
11
|
+
url?: string
|
|
17
12
|
/** API key for authentication. Required. */
|
|
18
13
|
apiKey: string
|
|
14
|
+
/** Additional headers to include in requests */
|
|
15
|
+
headers?: Record<string, string>
|
|
16
|
+
/** Request timeout in milliseconds */
|
|
17
|
+
timeoutMillis?: number
|
|
18
|
+
/** Whether to use keep-alive connections */
|
|
19
|
+
keepAlive?: boolean
|
|
20
|
+
/** Maximum number of concurrent requests */
|
|
21
|
+
concurrencyLimit?: number
|
|
19
22
|
/** Whether to use postMessage fallback for cross-origin requests */
|
|
20
23
|
usePostMessageFallback?: boolean
|
|
21
24
|
/** PostMessage type identifier */
|
|
@@ -29,10 +32,8 @@ export interface SessionRecorderBrowserTraceExporterConfig
|
|
|
29
32
|
* Exports traces via HTTP to Multiplayer's OTLP endpoint with browser-specific optimizations
|
|
30
33
|
* Only exports spans with trace IDs starting with Multiplayer prefixes
|
|
31
34
|
*/
|
|
32
|
-
export class SessionRecorderBrowserTraceExporter
|
|
33
|
-
|
|
34
|
-
implements SpanExporter {
|
|
35
|
-
|
|
35
|
+
export class SessionRecorderBrowserTraceExporter implements SpanExporter {
|
|
36
|
+
private exporter: OTLPTraceExporter
|
|
36
37
|
private usePostMessage: boolean = false
|
|
37
38
|
private readonly postMessageType: string
|
|
38
39
|
private readonly postMessageTargetOrigin: string
|
|
@@ -43,93 +44,32 @@ export class SessionRecorderBrowserTraceExporter
|
|
|
43
44
|
url = MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,
|
|
44
45
|
apiKey,
|
|
45
46
|
headers = {},
|
|
47
|
+
timeoutMillis = 30000,
|
|
48
|
+
keepAlive = true,
|
|
49
|
+
concurrencyLimit = 20,
|
|
46
50
|
postMessageType = 'MULTIPLAYER_SESSION_DEBUGGER_LIB',
|
|
47
51
|
postMessageTargetOrigin = '*',
|
|
48
|
-
...restConfig
|
|
49
52
|
} = config
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
...
|
|
54
|
+
this.config = {
|
|
55
|
+
...config,
|
|
53
56
|
url,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
},
|
|
57
|
+
apiKey,
|
|
58
|
+
headers,
|
|
59
|
+
timeoutMillis,
|
|
60
|
+
keepAlive,
|
|
61
|
+
concurrencyLimit,
|
|
60
62
|
}
|
|
61
|
-
|
|
62
|
-
super(
|
|
63
|
-
createLegacyOtlpBrowserExportDelegate(
|
|
64
|
-
_config,
|
|
65
|
-
{
|
|
66
|
-
serializeRequest: (spans: ReadableSpan[]) => {
|
|
67
|
-
// Create a simple trace service request structure
|
|
68
|
-
const request = {
|
|
69
|
-
resourceSpans: spans.map(span => ({
|
|
70
|
-
resource: {
|
|
71
|
-
attributes: Object.entries(span.resource.attributes).map(([key, value]) => ({
|
|
72
|
-
key,
|
|
73
|
-
value: { stringValue: String(value) },
|
|
74
|
-
})),
|
|
75
|
-
},
|
|
76
|
-
scopeSpans: [{
|
|
77
|
-
spans: [{
|
|
78
|
-
traceId: span.spanContext().traceId,
|
|
79
|
-
spanId: span.spanContext().spanId,
|
|
80
|
-
parentSpanId: span.spanContext().spanId, // Using spanId as fallback
|
|
81
|
-
name: span.name,
|
|
82
|
-
kind: span.kind,
|
|
83
|
-
startTimeUnixNano: span.startTime[0] * 1e9 + span.startTime[1],
|
|
84
|
-
endTimeUnixNano: span.endTime ? span.endTime[0] * 1e9 + span.endTime[1] : undefined,
|
|
85
|
-
attributes: Object.entries(span.attributes).map(([key, value]) => ({
|
|
86
|
-
key,
|
|
87
|
-
value: { stringValue: String(value) },
|
|
88
|
-
})),
|
|
89
|
-
events: span.events.map(event => ({
|
|
90
|
-
timeUnixNano: event.time[0] * 1e9 + event.time[1],
|
|
91
|
-
name: event.name,
|
|
92
|
-
attributes: Object.entries(event.attributes || {}).map(([key, value]) => ({
|
|
93
|
-
key,
|
|
94
|
-
value: { stringValue: String(value) },
|
|
95
|
-
})),
|
|
96
|
-
})),
|
|
97
|
-
links: span.links.map(link => ({
|
|
98
|
-
traceId: link.context.traceId,
|
|
99
|
-
spanId: link.context.spanId,
|
|
100
|
-
attributes: Object.entries(link.attributes || {}).map(([key, value]) => ({
|
|
101
|
-
key,
|
|
102
|
-
value: { stringValue: String(value) },
|
|
103
|
-
})),
|
|
104
|
-
})),
|
|
105
|
-
status: {
|
|
106
|
-
code: span.status.code,
|
|
107
|
-
message: span.status.message || '',
|
|
108
|
-
},
|
|
109
|
-
}],
|
|
110
|
-
}],
|
|
111
|
-
})),
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const encoder = new TextEncoder()
|
|
115
|
-
return encoder.encode(JSON.stringify(request))
|
|
116
|
-
},
|
|
117
|
-
deserializeResponse: (arg: Uint8Array) => {
|
|
118
|
-
const decoder = new TextDecoder()
|
|
119
|
-
return JSON.parse(decoder.decode(arg))
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
'v1/traces',
|
|
123
|
-
{ 'Content-Type': 'application/json' },
|
|
124
|
-
),
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
this.config = config
|
|
128
63
|
this.postMessageType = postMessageType
|
|
129
64
|
this.postMessageTargetOrigin = postMessageTargetOrigin
|
|
65
|
+
|
|
66
|
+
this.exporter = this._createExporter()
|
|
130
67
|
}
|
|
131
68
|
|
|
132
|
-
|
|
69
|
+
export(
|
|
70
|
+
spans: ReadableSpan[],
|
|
71
|
+
resultCallback: (result: { code: number }) => void,
|
|
72
|
+
): void {
|
|
133
73
|
// Filter spans to only include those with Multiplayer trace prefixes
|
|
134
74
|
const filteredSpans = spans.filter(span => {
|
|
135
75
|
const traceId = span.spanContext().traceId
|
|
@@ -148,7 +88,7 @@ export class SessionRecorderBrowserTraceExporter
|
|
|
148
88
|
return
|
|
149
89
|
}
|
|
150
90
|
|
|
151
|
-
|
|
91
|
+
this.exporter.export(filteredSpans, (result) => {
|
|
152
92
|
if (result.code === 0) {
|
|
153
93
|
resultCallback(result)
|
|
154
94
|
} else if (this.config.usePostMessageFallback) {
|
|
@@ -160,8 +100,8 @@ export class SessionRecorderBrowserTraceExporter
|
|
|
160
100
|
})
|
|
161
101
|
}
|
|
162
102
|
|
|
163
|
-
|
|
164
|
-
return
|
|
103
|
+
shutdown(): Promise<void> {
|
|
104
|
+
return this.exporter.shutdown()
|
|
165
105
|
}
|
|
166
106
|
|
|
167
107
|
private exportViaPostMessage(spans: ReadableSpan[], resultCallback: (result: { code: number }) => void): void {
|
|
@@ -199,7 +139,7 @@ export class SessionRecorderBrowserTraceExporter
|
|
|
199
139
|
startTime: span.startTime,
|
|
200
140
|
duration: span.duration,
|
|
201
141
|
attributes: span.attributes,
|
|
202
|
-
parentSpanId:
|
|
142
|
+
parentSpanId: span.parentSpanContext?.spanId,
|
|
203
143
|
droppedAttributesCount: span.droppedAttributesCount,
|
|
204
144
|
droppedEventsCount: span.droppedEventsCount,
|
|
205
145
|
droppedLinksCount: span.droppedLinksCount,
|
|
@@ -209,4 +149,25 @@ export class SessionRecorderBrowserTraceExporter
|
|
|
209
149
|
},
|
|
210
150
|
}
|
|
211
151
|
}
|
|
152
|
+
|
|
153
|
+
private _createExporter(): OTLPTraceExporter {
|
|
154
|
+
return new OTLPTraceExporter({
|
|
155
|
+
url: this.config.url,
|
|
156
|
+
headers: {
|
|
157
|
+
'Content-Type': 'application/x-protobuf',
|
|
158
|
+
'User-Agent': '@multiplayer-app/session-recorder-common/1.0.0',
|
|
159
|
+
'authorization': this.config.apiKey,
|
|
160
|
+
...(this.config.headers || {}),
|
|
161
|
+
},
|
|
162
|
+
timeoutMillis: this.config.timeoutMillis,
|
|
163
|
+
keepAlive: this.config.keepAlive,
|
|
164
|
+
concurrencyLimit: this.config.concurrencyLimit,
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
setApiKey(apiKey: string): void {
|
|
169
|
+
this.config.apiKey = apiKey
|
|
170
|
+
|
|
171
|
+
this.exporter = this._createExporter()
|
|
172
|
+
}
|
|
212
173
|
}
|