@logspace/sdk 1.0.2 → 1.1.0
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/logspace.esm.js +1130 -702
- package/logspace.esm.js.map +1 -1
- package/logspace.iife.js +1 -1
- package/logspace.iife.js.map +1 -1
- package/logspace.umd.js +1 -1
- package/logspace.umd.js.map +1 -1
- package/package.json +5 -3
- package/sdk/capture/base.d.ts +5 -3
- package/sdk/capture/sse.d.ts +0 -3
- package/sdk/capture/websocket.d.ts +0 -3
- package/sdk/index.d.ts +25 -1
- package/sdk/storage/indexed-db.d.ts +4 -0
- package/sdk/types.d.ts +15 -6
- package/shared/types.d.ts +108 -1
- package/shared/utils.d.ts +8 -1
- package/README.md +0 -269
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logspace/sdk",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "LogSpace JavaScript SDK for session recording and logging",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./logspace.umd.js",
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
|
-
"README.md",
|
|
23
22
|
"logspace.esm.js",
|
|
24
23
|
"logspace.esm.js.map",
|
|
25
24
|
"logspace.umd.js",
|
|
@@ -38,5 +37,8 @@
|
|
|
38
37
|
"monitoring"
|
|
39
38
|
],
|
|
40
39
|
"author": "LogSpace",
|
|
41
|
-
"license": "MIT"
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"scripts": {
|
|
42
|
+
"preinstall": "npx only-allow bun && bun --version | grep -q '^1.2.21$' || (echo 'Error: Bun version 1.2.21 is required' && exit 1)"
|
|
43
|
+
}
|
|
42
44
|
}
|
package/sdk/capture/base.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LogEntry, LogType } from '../../shared/types';
|
|
2
2
|
import { CaptureHandler, PrivacyConfig } from '../types';
|
|
3
|
-
import { generateId, safeStringify, maskSensitiveData, maskHeaders } from '../../shared/utils';
|
|
4
|
-
export { generateId, safeStringify, maskSensitiveData, maskHeaders };
|
|
3
|
+
import { generateId, safeStringify, maskSensitiveData, maskHeaders, maskConsoleArgs } from '../../shared/utils';
|
|
4
|
+
export { generateId, safeStringify, maskSensitiveData, maskHeaders, maskConsoleArgs };
|
|
5
5
|
/**
|
|
6
6
|
* Check if running in browser environment (SSR safety)
|
|
7
7
|
*/
|
|
@@ -39,7 +39,9 @@ export declare function applyPrivacy(log: LogEntry, privacy: PrivacyConfig): Log
|
|
|
39
39
|
*/
|
|
40
40
|
export interface CaptureModule {
|
|
41
41
|
name: string;
|
|
42
|
-
install(handler: CaptureHandler, privacy: PrivacyConfig)
|
|
42
|
+
install(handler: CaptureHandler, privacy: PrivacyConfig, onActivity?: () => void, limits?: {
|
|
43
|
+
maxNetworkBodySize?: number;
|
|
44
|
+
}): void;
|
|
43
45
|
uninstall(): void;
|
|
44
46
|
reset?(): void;
|
|
45
47
|
}
|
package/sdk/capture/sse.d.ts
CHANGED
package/sdk/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { LogEntry } from '../shared/types';
|
|
2
|
-
import { LogSpaceConfig, SDKSession, SessionPayload } from './types';
|
|
2
|
+
import { LogSpaceConfig, NormalizedConfig, SDKSession, SessionPayload } from './types';
|
|
3
3
|
import { eventWithTime } from './capture/rrweb';
|
|
4
4
|
export declare const LogSpace: {
|
|
5
5
|
/**
|
|
6
6
|
* Initialize the SDK
|
|
7
|
+
* @throws Error if SDK is already initialized
|
|
7
8
|
*/
|
|
8
9
|
init(userConfig: LogSpaceConfig): void;
|
|
9
10
|
/**
|
|
@@ -16,6 +17,7 @@ export declare const LogSpace: {
|
|
|
16
17
|
stopSession(): Promise<void>;
|
|
17
18
|
/**
|
|
18
19
|
* Identify user
|
|
20
|
+
* If called before session starts, the identity will be queued and applied when session starts
|
|
19
21
|
*/
|
|
20
22
|
identify(userId: string, traits?: Record<string, any>): void;
|
|
21
23
|
/**
|
|
@@ -55,6 +57,28 @@ export declare const LogSpace: {
|
|
|
55
57
|
* Get rrweb events for current session
|
|
56
58
|
*/
|
|
57
59
|
getRRWebEvents(): eventWithTime[];
|
|
60
|
+
/**
|
|
61
|
+
* Get current configuration (read-only)
|
|
62
|
+
* Returns the full NormalizedConfig plus convenience top-level fields
|
|
63
|
+
* that match the setConfig() interface for easy verification
|
|
64
|
+
*/
|
|
65
|
+
getConfig(): (NormalizedConfig & {
|
|
66
|
+
rateLimit: number;
|
|
67
|
+
maxLogs: number;
|
|
68
|
+
maxSize: number;
|
|
69
|
+
idleTimeout: number;
|
|
70
|
+
}) | null;
|
|
71
|
+
/**
|
|
72
|
+
* Update configuration at runtime
|
|
73
|
+
* Only certain settings can be changed after initialization
|
|
74
|
+
*/
|
|
75
|
+
setConfig(updates: {
|
|
76
|
+
rateLimit?: number;
|
|
77
|
+
maxLogs?: number;
|
|
78
|
+
maxSize?: number;
|
|
79
|
+
idleTimeout?: number;
|
|
80
|
+
debug?: boolean;
|
|
81
|
+
}): void;
|
|
58
82
|
/**
|
|
59
83
|
* Destroy SDK
|
|
60
84
|
*/
|
|
@@ -45,6 +45,10 @@ export declare function getCurrentSessionBackup(): Promise<CurrentSessionBackup
|
|
|
45
45
|
* Clear current session backup (called after successful send)
|
|
46
46
|
*/
|
|
47
47
|
export declare function clearCurrentSessionBackup(): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Clear current session backup only if it matches the provided session ID
|
|
50
|
+
*/
|
|
51
|
+
export declare function clearCurrentSessionBackupFor(sessionId: string): Promise<void>;
|
|
48
52
|
/**
|
|
49
53
|
* Add a session to pending queue (for retry later)
|
|
50
54
|
*/
|
package/sdk/types.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export type RecordingType = 'video' | 'rrweb';
|
|
|
12
12
|
*/
|
|
13
13
|
export interface SDKSession {
|
|
14
14
|
id: string;
|
|
15
|
+
tabId: string;
|
|
15
16
|
startTime: number;
|
|
16
17
|
endTime?: number;
|
|
17
18
|
status: 'idle' | 'recording' | 'paused' | 'stopped';
|
|
@@ -96,7 +97,7 @@ export interface RRWebConfig {
|
|
|
96
97
|
*/
|
|
97
98
|
recordCanvas?: boolean;
|
|
98
99
|
/** Take a full DOM snapshot every N events
|
|
99
|
-
* @default
|
|
100
|
+
* @default 150
|
|
100
101
|
*/
|
|
101
102
|
checkoutEveryNth?: number;
|
|
102
103
|
}
|
|
@@ -146,7 +147,7 @@ export interface SessionLimits {
|
|
|
146
147
|
*/
|
|
147
148
|
maxDuration?: number;
|
|
148
149
|
/** Idle timeout in seconds - auto-end if no activity
|
|
149
|
-
* @default
|
|
150
|
+
* @default 120
|
|
150
151
|
*/
|
|
151
152
|
idleTimeout?: number;
|
|
152
153
|
/** Navigate away timeout in seconds - grace period when tab becomes hidden
|
|
@@ -162,6 +163,10 @@ export interface SessionLimits {
|
|
|
162
163
|
* @default true
|
|
163
164
|
*/
|
|
164
165
|
deduplicate?: boolean;
|
|
166
|
+
/** Maximum size for network request/response bodies in bytes
|
|
167
|
+
* @default 10240 (10KB)
|
|
168
|
+
*/
|
|
169
|
+
maxNetworkBodySize?: number;
|
|
165
170
|
}
|
|
166
171
|
/**
|
|
167
172
|
* Session end triggers
|
|
@@ -193,11 +198,11 @@ export interface SamplingConfig {
|
|
|
193
198
|
*/
|
|
194
199
|
enabled?: boolean;
|
|
195
200
|
/** Seconds of logs to keep before the trigger event
|
|
196
|
-
* @default
|
|
201
|
+
* @default 30
|
|
197
202
|
*/
|
|
198
203
|
bufferBefore?: number;
|
|
199
204
|
/** Seconds to continue recording after the trigger event
|
|
200
|
-
* @default
|
|
205
|
+
* @default 30
|
|
201
206
|
*/
|
|
202
207
|
recordAfter?: number;
|
|
203
208
|
/** What triggers a session to be saved */
|
|
@@ -244,6 +249,10 @@ export interface HooksConfig {
|
|
|
244
249
|
* @default undefined
|
|
245
250
|
*/
|
|
246
251
|
onSamplingTrigger?: (trigger: 'error' | 'consoleError' | 'networkError' | 'manual', log?: LogEntry) => void;
|
|
252
|
+
/** Called when a sampling session is discarded (no trigger occurred)
|
|
253
|
+
* @default undefined
|
|
254
|
+
*/
|
|
255
|
+
onSessionDiscarded?: (session: SDKSession, reason: 'noTrigger' | 'idle' | 'maxDuration' | 'manual') => void;
|
|
247
256
|
/** Called on transport/network errors
|
|
248
257
|
* @default undefined
|
|
249
258
|
*/
|
|
@@ -266,7 +275,7 @@ export interface LogSpaceConfig {
|
|
|
266
275
|
*/
|
|
267
276
|
capture?: CaptureConfig;
|
|
268
277
|
/** rrweb DOM recording settings
|
|
269
|
-
* @default { maskAllInputs: false, recordCanvas: false, checkoutEveryNth:
|
|
278
|
+
* @default { maskAllInputs: false, recordCanvas: false, checkoutEveryNth: 150 }
|
|
270
279
|
*/
|
|
271
280
|
rrweb?: RRWebConfig;
|
|
272
281
|
/** Privacy settings for masking sensitive data
|
|
@@ -274,7 +283,7 @@ export interface LogSpaceConfig {
|
|
|
274
283
|
*/
|
|
275
284
|
privacy?: PrivacyConfig;
|
|
276
285
|
/** Session limits for protection against memory issues
|
|
277
|
-
* @default { maxLogs: 10000, maxSize: 10485760, maxDuration:
|
|
286
|
+
* @default { maxLogs: 10000, maxSize: 10485760, maxDuration: 1800, idleTimeout: 120, rateLimit: 100, deduplicate: true }
|
|
278
287
|
*/
|
|
279
288
|
limits?: SessionLimits;
|
|
280
289
|
/** Configure when to auto-end sessions
|
package/shared/types.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export interface RecordingSession {
|
|
|
11
11
|
cspBlocked?: boolean;
|
|
12
12
|
title?: string;
|
|
13
13
|
comment?: string;
|
|
14
|
+
videoStartTime?: number;
|
|
14
15
|
}
|
|
15
16
|
export interface TabRecording {
|
|
16
17
|
tabId: number;
|
|
@@ -233,8 +234,17 @@ export interface RecordingSettings {
|
|
|
233
234
|
excludeDomains: string[];
|
|
234
235
|
maskSensitiveData: boolean;
|
|
235
236
|
logLevels: LogSeverity[];
|
|
237
|
+
maxNetworkBodySize: number;
|
|
236
238
|
}
|
|
237
239
|
export declare const DEFAULT_SETTINGS: RecordingSettings;
|
|
240
|
+
export declare const API_TO_SETTINGS_KEY_MAP: Record<string, keyof RecordingSettings>;
|
|
241
|
+
export interface RemoteSettingsState {
|
|
242
|
+
disabledKeys: Set<keyof RecordingSettings>;
|
|
243
|
+
lastFetched: number | null;
|
|
244
|
+
loading: boolean;
|
|
245
|
+
error: string | null;
|
|
246
|
+
}
|
|
247
|
+
export declare function parseApiSettingValue(apiKey: string, value: string, valueType: string): any;
|
|
238
248
|
export interface SessionStats {
|
|
239
249
|
logCount: number;
|
|
240
250
|
networkLogCount: number;
|
|
@@ -300,6 +310,101 @@ export declare enum MessageType {
|
|
|
300
310
|
CSP_DETECTED = "CSP_DETECTED",// CSP blocked script injection
|
|
301
311
|
FETCH_ASSIGNED_LOGS = "FETCH_ASSIGNED_LOGS"
|
|
302
312
|
}
|
|
313
|
+
/**
|
|
314
|
+
* Internal message types used for communication between extension components
|
|
315
|
+
* These are not part of the public MessageType enum to avoid bloating it
|
|
316
|
+
*
|
|
317
|
+
* MESSAGE FLOW DOCUMENTATION:
|
|
318
|
+
*
|
|
319
|
+
* Background Script <-> Content Script:
|
|
320
|
+
* - REGISTER_TAB: Background registers a tab for recording
|
|
321
|
+
* - UNREGISTER_TAB: Background unregisters a tab
|
|
322
|
+
* - SHOW_COUNTDOWN: Background asks content to show countdown overlay
|
|
323
|
+
* - SELECT_AREA: Background asks content to show area selector
|
|
324
|
+
* - AREA_SELECTED: Content informs background of selected area
|
|
325
|
+
* - NETWORK_HEADERS_*: Background forwards network headers to content
|
|
326
|
+
* - show-webcam-overlay / hide-webcam-overlay: Webcam control
|
|
327
|
+
* - SAVE_ANNOTATION / SAVE_DRAWING_ANNOTATION: User annotations
|
|
328
|
+
* - STORAGE_SIZE_UPDATE: Background informs content of storage usage
|
|
329
|
+
* - SHOW_SAVE_MODAL / UPDATE_SAVE_MODAL_VIDEO: Save dialog control
|
|
330
|
+
*
|
|
331
|
+
* Background Script <-> Offscreen Document:
|
|
332
|
+
* - start-video-recording / stop-video-recording: Video recording control
|
|
333
|
+
* - start-display-media-recording: Screen capture control
|
|
334
|
+
* - test-microphone-permission / test-webcam-permission: Permission tests
|
|
335
|
+
* - start-microphone-visualization / stop-microphone-visualization: Audio levels
|
|
336
|
+
* - save-video: Offscreen sends video data to background
|
|
337
|
+
* - video-chunk-size: Offscreen reports chunk sizes
|
|
338
|
+
* - offscreen-log: Offscreen forwards logs to background
|
|
339
|
+
* - display-media-selected: User selected screen/window
|
|
340
|
+
* - microphone-audio-level: Audio visualization data
|
|
341
|
+
*
|
|
342
|
+
* Background Script <-> Popup:
|
|
343
|
+
* - CLOSE_POPUP: Background requests popup to close
|
|
344
|
+
* - RECORDING_STARTED / RECORDING_ERROR: Recording state notifications
|
|
345
|
+
* - All MessageType and AuthMessageType enums
|
|
346
|
+
*/
|
|
347
|
+
export declare enum InternalMessageType {
|
|
348
|
+
PING = "ping",
|
|
349
|
+
GET_TAB_ID = "GET_TAB_ID",
|
|
350
|
+
CANCEL_AREA_SELECTION = "CANCEL_AREA_SELECTION",
|
|
351
|
+
SHOW_COUNTDOWN = "SHOW_COUNTDOWN",
|
|
352
|
+
COUNTDOWN_COMPLETE = "COUNTDOWN_COMPLETE",
|
|
353
|
+
SELECT_AREA = "SELECT_AREA",
|
|
354
|
+
AREA_SELECTED = "AREA_SELECTED",
|
|
355
|
+
AREA_SELECTION_CANCELLED = "AREA_SELECTION_CANCELLED",
|
|
356
|
+
NETWORK_HEADERS_REQUEST = "NETWORK_HEADERS_REQUEST",
|
|
357
|
+
NETWORK_HEADERS_RESPONSE = "NETWORK_HEADERS_RESPONSE",
|
|
358
|
+
SHOW_WEBCAM_OVERLAY = "show-webcam-overlay",
|
|
359
|
+
HIDE_WEBCAM_OVERLAY = "hide-webcam-overlay",
|
|
360
|
+
SAVE_ANNOTATION = "SAVE_ANNOTATION",
|
|
361
|
+
SAVE_DRAWING_ANNOTATION = "SAVE_DRAWING_ANNOTATION",
|
|
362
|
+
STORAGE_SIZE_UPDATE = "STORAGE_SIZE_UPDATE",
|
|
363
|
+
SHOW_SAVE_MODAL = "SHOW_SAVE_MODAL",
|
|
364
|
+
UPDATE_SAVE_MODAL_VIDEO = "UPDATE_SAVE_MODAL_VIDEO",
|
|
365
|
+
START_VIDEO_RECORDING = "start-video-recording",
|
|
366
|
+
STOP_VIDEO_RECORDING = "stop-video-recording",
|
|
367
|
+
START_DISPLAY_MEDIA_RECORDING = "start-display-media-recording",
|
|
368
|
+
TEST_MICROPHONE_PERMISSION = "test-microphone-permission",
|
|
369
|
+
TEST_WEBCAM_PERMISSION = "test-webcam-permission",
|
|
370
|
+
START_MICROPHONE_VISUALIZATION = "start-microphone-visualization",
|
|
371
|
+
STOP_MICROPHONE_VISUALIZATION = "stop-microphone-visualization",
|
|
372
|
+
SAVE_VIDEO = "save-video",
|
|
373
|
+
VIDEO_CHUNK_SIZE = "video-chunk-size",
|
|
374
|
+
OFFSCREEN_LOG = "offscreen-log",
|
|
375
|
+
DISPLAY_MEDIA_SELECTED = "display-media-selected",
|
|
376
|
+
MICROPHONE_AUDIO_LEVEL = "microphone-audio-level",
|
|
377
|
+
BEGIN_MEDIA_RECORDING = "begin-media-recording",
|
|
378
|
+
VIDEO_RECORDING_STARTED = "video-recording-started",
|
|
379
|
+
SCREEN_SHARE_ENDED = "screen-share-ended",// User clicked browser's "Stop sharing" button
|
|
380
|
+
CLOSE_POPUP = "CLOSE_POPUP",
|
|
381
|
+
RECORDING_STARTED = "RECORDING_STARTED",
|
|
382
|
+
RECORDING_ERROR = "RECORDING_ERROR",
|
|
383
|
+
LOGIN_SUCCESS = "LOGIN_SUCCESS",
|
|
384
|
+
LOGIN_FAILED = "LOGIN_FAILED",
|
|
385
|
+
STATE_UPDATE = "STATE_UPDATE",
|
|
386
|
+
LOG_UPDATE = "LOG_UPDATE",
|
|
387
|
+
SAVE_RECORDING_METADATA = "SAVE_RECORDING_METADATA",
|
|
388
|
+
GET_SESSION_LOGS = "GET_SESSION_LOGS",
|
|
389
|
+
GET_UPLOAD_FORM_DATA = "GET_UPLOAD_FORM_DATA",
|
|
390
|
+
SEARCH_PROJECTS = "SEARCH_PROJECTS",
|
|
391
|
+
SEARCH_ENVIRONMENTS = "SEARCH_ENVIRONMENTS",
|
|
392
|
+
SEARCH_USERS = "SEARCH_USERS",
|
|
393
|
+
UPLOAD_RECORDING = "UPLOAD_RECORDING",
|
|
394
|
+
CONNECT = "CONNECT"
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Validate that a message has a valid type
|
|
398
|
+
* @param message The message to validate
|
|
399
|
+
* @returns true if the message has a valid type property
|
|
400
|
+
*/
|
|
401
|
+
export declare function isValidMessage(message: unknown): boolean;
|
|
402
|
+
/**
|
|
403
|
+
* Check if a message type is a known type
|
|
404
|
+
* @param type The message type to check
|
|
405
|
+
* @returns true if the type is in MessageType, AuthMessageType, or InternalMessageType
|
|
406
|
+
*/
|
|
407
|
+
export declare function isKnownMessageType(type: string): boolean;
|
|
303
408
|
export interface Message {
|
|
304
409
|
type: MessageType;
|
|
305
410
|
payload?: any;
|
|
@@ -323,6 +428,7 @@ export interface StatusResponse {
|
|
|
323
428
|
session: RecordingSession | null;
|
|
324
429
|
error?: string;
|
|
325
430
|
auth?: AuthState;
|
|
431
|
+
recordedTabIds?: number[];
|
|
326
432
|
}
|
|
327
433
|
export interface CspDetectedMessage extends Message {
|
|
328
434
|
type: MessageType.CSP_DETECTED;
|
|
@@ -352,5 +458,6 @@ export interface AuthPollingState {
|
|
|
352
458
|
export declare enum AuthMessageType {
|
|
353
459
|
LOGIN_START = "LOGIN_START",
|
|
354
460
|
LOGOUT = "LOGOUT",
|
|
355
|
-
VALIDATE_AUTH = "VALIDATE_AUTH"
|
|
461
|
+
VALIDATE_AUTH = "VALIDATE_AUTH",
|
|
462
|
+
SYNC_SETTINGS = "SYNC_SETTINGS"
|
|
356
463
|
}
|
package/shared/utils.d.ts
CHANGED
|
@@ -27,10 +27,17 @@ export declare function safeStringify(value: any): string;
|
|
|
27
27
|
* Mask sensitive data in strings for privacy protection
|
|
28
28
|
*/
|
|
29
29
|
export declare function maskSensitiveData(text: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Mask console arguments, handling the case where label and value are separate args
|
|
32
|
+
* e.g., console.log("Password:", "secret") produces ["Password:", "secret"]
|
|
33
|
+
*/
|
|
34
|
+
export declare function maskConsoleArgs(args: string[]): string[];
|
|
30
35
|
/**
|
|
31
36
|
* Mask sensitive data in HTTP headers for privacy protection
|
|
37
|
+
* @param headers - The headers object to mask
|
|
38
|
+
* @param additionalHeaders - Additional header names to redact (from config.privacy.redactHeaders)
|
|
32
39
|
*/
|
|
33
|
-
export declare function maskHeaders(headers: Record<string, string
|
|
40
|
+
export declare function maskHeaders(headers: Record<string, string>, additionalHeaders?: string[]): Record<string, string>;
|
|
34
41
|
/**
|
|
35
42
|
* Check if a URL matches any of the excluded domain patterns
|
|
36
43
|
* Supports regex patterns for flexible matching
|
package/README.md
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
# @logspace/sdk
|
|
2
|
-
|
|
3
|
-
A lightweight JavaScript SDK for session recording and debugging. Capture user sessions with DOM replay, console logs, network requests, errors, and more.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @logspace/sdk
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
yarn add @logspace/sdk
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
pnpm add @logspace/sdk
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Quick Start
|
|
20
|
-
|
|
21
|
-
```javascript
|
|
22
|
-
import LogSpace from '@logspace/sdk';
|
|
23
|
-
|
|
24
|
-
// Initialize the SDK
|
|
25
|
-
LogSpace.init({
|
|
26
|
-
serverUrl: 'https://your-logspace-server.com',
|
|
27
|
-
apiKey: 'project_id:environment_id',
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
// Start recording
|
|
31
|
-
LogSpace.startSession();
|
|
32
|
-
|
|
33
|
-
// Identify the user (optional)
|
|
34
|
-
LogSpace.identify('user-123', {
|
|
35
|
-
email: 'user@example.com',
|
|
36
|
-
plan: 'pro',
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
// Track custom events
|
|
40
|
-
LogSpace.track('button_clicked', { buttonId: 'submit' });
|
|
41
|
-
|
|
42
|
-
// Add breadcrumbs for debugging
|
|
43
|
-
LogSpace.breadcrumb('User opened settings', 'navigation');
|
|
44
|
-
|
|
45
|
-
// Stop recording and send to server
|
|
46
|
-
await LogSpace.stopSession();
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Features
|
|
50
|
-
|
|
51
|
-
- 🎬 **DOM Recording** - Full visual replay using rrweb
|
|
52
|
-
- 📝 **Console Logs** - Capture all console output (log, warn, error, debug)
|
|
53
|
-
- 🌐 **Network Requests** - Track XHR and Fetch calls with timing
|
|
54
|
-
- ❌ **Error Tracking** - Catch JavaScript errors and unhandled rejections
|
|
55
|
-
- 🖱️ **User Interactions** - Record clicks, inputs, and scrolls
|
|
56
|
-
- 📊 **Performance Metrics** - Core Web Vitals and resource timing
|
|
57
|
-
- 🔌 **WebSocket & SSE** - Monitor real-time connections
|
|
58
|
-
- 💾 **Storage Changes** - Track localStorage/sessionStorage modifications
|
|
59
|
-
- 🔒 **Privacy First** - Built-in PII masking and data sanitization
|
|
60
|
-
|
|
61
|
-
## Configuration
|
|
62
|
-
|
|
63
|
-
```javascript
|
|
64
|
-
LogSpace.init({
|
|
65
|
-
// Server configuration
|
|
66
|
-
serverUrl: 'https://your-server.com',
|
|
67
|
-
apiKey: 'project_id:environment_id',
|
|
68
|
-
|
|
69
|
-
// What to capture
|
|
70
|
-
capture: {
|
|
71
|
-
rrweb: true, // DOM recording
|
|
72
|
-
console: true, // Console logs
|
|
73
|
-
network: true, // Network requests
|
|
74
|
-
errors: true, // JavaScript errors
|
|
75
|
-
interactions: true, // User interactions
|
|
76
|
-
performance: true, // Performance metrics
|
|
77
|
-
websocket: true, // WebSocket connections
|
|
78
|
-
sse: true, // Server-Sent Events
|
|
79
|
-
storage: true, // localStorage/sessionStorage
|
|
80
|
-
resources: true, // Resource loading
|
|
81
|
-
spaNavigation: true, // SPA route changes
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
// rrweb settings
|
|
85
|
-
rrweb: {
|
|
86
|
-
maskAllInputs: false, // Mask all input values
|
|
87
|
-
maskTextSelector: null, // CSS selector for text masking
|
|
88
|
-
blockSelector: null, // CSS selector to block elements
|
|
89
|
-
recordCanvas: false, // Record canvas content
|
|
90
|
-
checkoutEveryNth: 200, // Full snapshot interval
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
// Privacy settings
|
|
94
|
-
privacy: {
|
|
95
|
-
maskSensitiveData: true, // Auto-mask PII patterns
|
|
96
|
-
maskSelectors: [], // CSS selectors to mask
|
|
97
|
-
excludeUrls: [], // URL patterns to exclude
|
|
98
|
-
blockNetworkBodies: [], // Block request/response bodies
|
|
99
|
-
redactHeaders: [], // Headers to redact
|
|
100
|
-
logLevels: ['log', 'info', 'warn', 'error', 'debug'],
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
// Session limits
|
|
104
|
-
limits: {
|
|
105
|
-
maxLogs: 10000, // Max logs per session
|
|
106
|
-
maxSize: 10 * 1024 * 1024, // Max session size (10MB)
|
|
107
|
-
maxDuration: 300, // Max duration in seconds (5 min)
|
|
108
|
-
idleTimeout: 30, // Idle timeout in seconds
|
|
109
|
-
rateLimit: 100, // Max logs per second
|
|
110
|
-
deduplicate: true, // Deduplicate consecutive logs
|
|
111
|
-
},
|
|
112
|
-
|
|
113
|
-
// Auto-end behavior
|
|
114
|
-
autoEnd: {
|
|
115
|
-
continueOnRefresh: true, // Continue session on page refresh
|
|
116
|
-
onIdle: true, // End on idle timeout
|
|
117
|
-
onLimitReached: true, // End when limits reached
|
|
118
|
-
},
|
|
119
|
-
|
|
120
|
-
// Sampling mode (only record on errors)
|
|
121
|
-
sampling: {
|
|
122
|
-
enabled: false,
|
|
123
|
-
bufferBefore: 15, // Seconds before trigger
|
|
124
|
-
recordAfter: 15, // Seconds after trigger
|
|
125
|
-
triggers: {
|
|
126
|
-
onError: true,
|
|
127
|
-
onConsoleError: true,
|
|
128
|
-
onNetworkStatus: [500, 502, 503, 504],
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
// Lifecycle hooks
|
|
133
|
-
hooks: {
|
|
134
|
-
onAction: (log, session) => {},
|
|
135
|
-
beforeSend: (logs) => logs,
|
|
136
|
-
onSessionStart: (session) => {},
|
|
137
|
-
onSessionEnd: (session, logs) => {},
|
|
138
|
-
onLimitReached: (reason) => {},
|
|
139
|
-
onSamplingTrigger: (trigger, log) => {},
|
|
140
|
-
onError: (error) => {},
|
|
141
|
-
},
|
|
142
|
-
|
|
143
|
-
// Additional options
|
|
144
|
-
headers: {}, // Custom API headers
|
|
145
|
-
debug: false, // Enable debug logging
|
|
146
|
-
});
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## API Reference
|
|
150
|
-
|
|
151
|
-
### Initialization
|
|
152
|
-
|
|
153
|
-
#### `LogSpace.init(config)`
|
|
154
|
-
|
|
155
|
-
Initialize the SDK with configuration options.
|
|
156
|
-
|
|
157
|
-
### Session Control
|
|
158
|
-
|
|
159
|
-
#### `LogSpace.startSession(metadata?)`
|
|
160
|
-
|
|
161
|
-
Start a new recording session with optional metadata.
|
|
162
|
-
|
|
163
|
-
```javascript
|
|
164
|
-
LogSpace.startSession({ page: 'checkout', variant: 'A' });
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
#### `LogSpace.stopSession()`
|
|
168
|
-
|
|
169
|
-
Stop recording and send the session to the server.
|
|
170
|
-
|
|
171
|
-
```javascript
|
|
172
|
-
await LogSpace.stopSession();
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
#### `LogSpace.pauseRecording()`
|
|
176
|
-
|
|
177
|
-
Temporarily pause recording.
|
|
178
|
-
|
|
179
|
-
#### `LogSpace.resumeRecording()`
|
|
180
|
-
|
|
181
|
-
Resume a paused recording.
|
|
182
|
-
|
|
183
|
-
### User Identification
|
|
184
|
-
|
|
185
|
-
#### `LogSpace.identify(userId, traits?)`
|
|
186
|
-
|
|
187
|
-
Associate the session with a user.
|
|
188
|
-
|
|
189
|
-
```javascript
|
|
190
|
-
LogSpace.identify('user-123', {
|
|
191
|
-
email: 'user@example.com',
|
|
192
|
-
name: 'John Doe',
|
|
193
|
-
plan: 'enterprise',
|
|
194
|
-
});
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
### Custom Events
|
|
198
|
-
|
|
199
|
-
#### `LogSpace.track(event, properties?)`
|
|
200
|
-
|
|
201
|
-
Track a custom event.
|
|
202
|
-
|
|
203
|
-
```javascript
|
|
204
|
-
LogSpace.track('purchase_completed', {
|
|
205
|
-
orderId: 'ORD-123',
|
|
206
|
-
amount: 99.99,
|
|
207
|
-
});
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
#### `LogSpace.breadcrumb(message, category?)`
|
|
211
|
-
|
|
212
|
-
Add a breadcrumb for debugging context.
|
|
213
|
-
|
|
214
|
-
```javascript
|
|
215
|
-
LogSpace.breadcrumb('User clicked add to cart', 'action');
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
### Sampling Mode
|
|
219
|
-
|
|
220
|
-
#### `LogSpace.trigger(reason?)`
|
|
221
|
-
|
|
222
|
-
Manually trigger session capture in sampling mode.
|
|
223
|
-
|
|
224
|
-
```javascript
|
|
225
|
-
LogSpace.trigger('user_reported_issue');
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
### Session Data
|
|
229
|
-
|
|
230
|
-
#### `LogSpace.getSession()`
|
|
231
|
-
|
|
232
|
-
Get the current session object.
|
|
233
|
-
|
|
234
|
-
#### `LogSpace.getSessionLogs()`
|
|
235
|
-
|
|
236
|
-
Get all logs for the current session.
|
|
237
|
-
|
|
238
|
-
#### `LogSpace.getSessionData()`
|
|
239
|
-
|
|
240
|
-
Get full session payload for local export.
|
|
241
|
-
|
|
242
|
-
#### `LogSpace.getRRWebEvents()`
|
|
243
|
-
|
|
244
|
-
Get rrweb events for the current session.
|
|
245
|
-
|
|
246
|
-
### Cleanup
|
|
247
|
-
|
|
248
|
-
#### `LogSpace.destroy()`
|
|
249
|
-
|
|
250
|
-
Destroy the SDK and clean up resources.
|
|
251
|
-
|
|
252
|
-
## Usage Formats
|
|
253
|
-
|
|
254
|
-
The SDK supports multiple module formats:
|
|
255
|
-
|
|
256
|
-
- **ESM**: `import LogSpace from '@logspace/sdk'`
|
|
257
|
-
- **CommonJS**: `const LogSpace = require('@logspace/sdk')`
|
|
258
|
-
- **IIFE**: `<script src="logspace.iife.js"></script>` (exposes `window.LogSpace`)
|
|
259
|
-
|
|
260
|
-
## Browser Support
|
|
261
|
-
|
|
262
|
-
- Chrome 60+
|
|
263
|
-
- Firefox 55+
|
|
264
|
-
- Safari 12+
|
|
265
|
-
- Edge 79+
|
|
266
|
-
|
|
267
|
-
## License
|
|
268
|
-
|
|
269
|
-
MIT
|