@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,10 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IdGenerator } from '@opentelemetry/sdk-trace-base';
|
|
2
2
|
import { SessionType } from './type';
|
|
3
|
-
export declare class SessionRecorderIdGenerator
|
|
3
|
+
export declare class SessionRecorderIdGenerator implements IdGenerator {
|
|
4
4
|
sessionShortId: string;
|
|
5
5
|
sessionType: SessionType;
|
|
6
|
-
generateLongId
|
|
6
|
+
private generateLongId;
|
|
7
|
+
private generateShortId;
|
|
7
8
|
constructor();
|
|
9
|
+
generateTraceId(): string;
|
|
10
|
+
generateSpanId(): string;
|
|
8
11
|
setSessionId(sessionShortId: string, sessionType?: SessionType): void;
|
|
9
12
|
}
|
|
10
13
|
//# sourceMappingURL=SessionRecorderIdGenerator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionRecorderIdGenerator.d.ts","sourceRoot":"","sources":["../../src/SessionRecorderIdGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"SessionRecorderIdGenerator.d.ts","sourceRoot":"","sources":["../../src/SessionRecorderIdGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAOpC,qBAAa,0BAA2B,YAAW,WAAW;IAC5D,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,WAAW,CAAA;IACxB,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,eAAe,CAAc;;IASrC,eAAe,IAAI,MAAM;IAuBzB,cAAc,IAAI,MAAM;IAIxB,YAAY,CACV,cAAc,EAAE,MAAM,EACtB,WAAW,GAAE,WAA+B;CAK/C"}
|
|
@@ -1,30 +1,32 @@
|
|
|
1
|
-
import { RandomIdGenerator } from '@opentelemetry/sdk-trace-base';
|
|
2
1
|
import { SessionType } from './type';
|
|
3
2
|
import { MULTIPLAYER_TRACE_DEBUG_PREFIX, MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX, } from './constants/constants.base';
|
|
4
3
|
import { getIdGenerator } from './sdk';
|
|
5
|
-
export class SessionRecorderIdGenerator
|
|
4
|
+
export class SessionRecorderIdGenerator {
|
|
6
5
|
constructor() {
|
|
7
|
-
super();
|
|
8
6
|
this.generateLongId = getIdGenerator(16);
|
|
7
|
+
this.generateShortId = getIdGenerator(8);
|
|
9
8
|
this.sessionShortId = '';
|
|
10
9
|
this.sessionType = SessionType.PLAIN;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const prefix = `${sessionTypePrefix}${this.sessionShortId}`;
|
|
23
|
-
const sessionTraceId = `${prefix}${traceId.substring(prefix.length, traceId.length)}`;
|
|
24
|
-
return sessionTraceId;
|
|
10
|
+
}
|
|
11
|
+
generateTraceId() {
|
|
12
|
+
const traceId = this.generateLongId();
|
|
13
|
+
if (this.sessionShortId) {
|
|
14
|
+
let sessionTypePrefix = '';
|
|
15
|
+
switch (this.sessionType) {
|
|
16
|
+
case SessionType.CONTINUOUS:
|
|
17
|
+
sessionTypePrefix = MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX;
|
|
18
|
+
break;
|
|
19
|
+
default:
|
|
20
|
+
sessionTypePrefix = MULTIPLAYER_TRACE_DEBUG_PREFIX;
|
|
25
21
|
}
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
const prefix = `${sessionTypePrefix}${this.sessionShortId}`;
|
|
23
|
+
const sessionTraceId = `${prefix}${traceId.substring(prefix.length, traceId.length)}`;
|
|
24
|
+
return sessionTraceId;
|
|
25
|
+
}
|
|
26
|
+
return traceId;
|
|
27
|
+
}
|
|
28
|
+
generateSpanId() {
|
|
29
|
+
return this.generateShortId();
|
|
28
30
|
}
|
|
29
31
|
setSessionId(sessionShortId, sessionType = SessionType.PLAIN) {
|
|
30
32
|
this.sessionShortId = sessionShortId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionRecorderIdGenerator.js","sourceRoot":"","sources":["../../src/SessionRecorderIdGenerator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SessionRecorderIdGenerator.js","sourceRoot":"","sources":["../../src/SessionRecorderIdGenerator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AACpC,OAAO,EACL,8BAA8B,EAC9B,yCAAyC,GAC1C,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAEtC,MAAM,OAAO,0BAA0B;IAMrC;QACE,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC,EAAE,CAAC,CAAA;QACxC,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC,CAAC,CAAC,CAAA;QACxC,IAAI,CAAC,cAAc,GAAG,EAAE,CAAA;QACxB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC,KAAK,CAAA;IACtC,CAAC;IAED,eAAe;QACb,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;QAErC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,iBAAiB,GAAW,EAAE,CAAA;YAClC,QAAQ,IAAI,CAAC,WAAW,EAAE,CAAC;gBACzB,KAAK,WAAW,CAAC,UAAU;oBACzB,iBAAiB,GAAG,yCAAyC,CAAA;oBAC7D,MAAK;gBACP;oBACE,iBAAiB,GAAG,8BAA8B,CAAA;YACtD,CAAC;YAED,MAAM,MAAM,GAAG,GAAG,iBAAiB,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;YAE3D,MAAM,cAAc,GAAG,GAAG,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAA;YAErF,OAAO,cAAc,CAAA;QACvB,CAAC;QAED,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,eAAe,EAAE,CAAA;IAC/B,CAAC;IAED,YAAY,CACV,cAAsB,EACtB,cAA2B,WAAW,CAAC,KAAK;QAE5C,IAAI,CAAC,cAAc,GAAG,cAAc,CAAA;QACpC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAA;IAChC,CAAC;CACF","sourcesContent":["import { IdGenerator } from '@opentelemetry/sdk-trace-base'\nimport { SessionType } from './type'\nimport {\n MULTIPLAYER_TRACE_DEBUG_PREFIX,\n MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX,\n} from './constants/constants.base'\nimport { getIdGenerator } from './sdk'\n\nexport class SessionRecorderIdGenerator implements IdGenerator {\n sessionShortId: string\n sessionType: SessionType\n private generateLongId: () => string\n private generateShortId: () => string\n\n constructor() {\n this.generateLongId = getIdGenerator(16)\n this.generateShortId = getIdGenerator(8)\n this.sessionShortId = ''\n this.sessionType = SessionType.PLAIN\n }\n\n generateTraceId(): string {\n const traceId = this.generateLongId()\n\n if (this.sessionShortId) {\n let sessionTypePrefix: string = ''\n switch (this.sessionType) {\n case SessionType.CONTINUOUS:\n sessionTypePrefix = MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX\n break\n default:\n sessionTypePrefix = MULTIPLAYER_TRACE_DEBUG_PREFIX\n }\n\n const prefix = `${sessionTypePrefix}${this.sessionShortId}`\n\n const sessionTraceId = `${prefix}${traceId.substring(prefix.length, traceId.length)}`\n\n return sessionTraceId\n }\n\n return traceId\n }\n\n generateSpanId(): string {\n return this.generateShortId()\n }\n\n setSessionId(\n sessionShortId: string,\n sessionType: SessionType = SessionType.PLAIN,\n ) {\n this.sessionShortId = sessionShortId\n this.sessionType = sessionType\n }\n}\n"]}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
export interface SessionRecorderBrowserTraceExporterConfig {
|
|
3
|
+
/** URL for the OTLP endpoint. Defaults to Multiplayer's default traces endpoint. */
|
|
4
|
+
url?: string;
|
|
4
5
|
/** API key for authentication. Required. */
|
|
5
6
|
apiKey: string;
|
|
7
|
+
/** Additional headers to include in requests */
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
/** Request timeout in milliseconds */
|
|
10
|
+
timeoutMillis?: number;
|
|
11
|
+
/** Whether to use keep-alive connections */
|
|
12
|
+
keepAlive?: boolean;
|
|
13
|
+
/** Maximum number of concurrent requests */
|
|
14
|
+
concurrencyLimit?: number;
|
|
6
15
|
/** Whether to use postMessage fallback for cross-origin requests */
|
|
7
16
|
usePostMessageFallback?: boolean;
|
|
8
17
|
/** PostMessage type identifier */
|
|
@@ -15,7 +24,8 @@ export interface SessionRecorderBrowserTraceExporterConfig extends OTLPExporterC
|
|
|
15
24
|
* Exports traces via HTTP to Multiplayer's OTLP endpoint with browser-specific optimizations
|
|
16
25
|
* Only exports spans with trace IDs starting with Multiplayer prefixes
|
|
17
26
|
*/
|
|
18
|
-
export declare class SessionRecorderBrowserTraceExporter
|
|
27
|
+
export declare class SessionRecorderBrowserTraceExporter implements SpanExporter {
|
|
28
|
+
private exporter;
|
|
19
29
|
private usePostMessage;
|
|
20
30
|
private readonly postMessageType;
|
|
21
31
|
private readonly postMessageTargetOrigin;
|
|
@@ -27,5 +37,7 @@ export declare class SessionRecorderBrowserTraceExporter extends OTLPExporterBas
|
|
|
27
37
|
shutdown(): Promise<void>;
|
|
28
38
|
private exportViaPostMessage;
|
|
29
39
|
private _serializeSpan;
|
|
40
|
+
private _createExporter;
|
|
41
|
+
setApiKey(apiKey: string): void;
|
|
30
42
|
}
|
|
31
43
|
//# sourceMappingURL=SessionRecorderBrowserTraceExporter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionRecorderBrowserTraceExporter.d.ts","sourceRoot":"","sources":["../../../src/exporters/SessionRecorderBrowserTraceExporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;
|
|
1
|
+
{"version":3,"file":"SessionRecorderBrowserTraceExporter.d.ts","sourceRoot":"","sources":["../../../src/exporters/SessionRecorderBrowserTraceExporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AAQ1E,MAAM,WAAW,yCAAyC;IACxD,oFAAoF;IACpF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAA;IACd,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,sCAAsC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,oEAAoE;IACpE,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,kCAAkC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,gCAAgC;IAChC,uBAAuB,CAAC,EAAE,MAAM,CAAA;CACjC;AAED;;;;GAIG;AACH,qBAAa,mCAAoC,YAAW,YAAY;IACtE,OAAO,CAAC,QAAQ,CAAmB;IACnC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAQ;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2C;gBAEtD,MAAM,EAAE,yCAAyC;IA2B7D,MAAM,CACJ,KAAK,EAAE,YAAY,EAAE,EACrB,cAAc,EAAE,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GACjD,IAAI;IA+BP,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,cAAc;IAyBtB,OAAO,CAAC,eAAe;IAevB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CAKhC"}
|
|
@@ -1,86 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
var t = {};
|
|
3
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
-
t[p] = s[p];
|
|
5
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
-
t[p[i]] = s[p[i]];
|
|
9
|
-
}
|
|
10
|
-
return t;
|
|
11
|
-
};
|
|
12
|
-
import { OTLPExporterBase, } from '@opentelemetry/otlp-exporter-base';
|
|
13
|
-
import { createLegacyOtlpBrowserExportDelegate, } from '@opentelemetry/otlp-exporter-base/browser-http';
|
|
1
|
+
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
14
2
|
import { MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL, MULTIPLAYER_TRACE_DEBUG_PREFIX, MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX, } from '../constants/constants.base';
|
|
15
3
|
/**
|
|
16
4
|
* Browser-specific trace exporter for Session Recorder
|
|
17
5
|
* Exports traces via HTTP to Multiplayer's OTLP endpoint with browser-specific optimizations
|
|
18
6
|
* Only exports spans with trace IDs starting with Multiplayer prefixes
|
|
19
7
|
*/
|
|
20
|
-
export class SessionRecorderBrowserTraceExporter
|
|
8
|
+
export class SessionRecorderBrowserTraceExporter {
|
|
21
9
|
constructor(config) {
|
|
22
|
-
const { url = MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL, apiKey, headers = {}, postMessageType = 'MULTIPLAYER_SESSION_DEBUGGER_LIB', postMessageTargetOrigin = '*' } = config, restConfig = __rest(config, ["url", "apiKey", "headers", "postMessageType", "postMessageTargetOrigin"]);
|
|
23
|
-
const _config = Object.assign(Object.assign({}, restConfig), { url, headers: Object.assign({ 'Content-Type': 'application/x-protobuf', 'User-Agent': '@multiplayer-app/session-recorder-common/1.0.0', 'Authorization': apiKey }, headers) });
|
|
24
|
-
super(createLegacyOtlpBrowserExportDelegate(_config, {
|
|
25
|
-
serializeRequest: (spans) => {
|
|
26
|
-
// Create a simple trace service request structure
|
|
27
|
-
const request = {
|
|
28
|
-
resourceSpans: spans.map(span => ({
|
|
29
|
-
resource: {
|
|
30
|
-
attributes: Object.entries(span.resource.attributes).map(([key, value]) => ({
|
|
31
|
-
key,
|
|
32
|
-
value: { stringValue: String(value) },
|
|
33
|
-
})),
|
|
34
|
-
},
|
|
35
|
-
scopeSpans: [{
|
|
36
|
-
spans: [{
|
|
37
|
-
traceId: span.spanContext().traceId,
|
|
38
|
-
spanId: span.spanContext().spanId,
|
|
39
|
-
parentSpanId: span.spanContext().spanId, // Using spanId as fallback
|
|
40
|
-
name: span.name,
|
|
41
|
-
kind: span.kind,
|
|
42
|
-
startTimeUnixNano: span.startTime[0] * 1e9 + span.startTime[1],
|
|
43
|
-
endTimeUnixNano: span.endTime ? span.endTime[0] * 1e9 + span.endTime[1] : undefined,
|
|
44
|
-
attributes: Object.entries(span.attributes).map(([key, value]) => ({
|
|
45
|
-
key,
|
|
46
|
-
value: { stringValue: String(value) },
|
|
47
|
-
})),
|
|
48
|
-
events: span.events.map(event => ({
|
|
49
|
-
timeUnixNano: event.time[0] * 1e9 + event.time[1],
|
|
50
|
-
name: event.name,
|
|
51
|
-
attributes: Object.entries(event.attributes || {}).map(([key, value]) => ({
|
|
52
|
-
key,
|
|
53
|
-
value: { stringValue: String(value) },
|
|
54
|
-
})),
|
|
55
|
-
})),
|
|
56
|
-
links: span.links.map(link => ({
|
|
57
|
-
traceId: link.context.traceId,
|
|
58
|
-
spanId: link.context.spanId,
|
|
59
|
-
attributes: Object.entries(link.attributes || {}).map(([key, value]) => ({
|
|
60
|
-
key,
|
|
61
|
-
value: { stringValue: String(value) },
|
|
62
|
-
})),
|
|
63
|
-
})),
|
|
64
|
-
status: {
|
|
65
|
-
code: span.status.code,
|
|
66
|
-
message: span.status.message || '',
|
|
67
|
-
},
|
|
68
|
-
}],
|
|
69
|
-
}],
|
|
70
|
-
})),
|
|
71
|
-
};
|
|
72
|
-
const encoder = new TextEncoder();
|
|
73
|
-
return encoder.encode(JSON.stringify(request));
|
|
74
|
-
},
|
|
75
|
-
deserializeResponse: (arg) => {
|
|
76
|
-
const decoder = new TextDecoder();
|
|
77
|
-
return JSON.parse(decoder.decode(arg));
|
|
78
|
-
},
|
|
79
|
-
}, 'v1/traces', { 'Content-Type': 'application/json' }));
|
|
80
10
|
this.usePostMessage = false;
|
|
81
|
-
|
|
11
|
+
const { url = MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL, apiKey, headers = {}, timeoutMillis = 30000, keepAlive = true, concurrencyLimit = 20, postMessageType = 'MULTIPLAYER_SESSION_DEBUGGER_LIB', postMessageTargetOrigin = '*', } = config;
|
|
12
|
+
this.config = Object.assign(Object.assign({}, config), { url,
|
|
13
|
+
apiKey,
|
|
14
|
+
headers,
|
|
15
|
+
timeoutMillis,
|
|
16
|
+
keepAlive,
|
|
17
|
+
concurrencyLimit });
|
|
82
18
|
this.postMessageType = postMessageType;
|
|
83
19
|
this.postMessageTargetOrigin = postMessageTargetOrigin;
|
|
20
|
+
this.exporter = this._createExporter();
|
|
84
21
|
}
|
|
85
22
|
export(spans, resultCallback) {
|
|
86
23
|
// Filter spans to only include those with Multiplayer trace prefixes
|
|
@@ -98,7 +35,7 @@ export class SessionRecorderBrowserTraceExporter extends OTLPExporterBase {
|
|
|
98
35
|
this.exportViaPostMessage(filteredSpans, resultCallback);
|
|
99
36
|
return;
|
|
100
37
|
}
|
|
101
|
-
|
|
38
|
+
this.exporter.export(filteredSpans, (result) => {
|
|
102
39
|
if (result.code === 0) {
|
|
103
40
|
resultCallback(result);
|
|
104
41
|
}
|
|
@@ -112,7 +49,7 @@ export class SessionRecorderBrowserTraceExporter extends OTLPExporterBase {
|
|
|
112
49
|
});
|
|
113
50
|
}
|
|
114
51
|
shutdown() {
|
|
115
|
-
return
|
|
52
|
+
return this.exporter.shutdown();
|
|
116
53
|
}
|
|
117
54
|
exportViaPostMessage(spans, resultCallback) {
|
|
118
55
|
if (typeof window === 'undefined') {
|
|
@@ -132,6 +69,7 @@ export class SessionRecorderBrowserTraceExporter extends OTLPExporterBase {
|
|
|
132
69
|
}
|
|
133
70
|
}
|
|
134
71
|
_serializeSpan(span) {
|
|
72
|
+
var _a;
|
|
135
73
|
const spanContext = span.spanContext();
|
|
136
74
|
return {
|
|
137
75
|
_spanContext: spanContext,
|
|
@@ -145,7 +83,7 @@ export class SessionRecorderBrowserTraceExporter extends OTLPExporterBase {
|
|
|
145
83
|
startTime: span.startTime,
|
|
146
84
|
duration: span.duration,
|
|
147
85
|
attributes: span.attributes,
|
|
148
|
-
parentSpanId:
|
|
86
|
+
parentSpanId: (_a = span.parentSpanContext) === null || _a === void 0 ? void 0 : _a.spanId,
|
|
149
87
|
droppedAttributesCount: span.droppedAttributesCount,
|
|
150
88
|
droppedEventsCount: span.droppedEventsCount,
|
|
151
89
|
droppedLinksCount: span.droppedLinksCount,
|
|
@@ -155,5 +93,18 @@ export class SessionRecorderBrowserTraceExporter extends OTLPExporterBase {
|
|
|
155
93
|
},
|
|
156
94
|
};
|
|
157
95
|
}
|
|
96
|
+
_createExporter() {
|
|
97
|
+
return new OTLPTraceExporter({
|
|
98
|
+
url: this.config.url,
|
|
99
|
+
headers: Object.assign({ 'Content-Type': 'application/x-protobuf', 'User-Agent': '@multiplayer-app/session-recorder-common/1.0.0', 'authorization': this.config.apiKey }, (this.config.headers || {})),
|
|
100
|
+
timeoutMillis: this.config.timeoutMillis,
|
|
101
|
+
keepAlive: this.config.keepAlive,
|
|
102
|
+
concurrencyLimit: this.config.concurrencyLimit,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
setApiKey(apiKey) {
|
|
106
|
+
this.config.apiKey = apiKey;
|
|
107
|
+
this.exporter = this._createExporter();
|
|
108
|
+
}
|
|
158
109
|
}
|
|
159
110
|
//# sourceMappingURL=SessionRecorderBrowserTraceExporter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionRecorderBrowserTraceExporter.js","sourceRoot":"","sources":["../../../src/exporters/SessionRecorderBrowserTraceExporter.ts"],"names":[],"mappings":"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","sourcesContent":["import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base'\nimport {\n OTLPExporterConfigBase,\n OTLPExporterBase,\n} from '@opentelemetry/otlp-exporter-base'\nimport {\n createLegacyOtlpBrowserExportDelegate,\n} from '@opentelemetry/otlp-exporter-base/browser-http'\nimport {\n MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,\n MULTIPLAYER_TRACE_DEBUG_PREFIX,\n MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX,\n} from '../constants/constants.base'\n\nexport interface SessionRecorderBrowserTraceExporterConfig\n extends OTLPExporterConfigBase {\n /** API key for authentication. Required. */\n apiKey: string\n /** Whether to use postMessage fallback for cross-origin requests */\n usePostMessageFallback?: boolean\n /** PostMessage type identifier */\n postMessageType?: string\n /** PostMessage target origin */\n postMessageTargetOrigin?: string\n}\n\n/**\n * Browser-specific trace exporter for Session Recorder\n * Exports traces via HTTP to Multiplayer's OTLP endpoint with browser-specific optimizations\n * Only exports spans with trace IDs starting with Multiplayer prefixes\n */\nexport class SessionRecorderBrowserTraceExporter\n extends OTLPExporterBase<ReadableSpan[]>\n implements SpanExporter {\n\n private usePostMessage: boolean = false\n private readonly postMessageType: string\n private readonly postMessageTargetOrigin: string\n private readonly config: SessionRecorderBrowserTraceExporterConfig\n\n constructor(config: SessionRecorderBrowserTraceExporterConfig) {\n const {\n url = MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,\n apiKey,\n headers = {},\n postMessageType = 'MULTIPLAYER_SESSION_DEBUGGER_LIB',\n postMessageTargetOrigin = '*',\n ...restConfig\n } = config\n\n const _config = {\n ...restConfig,\n url,\n headers: {\n 'Content-Type': 'application/x-protobuf',\n 'User-Agent': '@multiplayer-app/session-recorder-common/1.0.0',\n 'Authorization': apiKey,\n ...headers,\n },\n }\n\n super(\n createLegacyOtlpBrowserExportDelegate(\n _config,\n {\n serializeRequest: (spans: ReadableSpan[]) => {\n // Create a simple trace service request structure\n const request = {\n resourceSpans: spans.map(span => ({\n resource: {\n attributes: Object.entries(span.resource.attributes).map(([key, value]) => ({\n key,\n value: { stringValue: String(value) },\n })),\n },\n scopeSpans: [{\n spans: [{\n traceId: span.spanContext().traceId,\n spanId: span.spanContext().spanId,\n parentSpanId: span.spanContext().spanId, // Using spanId as fallback\n name: span.name,\n kind: span.kind,\n startTimeUnixNano: span.startTime[0] * 1e9 + span.startTime[1],\n endTimeUnixNano: span.endTime ? span.endTime[0] * 1e9 + span.endTime[1] : undefined,\n attributes: Object.entries(span.attributes).map(([key, value]) => ({\n key,\n value: { stringValue: String(value) },\n })),\n events: span.events.map(event => ({\n timeUnixNano: event.time[0] * 1e9 + event.time[1],\n name: event.name,\n attributes: Object.entries(event.attributes || {}).map(([key, value]) => ({\n key,\n value: { stringValue: String(value) },\n })),\n })),\n links: span.links.map(link => ({\n traceId: link.context.traceId,\n spanId: link.context.spanId,\n attributes: Object.entries(link.attributes || {}).map(([key, value]) => ({\n key,\n value: { stringValue: String(value) },\n })),\n })),\n status: {\n code: span.status.code,\n message: span.status.message || '',\n },\n }],\n }],\n })),\n }\n\n const encoder = new TextEncoder()\n return encoder.encode(JSON.stringify(request))\n },\n deserializeResponse: (arg: Uint8Array) => {\n const decoder = new TextDecoder()\n return JSON.parse(decoder.decode(arg))\n },\n },\n 'v1/traces',\n { 'Content-Type': 'application/json' },\n ),\n )\n\n this.config = config\n this.postMessageType = postMessageType\n this.postMessageTargetOrigin = postMessageTargetOrigin\n }\n\n override export(spans: ReadableSpan[], resultCallback: (result: { code: number }) => void): void {\n // Filter spans to only include those with Multiplayer trace prefixes\n const filteredSpans = spans.filter(span => {\n const traceId = span.spanContext().traceId\n return traceId.startsWith(MULTIPLAYER_TRACE_DEBUG_PREFIX) ||\n traceId.startsWith(MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX)\n })\n\n // Only proceed if there are filtered spans\n if (filteredSpans.length === 0) {\n resultCallback({ code: 0 })\n return\n }\n\n if (this.usePostMessage) {\n this.exportViaPostMessage(filteredSpans, resultCallback)\n return\n }\n\n super.export(filteredSpans, (result) => {\n if (result.code === 0) {\n resultCallback(result)\n } else if (this.config.usePostMessageFallback) {\n this.usePostMessage = true\n this.exportViaPostMessage(filteredSpans, resultCallback)\n } else {\n resultCallback(result)\n }\n })\n }\n\n override shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n private exportViaPostMessage(spans: ReadableSpan[], resultCallback: (result: { code: number }) => void): void {\n if (typeof window === 'undefined') {\n resultCallback({ code: 1 })\n return\n }\n\n try {\n window.postMessage(\n {\n action: 'traces',\n type: this.postMessageType,\n payload: spans.map(span => this._serializeSpan(span)),\n },\n this.postMessageTargetOrigin,\n )\n resultCallback({ code: 0 })\n } catch (e) {\n resultCallback({ code: 1 })\n }\n }\n\n private _serializeSpan(span: ReadableSpan): any {\n const spanContext = span.spanContext()\n return {\n _spanContext: spanContext,\n name: span.name,\n kind: span.kind,\n links: span.links,\n ended: span.ended,\n events: span.events,\n status: span.status,\n endTime: span.endTime,\n startTime: span.startTime,\n duration: span.duration,\n attributes: span.attributes,\n parentSpanId: spanContext.spanId, // Using spanId as parentSpanId is not available in newer versions\n droppedAttributesCount: span.droppedAttributesCount,\n droppedEventsCount: span.droppedEventsCount,\n droppedLinksCount: span.droppedLinksCount,\n resource: {\n attributes: span.resource.attributes,\n asyncAttributesPending: span.resource.asyncAttributesPending,\n },\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SessionRecorderBrowserTraceExporter.js","sourceRoot":"","sources":["../../../src/exporters/SessionRecorderBrowserTraceExporter.ts"],"names":[],"mappings":"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","sourcesContent":["import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base'\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport {\n MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,\n MULTIPLAYER_TRACE_DEBUG_PREFIX,\n MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX,\n} from '../constants/constants.base'\n\nexport interface SessionRecorderBrowserTraceExporterConfig {\n /** URL for the OTLP endpoint. Defaults to Multiplayer's default traces endpoint. */\n url?: string\n /** API key for authentication. Required. */\n apiKey: string\n /** Additional headers to include in requests */\n headers?: Record<string, string>\n /** Request timeout in milliseconds */\n timeoutMillis?: number\n /** Whether to use keep-alive connections */\n keepAlive?: boolean\n /** Maximum number of concurrent requests */\n concurrencyLimit?: number\n /** Whether to use postMessage fallback for cross-origin requests */\n usePostMessageFallback?: boolean\n /** PostMessage type identifier */\n postMessageType?: string\n /** PostMessage target origin */\n postMessageTargetOrigin?: string\n}\n\n/**\n * Browser-specific trace exporter for Session Recorder\n * Exports traces via HTTP to Multiplayer's OTLP endpoint with browser-specific optimizations\n * Only exports spans with trace IDs starting with Multiplayer prefixes\n */\nexport class SessionRecorderBrowserTraceExporter implements SpanExporter {\n private exporter: OTLPTraceExporter\n private usePostMessage: boolean = false\n private readonly postMessageType: string\n private readonly postMessageTargetOrigin: string\n private readonly config: SessionRecorderBrowserTraceExporterConfig\n\n constructor(config: SessionRecorderBrowserTraceExporterConfig) {\n const {\n url = MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,\n apiKey,\n headers = {},\n timeoutMillis = 30000,\n keepAlive = true,\n concurrencyLimit = 20,\n postMessageType = 'MULTIPLAYER_SESSION_DEBUGGER_LIB',\n postMessageTargetOrigin = '*',\n } = config\n\n this.config = {\n ...config,\n url,\n apiKey,\n headers,\n timeoutMillis,\n keepAlive,\n concurrencyLimit,\n }\n this.postMessageType = postMessageType\n this.postMessageTargetOrigin = postMessageTargetOrigin\n\n this.exporter = this._createExporter()\n }\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: { code: number }) => void,\n ): void {\n // Filter spans to only include those with Multiplayer trace prefixes\n const filteredSpans = spans.filter(span => {\n const traceId = span.spanContext().traceId\n return traceId.startsWith(MULTIPLAYER_TRACE_DEBUG_PREFIX) ||\n traceId.startsWith(MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX)\n })\n\n // Only proceed if there are filtered spans\n if (filteredSpans.length === 0) {\n resultCallback({ code: 0 })\n return\n }\n\n if (this.usePostMessage) {\n this.exportViaPostMessage(filteredSpans, resultCallback)\n return\n }\n\n this.exporter.export(filteredSpans, (result) => {\n if (result.code === 0) {\n resultCallback(result)\n } else if (this.config.usePostMessageFallback) {\n this.usePostMessage = true\n this.exportViaPostMessage(filteredSpans, resultCallback)\n } else {\n resultCallback(result)\n }\n })\n }\n\n shutdown(): Promise<void> {\n return this.exporter.shutdown()\n }\n\n private exportViaPostMessage(spans: ReadableSpan[], resultCallback: (result: { code: number }) => void): void {\n if (typeof window === 'undefined') {\n resultCallback({ code: 1 })\n return\n }\n\n try {\n window.postMessage(\n {\n action: 'traces',\n type: this.postMessageType,\n payload: spans.map(span => this._serializeSpan(span)),\n },\n this.postMessageTargetOrigin,\n )\n resultCallback({ code: 0 })\n } catch (e) {\n resultCallback({ code: 1 })\n }\n }\n\n private _serializeSpan(span: ReadableSpan): any {\n const spanContext = span.spanContext()\n return {\n _spanContext: spanContext,\n name: span.name,\n kind: span.kind,\n links: span.links,\n ended: span.ended,\n events: span.events,\n status: span.status,\n endTime: span.endTime,\n startTime: span.startTime,\n duration: span.duration,\n attributes: span.attributes,\n parentSpanId: span.parentSpanContext?.spanId,\n droppedAttributesCount: span.droppedAttributesCount,\n droppedEventsCount: span.droppedEventsCount,\n droppedLinksCount: span.droppedLinksCount,\n resource: {\n attributes: span.resource.attributes,\n asyncAttributesPending: span.resource.asyncAttributesPending,\n },\n }\n }\n\n private _createExporter(): OTLPTraceExporter {\n return new OTLPTraceExporter({\n url: this.config.url,\n headers: {\n 'Content-Type': 'application/x-protobuf',\n 'User-Agent': '@multiplayer-app/session-recorder-common/1.0.0',\n 'authorization': this.config.apiKey,\n ...(this.config.headers || {}),\n },\n timeoutMillis: this.config.timeoutMillis,\n keepAlive: this.config.keepAlive,\n concurrencyLimit: this.config.concurrencyLimit,\n })\n }\n\n setApiKey(apiKey: string): void {\n this.config.apiKey = apiKey\n\n this.exporter = this._createExporter()\n }\n}\n"]}
|