@multiplayer-app/session-recorder-node 1.2.1 → 1.2.2

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/LICENSE CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  MIT License
3
2
 
4
3
  Copyright (c) 2024 Multiplayer Software, Inc.
package/README.md CHANGED
@@ -1,96 +1,230 @@
1
- # Session Recorder
1
+ ![Description](../../docs/img/header-js.png)
2
+
3
+ <div align="center">
4
+ <a href="https://github.com/multiplayer-app/multiplayer-session-recorder-javascript">
5
+ <img src="https://img.shields.io/github/stars/multiplayer-app/multiplayer-session-recorder-javascript?style=social&label=Star&maxAge=2592000" alt="GitHub stars">
6
+ </a>
7
+ <a href="https://github.com/multiplayer-app/multiplayer-session-recorder-javascript/blob/main/LICENSE">
8
+ <img src="https://img.shields.io/github/license/multiplayer-app/multiplayer-session-recorder-javascript" alt="License">
9
+ </a>
10
+ <a href="https://multiplayer.app">
11
+ <img src="https://img.shields.io/badge/Visit-multiplayer.app-blue" alt="Visit Multiplayer">
12
+ </a>
13
+
14
+ </div>
15
+ <div>
16
+ <p align="center">
17
+ <a href="https://x.com/trymultiplayer">
18
+ <img src="https://img.shields.io/badge/Follow%20on%20X-000000?style=for-the-badge&logo=x&logoColor=white" alt="Follow on X" />
19
+ </a>
20
+ <a href="https://www.linkedin.com/company/multiplayer-app/">
21
+ <img src="https://img.shields.io/badge/Follow%20on%20LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white" alt="Follow on LinkedIn" />
22
+ </a>
23
+ <a href="https://discord.com/invite/q9K3mDzfrx">
24
+ <img src="https://img.shields.io/badge/Join%20our%20Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" alt="Join our Discord" />
25
+ </a>
26
+ </p>
27
+ </div>
28
+
29
+ # Multiplayer Full Stack Session Recorder
30
+
31
+ The Multiplayer Full Stack Session Recorder is a powerful tool that offers deep session replays with insights spanning frontend screens, platform traces, metrics, and logs. It helps your team pinpoint and resolve bugs faster by providing a complete picture of your backend system architecture. No more wasted hours combing through APM data; the Multiplayer Full Stack Session Recorder does it all in one place.
32
+
33
+ ## Install
2
34
 
3
- The Multiplayer **Session Recorder** is a powerful tool that offers deep session replays with insights spanning frontend screens, platform traces, metrics, and logs. It helps your team pinpoint and resolve bugs faster by providing a complete picture of your backend system architecture. No more wasted hours combing through APM data; the Multiplayer Session Recorder does it all in one place.
35
+ ```bash
36
+ npm i @multiplayer-app/session-recorder-node
37
+ # or
38
+ yarn add @multiplayer-app/session-recorder-node
39
+ ```
4
40
 
5
- ## Key Features
41
+ ## Set up backend services
6
42
 
7
- - **Reduced Inefficiencies**: Effortlessly capture the exact steps to reproduce an issue along with backend data in one click. No more hunting through scattered documentation, APM data, logs, or traces.
8
- - **Faster Cross-Team Alignment**: Engineers can share session links containing all relevant information, eliminating the need for long tickets or clarifying issues through back-and-forth communication.
9
- - **Uninterrupted Deep Work**: All system information—from architecture diagrams to API designs—is consolidated in one place. Minimize context switching and stay focused on what matters.
43
+ ### Route traces and logs to Multiplayer
10
44
 
11
- ## Getting Started
45
+ Multiplayer Full Stack Session Recorder is built on top of OpenTelemetry.
12
46
 
13
- ### Installation
47
+ ### New to OpenTelemetry?
14
48
 
15
- You can install the Session Recorder using npm or yarn:
49
+ No problem. You can set it up in a few minutes. If your services don't already use OpenTelemetry, you'll first need to install the OpenTelemetry libraries. Detailed instructions for this can be found in the [OpenTelemetry documentation](https://opentelemetry.io/docs/).
16
50
 
17
- ```bash
18
- npm install @multiplayer-app/session-recorder-node
19
- # or
20
- yarn add @multiplayer-app/session-recorder-node
51
+ ### Already using OpenTelemetry?
52
+
53
+ You have two primary options for routing your data to Multiplayer:
54
+
55
+ ***Direct Exporter***: This option involves using the Multiplayer Exporter directly within your services. It's a great choice for new applications or startups because it's simple to set up and doesn't require any additional infrastructure. You can configure it to send all session recording data to Multiplayer while optionally sending a sampled subset of data to your existing observability platform.
56
+
57
+ ***OpenTelemetry Collector***: For large, scaled platforms, we recommend using an OpenTelemetry Collector. This approach provides more flexibility by having your services send all telemetry to the collector, which then routes specific session recording data to Multiplayer and other data to your existing observability tools.
58
+
59
+
60
+ ### Option 1: Direct Exporter
61
+
62
+ Send OpenTelemetry data from your services to Multiplayer and optionally other destinations (e.g., OpenTelemetry Collectors, observability platforms, etc.).
63
+
64
+ This is the quickest way to get started, but consider using an OpenTelemetry Collector (see [Option 2](#option-2-opentelemetry-collector) below) if you're scalling or a have a large platform.
65
+
66
+ ```javascript
67
+ import {
68
+ SessionRecorderHttpTraceExporter,
69
+ SessionRecorderHttpLogsExporter,
70
+ SessionRecorderTraceExporterWrapper
71
+ SessionRecorderLogsExporterWrapper,
72
+ } from "@multiplayer-app/session-recorder-node"
73
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
74
+ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http"
75
+
76
+ // set up Multiplayer exporters. Note: GRPC exporters are also available.
77
+ // see: `SessionRecorderGrpcTraceExporter` and `SessionRecorderGrpcLogsExporter`
78
+ const multiplayerTraceExporter = new SessionRecorderHttpTraceExporter({
79
+ apiKey: "MULTIPLAYER_OTLP_KEY", // note: replace with your Multiplayer OTLP key
80
+ })
81
+ const multiplayerLogExporter = new SessionRecorderHttpLogsExporter({
82
+ apiKey: "MULTIPLAYER_OTLP_KEY", // note: replace with your Multiplayer OTLP key
83
+ })
84
+
85
+ // Multiplayer exporter wrappers filter out session recording atrtributes before passing to provided exporter
86
+ const traceExporter = new SessionRecorderTraceExporterWrapper(
87
+ // add any OTLP trace exporter
88
+ new OTLPTraceExporter({
89
+ // ...
90
+ })
91
+ )
92
+ const logExporter = new SessionRecorderLogsExporterWrapper(
93
+ // add any OTLP log exporter
94
+ new OTLPLogExporter({
95
+ // ...
96
+ })
97
+ )
21
98
  ```
22
99
 
23
- ### Basic Setup
100
+ ### Option 2: OpenTelemetry Collector
24
101
 
25
- To initialize the Session Recorder in your application, follow the steps below.
102
+ If you're scalling or a have a large platform, consider running a dedicated collector. See the Multiplayer OpenTelemetry collector [repository](https://github.com/multiplayer-app/multiplayer-otlp-collector) which shows how to configure the standard OpenTelemetry Collector to send data to Multiplayer and optional other destinations.
26
103
 
27
- #### Import the Session Recorder
104
+ Add standard [OpenTelemetry code](https://opentelemetry.io/docs/languages/js/exporters/) to export OTLP data to your collector.
105
+
106
+ See a basic example below:
28
107
 
29
108
  ```javascript
30
- import SessionRecorder from '@multiplayer-app/session-recorder-node'
31
- // Multiplayer trace id generator which is used during opentelemetry initialization
32
- import { idGenerator } from './opentelemetry'
109
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
110
+ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http"
111
+
112
+ const traceExporter = new OTLPTraceExporter({
113
+ url: "http://<OTLP_COLLECTOR_URL>/v1/traces",
114
+ headers: {
115
+ // ...
116
+ }
117
+ })
118
+
119
+ const logExporter = new OTLPLogExporter({
120
+ url: "http://<OTLP_COLLECTOR_URL>/v1/logs",
121
+ headers: {
122
+ // ...
123
+ }
124
+ })
33
125
  ```
34
126
 
35
- #### Initialization
127
+ ### Capturing request/response and header content
128
+
129
+ In addition to sending traces and logs, you need to capture request and response content. We offer two solutions for this:
130
+
131
+ ***In-Service Code Capture:*** You can use our libraries to capture, serialize, and mask request/response and header content directly within your service code. This is an easy way to get started, especially for new projects, as it requires no extra components in your platform.
132
+
133
+ ***Multiplayer Proxy:*** Alternatively, you can run a [Multiplayer Proxy](https://github.com/multiplayer-app/multiplayer-proxy) to handle this outside of your services. This is ideal for large-scale applications and supports all languages, including those like Java that don't allow for in-service request/response hooks. The proxy can be deployed in various ways, such as an Ingress Proxy, a Sidecar Proxy, or an Embedded Proxy, to best fit your architecture.
36
134
 
37
- Use the following code to initialize the session recorder with your application details:
135
+ ### Option 1: In-Service Code Capture
136
+
137
+ The Multiplayer Session Recorder library provides utilities for capturing request, response and header content. See example below:
38
138
 
39
139
  ```javascript
40
- SessionRecorder.init({
41
- apiKey: '{YOUR_API_KEY}',
42
- traceIdGenerator: idGenerator,
43
- resourceAttributes: {
44
- serviceName: '{YOUR_APPLICATION_NAME}'
45
- version: '{YOUR_APPLICATION_VERSION}',
46
- environment: '{YOUR_APPLICATION_ENVIRONMENT}',
47
- }
48
- })
140
+ import {
141
+ SessionRecorderHttpInstrumentationHooksNode,
142
+ } from "@multiplayer-app/session-recorder-node"
143
+ import {
144
+ getNodeAutoInstrumentations,
145
+ } from "@opentelemetry/auto-instrumentations-node"
146
+ import { type Instrumentation } from "@opentelemetry/instrumentation"
147
+
148
+ export const instrumentations: Instrumentation[] = getNodeAutoInstrumentations({
149
+ "@opentelemetry/instrumentation-http": {
150
+ enabled: true,
151
+ responseHook: SessionRecorderHttpInstrumentationHooksNode.responseHook({
152
+ // list of headers to mask in request/response headers
153
+ maskHeadersList: ["set-cookie"],
154
+ // set the maximum request/response content size (in bytes) that will be captured
155
+ // any request/response content greater than size will be not included in session recordings
156
+ maxPayloadSizeBytes: 500000,
157
+ isMaskBodyEnabled: false,
158
+ isMaskHeadersEnabled: true,
159
+ }),
160
+ requestHook: SessionRecorderHttpInstrumentationHooksNode.requestHook({
161
+ maskHeadersList: ["Authorization", "cookie"],
162
+ maxPayloadSizeBytes: 500000,
163
+ isMaskBodyEnabled: false,
164
+ isMaskHeadersEnabled: true,
165
+ }),
166
+ }
167
+ })
49
168
  ```
50
169
 
51
- Replace the placeholders with your application’s version, name, environment, and API key.
170
+ ### Option 2: Multiplayer Proxy
171
+
172
+ The Multiplayer Proxy enables capturing request/response and header content without changing service code. See instructions at the [Multiplayer Proxy repository](https://github.com/multiplayer-app/multiplayer-proxy).
52
173
 
53
- ## Dependencies
174
+ ## Set up CLI app
54
175
 
55
- This library relies on the following packages:
176
+ The Multiplayer Full Stack Session Recorder can be used inside the CLI apps.
56
177
 
57
- - **[OpenTelemetry](https://opentelemetry.io/)**: Used to capture backend traces, metrics, and logs that integrate seamlessly with the session replays for comprehensive debugging.
178
+ The [Multiplayer Time Travel Demo](https://github.com/multiplayer-app/multiplayer-time-travel-platform) includes an example [node.js CLI app](https://github.com/multiplayer-app/multiplayer-time-travel-platform/tree/main/clients/nodejs-cli-app).
58
179
 
59
- ## Example Usage
180
+ See an additional example below.
181
+
182
+ ### Quick start
183
+
184
+ Use the following code below to initialize and run the session recorder.
60
185
 
61
186
  ```javascript
187
+ // IMPORTANT: set up OpenTelemetry
188
+ // for an example see ./session-recorder-node/examples/opentelemetry.ts
189
+ // NOTE: for the code below to work copy examples/opentelemetry.ts to ./opentelemetry.ts
190
+ import { idGenerator } from "./opentelemetry"
191
+ import SessionRecorder from "@multiplayer-app/session-recorder-node"
62
192
  import {
63
- sessionRecorder,
64
- SessionType
65
- } from '@multiplayer-app/session-recorder-node'
66
- // Session recorder trace id generator which is used during opentelemetry initialization
67
- import { idGenerator } from './opentelemetry'
68
-
69
- sessionRecorder.init({
70
- apiKey: '{YOUR_API_KEY}',
193
+ SessionRecorderHttpInstrumentationHooksNode,
194
+ SessionRecorderTraceIdRatioBasedSampler,
195
+ SessionRecorderIdGenerator,
196
+ SessionRecorderHttpTraceExporter,
197
+ SessionRecorderHttpLogsExporter,
198
+ } from "@multiplayer-app/session-recorder-node"
199
+
200
+ SessionRecorder.init({
201
+ apiKey: "MULTIPLAYER_OTLP_KEY", // note: replace with your Multiplayer OTLP key
71
202
  traceIdGenerator: idGenerator,
72
203
  resourceAttributes: {
73
- serviceName: '{YOUR_APPLICATION_NAME}',
74
- version: '{YOUR_APPLICATION_VERSION}',
75
- environment: '{YOUR_APPLICATION_ENVIRONMENT}',
204
+ serviceName: "{YOUR_APPLICATION_NAME}"
205
+ version: "{YOUR_APPLICATION_VERSION}",
206
+ environment: "{YOUR_APPLICATION_ENVIRONMENT}",
76
207
  }
77
208
  })
78
209
 
79
- // ...
80
-
81
- await sessionRecorder.start(
82
- SessionType.PLAIN,
83
- {
84
- name: 'This is test session',
85
- sessionAttributes: {
86
- accountId: '687e2c0d3ec8ef6053e9dc97',
87
- accountName: 'Acme Corporation'
88
- }
210
+ await sessionRecorder.start(
211
+ SessionType.PLAIN,
212
+ {
213
+ name: "This is test session",
214
+ sessionAttributes: {
215
+ accountId: "687e2c0d3ec8ef6053e9dc97",
216
+ accountName: "Acme Corporation"
89
217
  }
90
- )
91
-
92
- // do something here
218
+ }
219
+ )
93
220
 
94
- await sessionRecorder.stop()
221
+ // do something here
95
222
 
223
+ await sessionRecorder.stop()
96
224
  ```
225
+
226
+ Replace the placeholders with your application’s version, name, environment, and API key.
227
+
228
+ ## License
229
+
230
+ MIT — see [LICENSE](./LICENSE).
@@ -1 +1 @@
1
- {"version":3,"file":"sessionRecorder.d.ts","sourceRoot":"","sources":["../src/sessionRecorder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAEX,0BAA0B,EAG3B,MAAM,0CAA0C,CAAA;AAEjD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIlC,qBAAa,eAAe;IAC1B,OAAO,CAAC,cAAc,CAAQ;IAE9B,OAAO,CAAC,eAAe,CAA0B;IAEjD,OAAO,CAAC,iBAAiB,CAAwC;IACjE,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,wBAAwB,CAAqF;IAErH,OAAO,CAAC,mBAAmB,CAAa;IAExC;;OAEG;;IAGH;;;;;;;;OAQG;IACI,IAAI,CAAC,MAAM,EAAE;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,gBAAgB,EAAE,0BAA0B,CAAC;QAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,6BAA6B,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;QACzD,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,GAAG,IAAI;IAyBR;;;;;OAKG;IACU,KAAK,CAChB,WAAW,EAAE,WAAW,EACxB,cAAc,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC;IAiDhB;;;;OAIG;WACU,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM;IAIjC;;;;OAIG;IACU,IAAI,CACf,WAAW,CAAC,EAAE,QAAQ,GACrB,OAAO,CAAC,IAAI,CAAC;IAiChB;;;;OAIG;IACU,IAAI,CACf,WAAW,CAAC,EAAE,QAAQ,GACrB,OAAO,CAAC,IAAI,CAAC;IAiChB;;;OAGG;IACU,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BpC;;;;OAIG;IACU,4BAA4B,CACvC,cAAc,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC,GACjD,OAAO,CAAC,IAAI,CAAC;CAsBjB"}
1
+ {"version":3,"file":"sessionRecorder.d.ts","sourceRoot":"","sources":["../src/sessionRecorder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAEX,0BAA0B,EAG3B,MAAM,0CAA0C,CAAA;AAEjD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIlC,qBAAa,eAAe;IAC1B,OAAO,CAAC,cAAc,CAAQ;IAE9B,OAAO,CAAC,eAAe,CAA0B;IAEjD,OAAO,CAAC,iBAAiB,CAAwC;IACjE,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,wBAAwB,CAAqF;IAErH,OAAO,CAAC,mBAAmB,CAAa;IAExC;;OAEG;;IAGH;;;;;;;;OAQG;IACI,IAAI,CAAC,MAAM,EAAE;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,gBAAgB,EAAE,0BAA0B,CAAC;QAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,6BAA6B,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;QACzD,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,GAAG,IAAI;IAyBR;;;;;OAKG;IACU,KAAK,CAChB,WAAW,EAAE,WAAW,EACxB,cAAc,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC;IAqDhB;;;;OAIG;WACU,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM;IAIjC;;;;OAIG;IACU,IAAI,CACf,WAAW,CAAC,EAAE,QAAQ,GACrB,OAAO,CAAC,IAAI,CAAC;IAiChB;;;;OAIG;IACU,IAAI,CACf,WAAW,CAAC,EAAE,QAAQ,GACrB,OAAO,CAAC,IAAI,CAAC;IAiChB;;;OAGG;IACU,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BpC;;;;OAIG;IACU,4BAA4B,CACvC,cAAc,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC,GACjD,OAAO,CAAC,IAAI,CAAC;CAsBjB"}
@@ -82,6 +82,9 @@ class SessionRecorder {
82
82
  else {
83
83
  session = await this._apiService.startSession(sessionPayload);
84
84
  }
85
+ if (!(session === null || session === void 0 ? void 0 : session.shortId)) {
86
+ throw new Error('Failed to start session');
87
+ }
85
88
  this._shortSessionId = session.shortId;
86
89
  this._traceIdGenerator.setSessionId(this._shortSessionId, this._sessionType);
87
90
  this._sessionState = 'STARTED';
@@ -1 +1 @@
1
- {"version":3,"file":"sessionRecorder.js","sourceRoot":"","sources":["../src/sessionRecorder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessionRecorder.js","sourceRoot":"","sources":["../src/sessionRecorder.ts"],"names":[],"mappings":";;;AAAA,sFAMiD;AACjD,wDAAmD;AAEnD,qCAA2C;AAC3C,qCAAmD;AAEnD,MAAa,eAAe;IAa1B;;OAEG;IACH;QAfQ,mBAAc,GAAG,KAAK,CAAA;QAEtB,oBAAe,GAAqB,KAAK,CAAA;QAGzC,iBAAY,GAAgB,qCAAW,CAAC,KAAK,CAAA;QAC7C,kBAAa,GAAqC,SAAS,CAAA;QAC3D,gBAAW,GAAG,IAAI,wBAAU,EAAE,CAAA;QAC9B,6BAAwB,GAAG,4CAAkB,CAAC,cAAc,CAAC,yEAA+C,CAAC,CAAA;QAE7G,wBAAmB,GAAW,EAAE,CAAA;IAKxB,CAAC;IAEjB;;;;;;;;OAQG;IACI,IAAI,CAAC,MAMX;;QACC,IAAI,CAAC,mBAAmB,GAAG,MAAM,CAAC,kBAAkB,IAAI;YACtD,CAAC,mEAAyC,CAAC,EAAE,iCAAwB;SACtE,CAAA;QACD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;QAE1B,IAAI,OAAO,MAAM,CAAC,6BAA6B,KAAK,UAAU,EAAE,CAAC;YAC/D,IAAI,CAAC,wBAAwB,GAAG,MAAM,CAAC,6BAA6B,CAAA;QACtE,CAAC;QAED,IAAI,CAAC,CAAA,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,0CAAE,MAAM,CAAA,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAA;QACzC,CAAC;QAED,IAAI,CAAC,CAAA,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,gBAAgB,0CAAE,YAAY,CAAA,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;QACpD,CAAC;QAED,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC,gBAAgB,CAAA;QAChD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YACpB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC,CAAA;IACJ,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,KAAK,CAChB,WAAwB,EACxB,cAAsC;;QAEtC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAA;QACH,CAAC;QAED,IACE,CAAA,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,OAAO;eACpB,CAAA,MAAA,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,OAAO,0CAAE,MAAM,MAAK,yEAA+C,EACtF,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;QAC7C,CAAC;QAED,cAAc,GAAG,cAAc,IAAI,EAAE,CAAA;QAErC,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAA;QACrE,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,WAAW,CAAA;QAE/B,IAAI,OAAiB,CAAA;QAErB,cAAc,CAAC,IAAI,GAAG,cAAc,CAAC,IAAI;YACvC,CAAC,CAAC,cAAc,CAAC,IAAI;YACrB,CAAC,CAAC,cAAc,IAAA,yBAAgB,EAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,CAAA;QAEhD,cAAc,CAAC,kBAAkB,GAAG;YAClC,GAAG,IAAI,CAAC,mBAAmB;YAC3B,GAAG,cAAc,CAAC,kBAAkB;SACrC,CAAA;QAED,IAAI,IAAI,CAAC,YAAY,KAAK,qCAAW,CAAC,UAAU,EAAE,CAAC;YACjD,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAAC,cAAc,CAAC,CAAA;QACzE,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,cAAc,CAAC,CAAA;QAC/D,CAAC;QAED,IAAI,CAAC,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,CAAA,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAA;QAC5C,CAAC;QAED,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,OAAiB,CAAA;QAE/C,IAAI,CAAC,iBAAgD,CAAC,YAAY,CACjE,IAAI,CAAC,eAAe,EACpB,IAAI,CAAC,YAAY,CAClB,CAAA;QAED,IAAI,CAAC,aAAa,GAAG,SAAS,CAAA;IAChC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAe;QAC/B,4CAAkB,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAA;IAClD,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,IAAI,CACf,WAAsB;QAEtB,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAA;YACH,CAAC;YAED,IACE,IAAI,CAAC,aAAa,KAAK,SAAS;mBAC7B,OAAO,IAAI,CAAC,eAAe,KAAK,QAAQ,EAC3C,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;YACvD,CAAC;YAED,IAAI,IAAI,CAAC,YAAY,KAAK,qCAAW,CAAC,UAAU,EAAE,CAAC;gBACjD,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAA;YACzC,CAAC;YAED,MAAM,IAAI,CAAC,WAAW,CAAC,qBAAqB,CAC1C,IAAI,CAAC,eAAe,EACpB;gBACE,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;gBACtB,IAAI,EAAE,CAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,IAAI;oBACrB,CAAC,CAAC,WAAW,CAAC,IAAI;oBAClB,CAAC,CAAC,cAAc,IAAA,yBAAgB,EAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE;aACjD,CACF,CAAA;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,CAAA;QACT,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,IAAI,CACf,WAAsB;QAEtB,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAA;YACH,CAAC;YAED,IACE,IAAI,CAAC,aAAa,KAAK,SAAS;mBAC7B,OAAO,IAAI,CAAC,eAAe,KAAK,QAAQ,EAC3C,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;YACvD,CAAC;YAED,IAAI,IAAI,CAAC,YAAY,KAAK,qCAAW,CAAC,KAAK,EAAE,CAAC;gBAC5C,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAA;YACzC,CAAC;YAED,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAChC,IAAI,CAAC,eAAe,EACpB,WAAW,IAAI,EAAE,CAClB,CAAA;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,CAAA;QACT,CAAC;gBAAS,CAAC;YACR,IAAI,CAAC,iBAAgD,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;YAEvE,IAAI,CAAC,eAAe,GAAG,KAAK,CAAA;YAC5B,IAAI,CAAC,aAAa,GAAG,SAAS,CAAA;QAChC,CAAC;IACH,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,MAAM;QACjB,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAA;YACH,CAAC;YAED,IACE,IAAI,CAAC,aAAa,KAAK,SAAS;mBAC7B,OAAO,IAAI,CAAC,eAAe,KAAK,QAAQ,EAC3C,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;YACvD,CAAC;YAED,IAAI,IAAI,CAAC,YAAY,KAAK,qCAAW,CAAC,UAAU,EAAE,CAAC;gBACjD,MAAM,IAAI,CAAC,WAAW,CAAC,qBAAqB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;YACpE,CAAC;iBAAM,IAAI,IAAI,CAAC,YAAY,KAAK,qCAAW,CAAC,KAAK,EAAE,CAAC;gBACnD,MAAM,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;YAC5D,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,CAAA;QACT,CAAC;gBAAS,CAAC;YACR,IAAI,CAAC,iBAAgD,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;YAEvE,IAAI,CAAC,eAAe,GAAG,KAAK,CAAA;YAC5B,IAAI,CAAC,aAAa,GAAG,SAAS,CAAA;QAChC,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,4BAA4B,CACvC,cAAkD;QAElD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAA;QACH,CAAC;QAED,cAAc,GAAG,cAAc,IAAI,EAAE,CAAA;QAErC,cAAc,CAAC,kBAAkB,GAAG;YAClC,GAAG,CAAC,cAAc,CAAC,kBAAkB,IAAI,EAAE,CAAC;YAC5C,GAAG,IAAI,CAAC,mBAAmB;SAC5B,CAAA;QAED,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAA;QAE3E,IAAI,KAAK,IAAI,OAAO,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YACzD,MAAM,IAAI,CAAC,KAAK,CAAC,qCAAW,CAAC,UAAU,EAAE,cAAc,CAAC,CAAA;QAC1D,CAAC;aAAM,IAAI,KAAK,IAAI,MAAM,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YAC/D,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;QACnB,CAAC;IACH,CAAC;CACF;AAhRD,0CAgRC"}
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "example-session-recorder-node",
3
+ "version": "0.0.0",
4
+ "description": "Multiplayer Fullstack Session Recorder Node.js example",
5
+ "author": {
6
+ "name": "Multiplayer Software, Inc.",
7
+ "url": "https://www.multiplayer.app"
8
+ },
9
+ "license": "MIT",
10
+ "engines": {
11
+ "node": ">=18",
12
+ "npm": ">=8"
13
+ },
14
+ "keywords": [
15
+ "multiplayer",
16
+ "debugger",
17
+ "platform",
18
+ "platform debugger",
19
+ "session recorder",
20
+ "otlp",
21
+ "fullstack session recorder"
22
+ ],
23
+ "dependencies": {
24
+ "@multiplayer-app/session-recorder-common": "1.2.1",
25
+ "@opentelemetry/sdk-node": "^0.203.0",
26
+ "@opentelemetry/api": "^1.9.0",
27
+ "@opentelemetry/core": "^2.0.1",
28
+ "@opentelemetry/otlp-exporter-base": "^0.203.0",
29
+ "@opentelemetry/otlp-transformer": "^0.203.0",
30
+ "@opentelemetry/sdk-trace-base": "^2.0.1",
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "24.0.12",
34
+ "typescript": "5.8.3"
35
+ }
36
+ }
@@ -0,0 +1,138 @@
1
+ import { hostname } from 'os'
2
+ import { node, NodeSDK } from '@opentelemetry/sdk-node'
3
+ import {
4
+ BatchSpanProcessor,
5
+ ParentBasedSampler,
6
+ } from '@opentelemetry/sdk-trace-base'
7
+ import {
8
+ getNodeAutoInstrumentations,
9
+ getResourceDetectors,
10
+ } from '@opentelemetry/auto-instrumentations-node'
11
+ import {
12
+ resourceFromAttributes,
13
+ detectResources,
14
+ } from '@opentelemetry/resources'
15
+ import {
16
+ ATTR_SERVICE_NAME,
17
+ ATTR_SERVICE_VERSION,
18
+ SEMRESATTRS_HOST_NAME,
19
+ SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
20
+ SEMRESATTRS_PROCESS_RUNTIME_VERSION,
21
+ SEMRESATTRS_PROCESS_PID,
22
+ } from '@opentelemetry/semantic-conventions'
23
+ import api from '@opentelemetry/api'
24
+ // import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
25
+ import { W3CTraceContextPropagator } from '@opentelemetry/core'
26
+ import {
27
+ SessionRecorderHttpInstrumentationHooksNode,
28
+ SessionRecorderTraceIdRatioBasedSampler,
29
+ SessionRecorderIdGenerator,
30
+ SessionRecorderHttpTraceExporter,
31
+ SessionRecorderHttpLogsExporter,
32
+ } from '@multiplayer-app/session-recorder-node'
33
+ import { LoggerProvider, BatchLogRecordProcessor } from '@opentelemetry/sdk-logs'
34
+ import * as apiLogs from '@opentelemetry/api-logs'
35
+ // import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'
36
+
37
+ const SERVICE_NAME = ''
38
+ const SERVICE_VERSION = ''
39
+ const PLATFORM_ENV = ''
40
+ const MULTIPLAYER_OTLP_KEY = ''
41
+ const OTLP_TRACES_ENDPOINT = ''
42
+ const OTLP_LOGS_ENDPOINT = ''
43
+ const MULTIPLAYER_OTLP_SPAN_RATIO = ''
44
+
45
+ // NOTE: Update instrumentation configuration as needed
46
+ // For more see: https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node
47
+ const instrumentations = [
48
+ getNodeAutoInstrumentations({
49
+ '@opentelemetry/instrumentation-http': {
50
+ requestHook: SessionRecorderHttpInstrumentationHooksNode.requestHook({
51
+ maskHeadersList: ['X-Api-Key'],
52
+ maxPayloadSizeBytes: 5000,
53
+ schemifyDocSpanPayload: false,
54
+ isMaskBodyEnabled: false,
55
+ }),
56
+ responseHook: SessionRecorderHttpInstrumentationHooksNode.responseHook({
57
+ maskHeadersList: ['X-Api-Key'],
58
+ maxPayloadSizeBytes: 5000,
59
+ schemifyDocSpanPayload: false,
60
+ isMaskBodyEnabled: false,
61
+ }),
62
+ },
63
+ }),
64
+ ]
65
+
66
+ const getResource = () => {
67
+ const resourceWithAttributes = resourceFromAttributes({
68
+ [ATTR_SERVICE_NAME]: SERVICE_NAME,
69
+ [ATTR_SERVICE_VERSION]: SERVICE_VERSION,
70
+ [SEMRESATTRS_HOST_NAME]: hostname(),
71
+ [SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: PLATFORM_ENV,
72
+ [SEMRESATTRS_PROCESS_RUNTIME_VERSION]: process.version,
73
+ [SEMRESATTRS_PROCESS_PID]: process.pid,
74
+ })
75
+ const detectedResources = detectResources({ detectors: getResourceDetectors() })
76
+ const resource = resourceWithAttributes.merge(detectedResources)
77
+
78
+ return resource
79
+ }
80
+
81
+ export const idGenerator = new SessionRecorderIdGenerator()
82
+
83
+ const opentelemetry = () => {
84
+ // const traceExporter = new OTLPTraceExporter({
85
+ // url: OTLP_TRACES_ENDPOINT,
86
+ // headers: {
87
+ // Authorization: MULTIPLAYER_OTLP_KEY
88
+ // },
89
+ // })
90
+ const traceExporter = new SessionRecorderHttpTraceExporter({
91
+ apiKey: MULTIPLAYER_OTLP_KEY,
92
+ url: OTLP_TRACES_ENDPOINT,
93
+ })
94
+
95
+ const resource = getResource()
96
+
97
+ const provider = new node.NodeTracerProvider({
98
+ resource,
99
+ spanProcessors: [
100
+ new BatchSpanProcessor(traceExporter),
101
+ ],
102
+ sampler: new ParentBasedSampler({
103
+ root: new SessionRecorderTraceIdRatioBasedSampler(MULTIPLAYER_OTLP_SPAN_RATIO),
104
+ }),
105
+ idGenerator,
106
+ })
107
+
108
+ // const logExporter = new OTLPLogExporter({
109
+ // url: OTLP_LOGS_ENDPOINT,
110
+ // headers: {
111
+ // Authorization: MULTIPLAYER_OTLP_KEY
112
+ // },
113
+ // })
114
+ const logExporter = new SessionRecorderHttpLogsExporter({
115
+ apiKey: MULTIPLAYER_OTLP_KEY,
116
+ url: OTLP_LOGS_ENDPOINT,
117
+ })
118
+ const logRecordProcessor = new BatchLogRecordProcessor(logExporter)
119
+
120
+ const loggerProvider = new LoggerProvider({
121
+ resource,
122
+ processors: [logRecordProcessor],
123
+ })
124
+
125
+ apiLogs.logs.setGlobalLoggerProvider(loggerProvider)
126
+
127
+ provider.register()
128
+ api.trace.setGlobalTracerProvider(provider)
129
+ api.propagation.setGlobalPropagator(new W3CTraceContextPropagator())
130
+
131
+ const sdk = new NodeSDK({
132
+ instrumentations,
133
+ })
134
+
135
+ sdk.start()
136
+ }
137
+
138
+ opentelemetry()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplayer-app/session-recorder-node",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Multiplayer Fullstack Session Recorder for Node.js",
5
5
  "author": {
6
6
  "name": "Multiplayer Software, Inc.",
@@ -29,7 +29,7 @@
29
29
  "prepublishOnly": "npm run build"
30
30
  },
31
31
  "dependencies": {
32
- "@multiplayer-app/session-recorder-common": "1.2.1",
32
+ "@multiplayer-app/session-recorder-common": "1.2.2",
33
33
  "@opentelemetry/api": "^1.9.0",
34
34
  "@opentelemetry/core": "^2.0.1",
35
35
  "@opentelemetry/otlp-exporter-base": "^0.203.0",
@@ -116,6 +116,10 @@ export class SessionRecorder {
116
116
  session = await this._apiService.startSession(sessionPayload)
117
117
  }
118
118
 
119
+ if (!session?.shortId) {
120
+ throw new Error('Failed to start session')
121
+ }
122
+
119
123
  this._shortSessionId = session.shortId as string
120
124
 
121
125
  (this._traceIdGenerator as SessionRecorderIdGenerator).setSessionId(
package/tsconfig.json CHANGED
@@ -26,10 +26,10 @@
26
26
  "strict": true,
27
27
  "composite": true,
28
28
  "outDir": "./dist/",
29
- "rootDir": "./src",
29
+ "rootDir": "./src/",
30
30
  "preserveSymlinks": true,
31
31
  "paths": {}
32
32
  },
33
- "exclude": ["dist"],
33
+ "exclude": ["dist", "examples"],
34
34
  "references": []
35
35
  }