@lavarage/telemetry 1.1.0 → 1.2.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/README.md +188 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +30 -0
- package/dist/react.d.ts +73 -0
- package/dist/react.js +149 -0
- package/dist/types.d.ts +8 -1
- package/package.json +36 -9
package/README.md
CHANGED
|
@@ -263,6 +263,22 @@ Track a system event (not tied to any wallet address). System events are display
|
|
|
263
263
|
```typescript
|
|
264
264
|
// Track app startup
|
|
265
265
|
telemetry.trackSystemEvent('app_start', 'Application initialized', 'info');
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
#### `trackStateChange(stateName: string, previousValue?: any, newValue?: any, action?: string, metadata?: object)`
|
|
269
|
+
|
|
270
|
+
Track a React state change. Useful for debugging and understanding user interactions.
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
// Track a state change manually
|
|
274
|
+
telemetry.trackStateChange(
|
|
275
|
+
'userPreferences',
|
|
276
|
+
{ theme: 'light' },
|
|
277
|
+
{ theme: 'dark' },
|
|
278
|
+
'TOGGLE_THEME',
|
|
279
|
+
{ source: 'settings-panel' }
|
|
280
|
+
);
|
|
281
|
+
```
|
|
266
282
|
|
|
267
283
|
// Track feature usage
|
|
268
284
|
telemetry.trackSystemEvent('feature_used', 'User enabled dark mode', 'info', {
|
|
@@ -333,6 +349,177 @@ Clean up the telemetry instance, restore original functions, and flush remaining
|
|
|
333
349
|
telemetry.destroy();
|
|
334
350
|
```
|
|
335
351
|
|
|
352
|
+
## React State Tracking
|
|
353
|
+
|
|
354
|
+
The SDK provides React hooks for automatically tracking state changes in your React components.
|
|
355
|
+
|
|
356
|
+
### Installation
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
# Install the SDK
|
|
360
|
+
npm install @lavarage/telemetry
|
|
361
|
+
|
|
362
|
+
# If you want to use React hooks, also install React (peer dependency)
|
|
363
|
+
npm install react
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Quick Start
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import { LavarageTelemetry } from '@lavarage/telemetry';
|
|
370
|
+
// Import React hooks from the separate entry point
|
|
371
|
+
import { useTrackedState } from '@lavarage/telemetry/react';
|
|
372
|
+
|
|
373
|
+
const telemetry = new LavarageTelemetry({
|
|
374
|
+
apiEndpoint: 'https://telemetry.lavarage.com',
|
|
375
|
+
platform: 'lavarage-web',
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
function MyComponent() {
|
|
379
|
+
// Automatically tracks all state changes
|
|
380
|
+
const [count, setCount] = useTrackedState(0, {
|
|
381
|
+
stateName: 'counter',
|
|
382
|
+
telemetry: telemetry,
|
|
383
|
+
action: 'SET_COUNT'
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
return (
|
|
387
|
+
<button onClick={() => setCount(count + 1)}>
|
|
388
|
+
Count: {count}
|
|
389
|
+
</button>
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Available Hooks
|
|
395
|
+
|
|
396
|
+
#### `useTrackedState(initialState, config)`
|
|
397
|
+
|
|
398
|
+
Wraps React's `useState` and automatically tracks state changes.
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
const [state, setState] = useTrackedState(initialValue, {
|
|
402
|
+
stateName: 'userPreferences', // Required: name for this state
|
|
403
|
+
telemetry: telemetryInstance, // Required: telemetry instance
|
|
404
|
+
trackInitial: false, // Optional: track initial state (default: false)
|
|
405
|
+
action: 'UPDATE_PREFERENCES', // Optional: action name
|
|
406
|
+
metadata: { source: 'settings' }, // Optional: additional metadata
|
|
407
|
+
shouldTrack: (prev, next) => { // Optional: filter which changes to track
|
|
408
|
+
return prev !== next; // Only track if values actually changed
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
#### `useTrackedReducer(reducer, initialState, config)`
|
|
414
|
+
|
|
415
|
+
Wraps React's `useReducer` and automatically tracks state changes with action information.
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
const [state, dispatch] = useTrackedReducer(reducer, initialState, {
|
|
419
|
+
stateName: 'cart',
|
|
420
|
+
telemetry: telemetryInstance,
|
|
421
|
+
trackInitial: false,
|
|
422
|
+
metadata: { userId: '123' }
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// Dispatch actions normally - they'll be tracked automatically
|
|
426
|
+
dispatch({ type: 'ADD_ITEM', payload: { id: 1, name: 'Product' } });
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
#### `useStateTracker(telemetry)`
|
|
430
|
+
|
|
431
|
+
Returns a function to manually track state changes with more control.
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
const trackState = useStateTracker(telemetry);
|
|
435
|
+
|
|
436
|
+
const handleChange = (newValue) => {
|
|
437
|
+
trackState('theme', currentValue, newValue, 'SET_THEME', {
|
|
438
|
+
source: 'user-action'
|
|
439
|
+
});
|
|
440
|
+
setCurrentValue(newValue);
|
|
441
|
+
};
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### Configuration Options
|
|
445
|
+
|
|
446
|
+
- **stateName** (required): A unique identifier for this state (e.g., 'cart', 'userPreferences', 'theme')
|
|
447
|
+
- **telemetry** (required): Your telemetry instance
|
|
448
|
+
- **trackInitial** (optional): Whether to track the initial state value (default: false)
|
|
449
|
+
- **action** (optional): Action name to use when tracking (default: 'STATE_CHANGE')
|
|
450
|
+
- **metadata** (optional): Additional context to include with each state change
|
|
451
|
+
- **shouldTrack** (optional): Function to filter which changes to track - useful for avoiding noise
|
|
452
|
+
|
|
453
|
+
### Example: Shopping Cart
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
import { useTrackedState } from '@lavarage/telemetry/react';
|
|
457
|
+
|
|
458
|
+
function ShoppingCart() {
|
|
459
|
+
const [items, setItems] = useTrackedState([], {
|
|
460
|
+
stateName: 'cartItems',
|
|
461
|
+
telemetry: telemetry,
|
|
462
|
+
action: 'CART_UPDATE',
|
|
463
|
+
shouldTrack: (prev, next) => {
|
|
464
|
+
// Only track if cart actually changed (not just reference)
|
|
465
|
+
return JSON.stringify(prev) !== JSON.stringify(next);
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
const addItem = (item) => {
|
|
470
|
+
setItems([...items, item]);
|
|
471
|
+
// State change is automatically tracked!
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
return (
|
|
475
|
+
<div>
|
|
476
|
+
{items.map(item => <div key={item.id}>{item.name}</div>)}
|
|
477
|
+
<button onClick={() => addItem({ id: 1, name: 'Product' })}>
|
|
478
|
+
Add Item
|
|
479
|
+
</button>
|
|
480
|
+
</div>
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### Example: User Preferences with useReducer
|
|
486
|
+
|
|
487
|
+
```typescript
|
|
488
|
+
import { useTrackedReducer } from '@lavarage/telemetry/react';
|
|
489
|
+
|
|
490
|
+
function preferencesReducer(state, action) {
|
|
491
|
+
switch (action.type) {
|
|
492
|
+
case 'SET_THEME':
|
|
493
|
+
return { ...state, theme: action.payload };
|
|
494
|
+
case 'SET_LANGUAGE':
|
|
495
|
+
return { ...state, language: action.payload };
|
|
496
|
+
default:
|
|
497
|
+
return state;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function UserPreferences() {
|
|
502
|
+
const [prefs, dispatch] = useTrackedReducer(
|
|
503
|
+
preferencesReducer,
|
|
504
|
+
{ theme: 'light', language: 'en' },
|
|
505
|
+
{
|
|
506
|
+
stateName: 'userPreferences',
|
|
507
|
+
telemetry: telemetry,
|
|
508
|
+
metadata: { userId: currentUser.id }
|
|
509
|
+
}
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
return (
|
|
513
|
+
<div>
|
|
514
|
+
<button onClick={() => dispatch({ type: 'SET_THEME', payload: 'dark' })}>
|
|
515
|
+
Dark Mode
|
|
516
|
+
</button>
|
|
517
|
+
{/* State changes are automatically tracked with action type! */}
|
|
518
|
+
</div>
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
336
523
|
## Event Types
|
|
337
524
|
|
|
338
525
|
The SDK tracks the following event types:
|
|
@@ -343,6 +530,7 @@ The SDK tracks the following event types:
|
|
|
343
530
|
- **request**: Network requests (fetch/Axios)
|
|
344
531
|
- **system_event**: System-level events not tied to any wallet address (displayed in separate dashboard panel)
|
|
345
532
|
- **log**: Custom log events (via `logWalletEvent()` or `sendLog()`)
|
|
533
|
+
- **state_change**: React state changes (via `trackStateChange()` or React hooks)
|
|
346
534
|
|
|
347
535
|
## Batching
|
|
348
536
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TelemetryConfig, TelemetryEvent, ErrorEvent, RequestEvent, HostFilterInput, HostFilterConfig, ErrorFilterConfig, SystemEvent } from './types';
|
|
2
2
|
export type { TelemetryConfig, TelemetryEvent, ErrorEvent, RequestEvent, HostFilterInput, HostFilterConfig, ErrorFilterConfig, SystemEvent, };
|
|
3
|
+
export type { StateChangeEvent } from './types';
|
|
3
4
|
export declare class LavarageTelemetry {
|
|
4
5
|
private apiEndpoint;
|
|
5
6
|
private platform;
|
|
@@ -64,5 +65,15 @@ export declare class LavarageTelemetry {
|
|
|
64
65
|
*/
|
|
65
66
|
sendLog(walletAddress: string, eventType: string, message: string, metadata?: object): Promise<void>;
|
|
66
67
|
updateHostFilter(captureHosts: HostFilterInput): void;
|
|
68
|
+
/**
|
|
69
|
+
* Track a React state change
|
|
70
|
+
* Use this method to manually log state changes, or use the useTrackedState/useTrackedReducer hooks for automatic tracking
|
|
71
|
+
* @param stateName - Name/identifier for the state (e.g., 'userPreferences', 'cartItems', 'theme')
|
|
72
|
+
* @param previousValue - Previous state value (optional, will be sanitized)
|
|
73
|
+
* @param newValue - New state value (optional, will be sanitized)
|
|
74
|
+
* @param action - Action that caused the change (e.g., 'SET_USER', 'ADD_TO_CART', 'TOGGLE_THEME')
|
|
75
|
+
* @param metadata - Additional context about the state change
|
|
76
|
+
*/
|
|
77
|
+
trackStateChange(stateName: string, previousValue?: any, newValue?: any, action?: string, metadata?: object): void;
|
|
67
78
|
destroy(): void;
|
|
68
79
|
}
|
package/dist/index.js
CHANGED
|
@@ -684,6 +684,36 @@ class LavarageTelemetry {
|
|
|
684
684
|
// Silently fail
|
|
685
685
|
}
|
|
686
686
|
}
|
|
687
|
+
/**
|
|
688
|
+
* Track a React state change
|
|
689
|
+
* Use this method to manually log state changes, or use the useTrackedState/useTrackedReducer hooks for automatic tracking
|
|
690
|
+
* @param stateName - Name/identifier for the state (e.g., 'userPreferences', 'cartItems', 'theme')
|
|
691
|
+
* @param previousValue - Previous state value (optional, will be sanitized)
|
|
692
|
+
* @param newValue - New state value (optional, will be sanitized)
|
|
693
|
+
* @param action - Action that caused the change (e.g., 'SET_USER', 'ADD_TO_CART', 'TOGGLE_THEME')
|
|
694
|
+
* @param metadata - Additional context about the state change
|
|
695
|
+
*/
|
|
696
|
+
trackStateChange(stateName, previousValue, newValue, action, metadata) {
|
|
697
|
+
try {
|
|
698
|
+
const event = {
|
|
699
|
+
type: 'state_change',
|
|
700
|
+
wallet: this.wallet,
|
|
701
|
+
platform: this.platform,
|
|
702
|
+
stateName,
|
|
703
|
+
previousValue: previousValue !== undefined ? this.sanitizePayload(previousValue) : undefined,
|
|
704
|
+
newValue: newValue !== undefined ? this.sanitizePayload(newValue) : undefined,
|
|
705
|
+
action: action || 'STATE_CHANGE',
|
|
706
|
+
metadata: metadata ? this.sanitizePayload(metadata) : undefined,
|
|
707
|
+
timestamp: Date.now(),
|
|
708
|
+
sessionId: this.sessionId,
|
|
709
|
+
url: typeof window !== 'undefined' ? window.location.href : '',
|
|
710
|
+
};
|
|
711
|
+
this.enqueue(event);
|
|
712
|
+
}
|
|
713
|
+
catch (error) {
|
|
714
|
+
// Silently fail
|
|
715
|
+
}
|
|
716
|
+
}
|
|
687
717
|
destroy() {
|
|
688
718
|
// Restore original functions
|
|
689
719
|
if (this.originalFetch && typeof window !== 'undefined') {
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hooks for automatic state change tracking
|
|
3
|
+
*
|
|
4
|
+
* These hooks wrap React's useState and useReducer to automatically
|
|
5
|
+
* track state changes to the telemetry system.
|
|
6
|
+
*/
|
|
7
|
+
import { Dispatch, SetStateAction, Reducer } from 'react';
|
|
8
|
+
import { LavarageTelemetry } from './index';
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for tracked state
|
|
11
|
+
*/
|
|
12
|
+
export interface TrackedStateConfig {
|
|
13
|
+
/** Name/identifier for this state (e.g., 'userPreferences', 'cartItems') */
|
|
14
|
+
stateName: string;
|
|
15
|
+
/** Telemetry instance to use for tracking */
|
|
16
|
+
telemetry: LavarageTelemetry;
|
|
17
|
+
/** Whether to track the initial state value (default: false) */
|
|
18
|
+
trackInitial?: boolean;
|
|
19
|
+
/** Action name to use when tracking (default: 'STATE_CHANGE') */
|
|
20
|
+
action?: string;
|
|
21
|
+
/** Additional metadata to include with each state change */
|
|
22
|
+
metadata?: object;
|
|
23
|
+
/** Function to determine if a state change should be tracked (useful for filtering) */
|
|
24
|
+
shouldTrack?: (previousValue: any, newValue: any) => boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Hook that wraps useState and automatically tracks state changes
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* const [count, setCount] = useTrackedState(0, {
|
|
32
|
+
* stateName: 'counter',
|
|
33
|
+
* telemetry: telemetryInstance,
|
|
34
|
+
* action: 'SET_COUNT'
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function useTrackedState<T>(initialState: T | (() => T), config: TrackedStateConfig): [T, Dispatch<SetStateAction<T>>];
|
|
39
|
+
/**
|
|
40
|
+
* Action type for tracked reducer
|
|
41
|
+
*/
|
|
42
|
+
export interface TrackedReducerAction {
|
|
43
|
+
type: string;
|
|
44
|
+
payload?: any;
|
|
45
|
+
[key: string]: any;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Hook that wraps useReducer and automatically tracks state changes
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* const [state, dispatch] = useTrackedReducer(reducer, initialState, {
|
|
53
|
+
* stateName: 'cart',
|
|
54
|
+
* telemetry: telemetryInstance
|
|
55
|
+
* });
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function useTrackedReducer<TState, TAction extends TrackedReducerAction>(reducer: Reducer<TState, TAction>, initialState: TState, config: TrackedStateConfig): [TState, Dispatch<TAction>];
|
|
59
|
+
/**
|
|
60
|
+
* Hook to manually track state changes with more control
|
|
61
|
+
* Useful when you want to track state changes but don't want to use the tracked hooks
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* const trackState = useStateTracker(telemetryInstance);
|
|
66
|
+
*
|
|
67
|
+
* const handleChange = (newValue) => {
|
|
68
|
+
* trackState('userPreferences', currentValue, newValue, 'UPDATE_PREFERENCES');
|
|
69
|
+
* setCurrentValue(newValue);
|
|
70
|
+
* };
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare function useStateTracker(telemetry: LavarageTelemetry): (stateName: string, previousValue?: any, newValue?: any, action?: string, metadata?: object) => void;
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* React hooks for automatic state change tracking
|
|
4
|
+
*
|
|
5
|
+
* These hooks wrap React's useState and useReducer to automatically
|
|
6
|
+
* track state changes to the telemetry system.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.useTrackedState = useTrackedState;
|
|
10
|
+
exports.useTrackedReducer = useTrackedReducer;
|
|
11
|
+
exports.useStateTracker = useStateTracker;
|
|
12
|
+
const react_1 = require("react");
|
|
13
|
+
/**
|
|
14
|
+
* Hook that wraps useState and automatically tracks state changes
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const [count, setCount] = useTrackedState(0, {
|
|
19
|
+
* stateName: 'counter',
|
|
20
|
+
* telemetry: telemetryInstance,
|
|
21
|
+
* action: 'SET_COUNT'
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
function useTrackedState(initialState, config) {
|
|
26
|
+
const { stateName, telemetry, trackInitial = false, action, metadata, shouldTrack } = config;
|
|
27
|
+
const [state, setState] = (0, react_1.useState)(initialState);
|
|
28
|
+
const previousStateRef = (0, react_1.useRef)(state);
|
|
29
|
+
const isInitialMount = (0, react_1.useRef)(true);
|
|
30
|
+
// Track initial state if configured
|
|
31
|
+
(0, react_1.useEffect)(() => {
|
|
32
|
+
if (trackInitial && isInitialMount.current) {
|
|
33
|
+
isInitialMount.current = false;
|
|
34
|
+
telemetry.trackStateChange(stateName, undefined, state, action || 'INITIAL_STATE', metadata);
|
|
35
|
+
}
|
|
36
|
+
}, []);
|
|
37
|
+
// Track state changes
|
|
38
|
+
(0, react_1.useEffect)(() => {
|
|
39
|
+
// Skip tracking on initial mount unless trackInitial is true
|
|
40
|
+
if (isInitialMount.current && !trackInitial) {
|
|
41
|
+
isInitialMount.current = false;
|
|
42
|
+
previousStateRef.current = state;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (isInitialMount.current) {
|
|
46
|
+
isInitialMount.current = false;
|
|
47
|
+
previousStateRef.current = state;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const previousValue = previousStateRef.current;
|
|
51
|
+
// Check if we should track this change
|
|
52
|
+
if (shouldTrack && !shouldTrack(previousValue, state)) {
|
|
53
|
+
previousStateRef.current = state;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Track the state change
|
|
57
|
+
telemetry.trackStateChange(stateName, previousValue, state, action, metadata);
|
|
58
|
+
previousStateRef.current = state;
|
|
59
|
+
}, [state, stateName, telemetry, action, metadata, shouldTrack]);
|
|
60
|
+
// Wrapper for setState that ensures tracking
|
|
61
|
+
const trackedSetState = (value) => {
|
|
62
|
+
setState(value);
|
|
63
|
+
};
|
|
64
|
+
return [state, trackedSetState];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Hook that wraps useReducer and automatically tracks state changes
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```tsx
|
|
71
|
+
* const [state, dispatch] = useTrackedReducer(reducer, initialState, {
|
|
72
|
+
* stateName: 'cart',
|
|
73
|
+
* telemetry: telemetryInstance
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
function useTrackedReducer(reducer, initialState, config) {
|
|
78
|
+
const { stateName, telemetry, trackInitial = false, metadata, shouldTrack } = config;
|
|
79
|
+
const [state, dispatch] = (0, react_1.useReducer)(reducer, initialState);
|
|
80
|
+
const previousStateRef = (0, react_1.useRef)(state);
|
|
81
|
+
const isInitialMount = (0, react_1.useRef)(true);
|
|
82
|
+
// Track initial state if configured
|
|
83
|
+
(0, react_1.useEffect)(() => {
|
|
84
|
+
if (trackInitial && isInitialMount.current) {
|
|
85
|
+
isInitialMount.current = false;
|
|
86
|
+
telemetry.trackStateChange(stateName, undefined, state, 'INITIAL_STATE', metadata);
|
|
87
|
+
}
|
|
88
|
+
}, []);
|
|
89
|
+
// Track state changes
|
|
90
|
+
(0, react_1.useEffect)(() => {
|
|
91
|
+
// Skip tracking on initial mount unless trackInitial is true
|
|
92
|
+
if (isInitialMount.current && !trackInitial) {
|
|
93
|
+
isInitialMount.current = false;
|
|
94
|
+
previousStateRef.current = state;
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (isInitialMount.current) {
|
|
98
|
+
isInitialMount.current = false;
|
|
99
|
+
previousStateRef.current = state;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const previousValue = previousStateRef.current;
|
|
103
|
+
// Check if we should track this change
|
|
104
|
+
if (shouldTrack && !shouldTrack(previousValue, state)) {
|
|
105
|
+
previousStateRef.current = state;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// Track the state change (action type will be included in the reducer action)
|
|
109
|
+
telemetry.trackStateChange(stateName, previousValue, state, undefined, // Action will be determined by the reducer
|
|
110
|
+
metadata);
|
|
111
|
+
previousStateRef.current = state;
|
|
112
|
+
}, [state, stateName, telemetry, metadata, shouldTrack]);
|
|
113
|
+
// Wrapper for dispatch that tracks the action
|
|
114
|
+
const trackedDispatch = (action) => {
|
|
115
|
+
// Track before dispatching
|
|
116
|
+
const previousValue = previousStateRef.current;
|
|
117
|
+
dispatch(action);
|
|
118
|
+
// Note: The actual state change will be tracked in the useEffect above
|
|
119
|
+
// But we can also track the action here for immediate feedback
|
|
120
|
+
if (!shouldTrack || shouldTrack(previousValue, state)) {
|
|
121
|
+
telemetry.trackStateChange(stateName, previousValue, state, // This will be the old state, useEffect will track the new one
|
|
122
|
+
action.type || 'REDUCER_ACTION', {
|
|
123
|
+
...metadata,
|
|
124
|
+
actionPayload: action.payload,
|
|
125
|
+
...action
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
return [state, trackedDispatch];
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Hook to manually track state changes with more control
|
|
133
|
+
* Useful when you want to track state changes but don't want to use the tracked hooks
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```tsx
|
|
137
|
+
* const trackState = useStateTracker(telemetryInstance);
|
|
138
|
+
*
|
|
139
|
+
* const handleChange = (newValue) => {
|
|
140
|
+
* trackState('userPreferences', currentValue, newValue, 'UPDATE_PREFERENCES');
|
|
141
|
+
* setCurrentValue(newValue);
|
|
142
|
+
* };
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
function useStateTracker(telemetry) {
|
|
146
|
+
return (stateName, previousValue, newValue, action, metadata) => {
|
|
147
|
+
telemetry.trackStateChange(stateName, previousValue, newValue, action, metadata);
|
|
148
|
+
};
|
|
149
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface ErrorFilterConfig {
|
|
|
17
17
|
exclude?: string[];
|
|
18
18
|
}
|
|
19
19
|
export interface TelemetryEvent {
|
|
20
|
-
type: 'login' | 'pair_view' | 'error' | 'request' | 'system_event';
|
|
20
|
+
type: 'login' | 'pair_view' | 'error' | 'request' | 'system_event' | 'state_change';
|
|
21
21
|
wallet: string | null;
|
|
22
22
|
platform: string;
|
|
23
23
|
timestamp: number;
|
|
@@ -53,3 +53,10 @@ export interface RequestEvent {
|
|
|
53
53
|
export interface BatchIngestRequest {
|
|
54
54
|
events: TelemetryEvent[];
|
|
55
55
|
}
|
|
56
|
+
export interface StateChangeEvent {
|
|
57
|
+
stateName: string;
|
|
58
|
+
previousValue?: any;
|
|
59
|
+
newValue?: any;
|
|
60
|
+
action?: string;
|
|
61
|
+
metadata?: object;
|
|
62
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lavarage/telemetry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Production telemetry SDK for Lavarage and partner applications",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -10,29 +10,56 @@
|
|
|
10
10
|
"node-fetch": false
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "tsc",
|
|
13
|
+
"build": "tsc && tsc --project tsconfig.react.json",
|
|
14
|
+
"build:main": "tsc",
|
|
15
|
+
"build:react": "tsc --project tsconfig.react.json",
|
|
14
16
|
"dev": "tsc --watch",
|
|
15
17
|
"prepublishOnly": "npm run build",
|
|
16
18
|
"test": "jest"
|
|
17
19
|
},
|
|
18
|
-
"keywords": [
|
|
20
|
+
"keywords": [
|
|
21
|
+
"telemetry",
|
|
22
|
+
"analytics",
|
|
23
|
+
"monitoring",
|
|
24
|
+
"lavarage"
|
|
25
|
+
],
|
|
19
26
|
"author": "Lavarage",
|
|
20
27
|
"license": "MIT",
|
|
21
28
|
"peerDependencies": {
|
|
22
|
-
"node-fetch": "^2.6.0 || ^3.0.0"
|
|
29
|
+
"node-fetch": "^2.6.0 || ^3.0.0",
|
|
30
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
23
31
|
},
|
|
24
32
|
"peerDependenciesMeta": {
|
|
25
33
|
"node-fetch": {
|
|
26
34
|
"optional": true
|
|
35
|
+
},
|
|
36
|
+
"react": {
|
|
37
|
+
"optional": true
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"exports": {
|
|
41
|
+
".": {
|
|
42
|
+
"import": "./dist/index.js",
|
|
43
|
+
"require": "./dist/index.js",
|
|
44
|
+
"types": "./dist/index.d.ts"
|
|
45
|
+
},
|
|
46
|
+
"./react": {
|
|
47
|
+
"import": "./dist/react.js",
|
|
48
|
+
"require": "./dist/react.js",
|
|
49
|
+
"types": "./dist/react.d.ts"
|
|
27
50
|
}
|
|
28
51
|
},
|
|
29
52
|
"devDependencies": {
|
|
53
|
+
"@types/jest": "^29.0.0",
|
|
30
54
|
"@types/node": "^20.0.0",
|
|
31
|
-
"
|
|
55
|
+
"@types/react": "^19.2.8",
|
|
56
|
+
"@types/react-dom": "^19.2.3",
|
|
32
57
|
"jest": "^29.0.0",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
58
|
+
"ts-jest": "^29.0.0",
|
|
59
|
+
"typescript": "^5.0.0"
|
|
35
60
|
},
|
|
36
|
-
"files": [
|
|
61
|
+
"files": [
|
|
62
|
+
"dist",
|
|
63
|
+
"README.md"
|
|
64
|
+
]
|
|
37
65
|
}
|
|
38
|
-
|