@multiplayer-app/session-recorder-react-native 0.0.1-alpha.8 → 0.0.1
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/components/GestureCaptureWrapper/GestureCaptureWrapper.d.ts +6 -0
- package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.js +1 -0
- package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.js.map +1 -0
- package/dist/components/GestureCaptureWrapper/index.d.ts +1 -0
- package/dist/components/GestureCaptureWrapper/index.js +1 -0
- package/dist/components/GestureCaptureWrapper/index.js.map +1 -0
- package/dist/components/GestureCaptureWrapper.js +1 -1
- package/dist/components/GestureCaptureWrapper.js.map +1 -1
- package/dist/components/ScreenRecorderView/ScreenRecorderView.d.ts +5 -0
- package/dist/components/ScreenRecorderView/ScreenRecorderView.js +1 -0
- package/dist/components/ScreenRecorderView/ScreenRecorderView.js.map +1 -0
- package/dist/components/ScreenRecorderView/index.d.ts +1 -0
- package/dist/components/ScreenRecorderView/index.js +1 -0
- package/dist/components/ScreenRecorderView/index.js.map +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/index.js.map +1 -0
- package/dist/context/SessionRecorderContext.js +1 -1
- package/dist/context/SessionRecorderContext.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/otel/index.d.ts +0 -2
- package/dist/otel/index.js.map +1 -1
- package/dist/otel/instrumentations/gestureInstrumentation.js +1 -1
- package/dist/otel/instrumentations/gestureInstrumentation.js.map +1 -1
- package/dist/otel/instrumentations/index.d.ts +0 -3
- package/dist/otel/instrumentations/index.js +1 -1
- package/dist/otel/instrumentations/index.js.map +1 -1
- package/dist/patch/xhr.js +1 -1
- package/dist/patch/xhr.js.map +1 -1
- package/dist/recorder/gestureRecorder.d.ts +0 -9
- package/dist/recorder/gestureRecorder.js +1 -1
- package/dist/recorder/gestureRecorder.js.map +1 -1
- package/dist/recorder/index.d.ts +4 -3
- package/dist/recorder/index.js +1 -1
- package/dist/recorder/index.js.map +1 -1
- package/dist/recorder/screenRecorder.d.ts +1 -6
- package/dist/recorder/screenRecorder.js +1 -1
- package/dist/recorder/screenRecorder.js.map +1 -1
- package/dist/session-recorder.d.ts +3 -2
- package/dist/session-recorder.js.map +1 -1
- package/dist/types/index.d.ts +2 -16
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/app-metadata.d.ts +16 -0
- package/dist/utils/app-metadata.js +1 -0
- package/dist/utils/app-metadata.js.map +1 -0
- package/dist/utils/platform.d.ts +35 -3
- package/dist/utils/platform.js +1 -1
- package/dist/utils/platform.js.map +1 -1
- package/dist/utils/rrweb-events.d.ts +1 -1
- package/dist/utils/rrweb-events.js +1 -1
- package/dist/utils/rrweb-events.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/AUTO_METADATA_DETECTION.md +108 -0
- package/package.json +6 -9
- package/scripts/generate-app-metadata.js +173 -0
- package/src/components/{GestureCaptureWrapper.tsx → GestureCaptureWrapper/GestureCaptureWrapper.tsx} +1 -25
- package/src/components/GestureCaptureWrapper/index.ts +1 -0
- package/src/components/ScreenRecorderView/ScreenRecorderView.tsx +72 -0
- package/src/components/ScreenRecorderView/index.ts +1 -0
- package/src/components/index.ts +1 -0
- package/src/context/SessionRecorderContext.tsx +21 -89
- package/src/index.ts +8 -0
- package/src/otel/index.ts +1 -12
- package/src/otel/instrumentations/index.ts +1 -6
- package/src/patch/xhr.ts +2 -2
- package/src/recorder/gestureRecorder.ts +10 -134
- package/src/recorder/index.ts +9 -7
- package/src/recorder/screenRecorder.ts +6 -14
- package/src/session-recorder.ts +2 -3
- package/src/types/index.ts +2 -20
- package/src/utils/app-metadata.ts +31 -0
- package/src/utils/platform.ts +303 -6
- package/src/utils/rrweb-events.ts +2 -4
- package/src/version.ts +1 -1
- package/example-usage.tsx +0 -174
- package/src/otel/instrumentations/gestureInstrumentation.ts +0 -141
- package/src/otel/instrumentations/reactNativeInstrumentation.ts +0 -77
- package/src/otel/instrumentations/reactNavigationInstrumentation.ts +0 -119
- package/src/recorder/gestureHandlerRecorder.ts +0 -157
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { InstrumentationBase } from '@opentelemetry/instrumentation'
|
|
2
|
-
import { logger } from '../../utils'
|
|
3
|
-
import { trace, SpanStatusCode } from '@opentelemetry/api'
|
|
4
|
-
import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
5
|
-
|
|
6
|
-
export class ReactNativeInstrumentation extends InstrumentationBase {
|
|
7
|
-
constructor() {
|
|
8
|
-
super('react-native', '1.0.0', {})
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
init(): void {
|
|
12
|
-
// Initialize the instrumentation
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
enable(): void {
|
|
16
|
-
// Try to wrap AsyncStorage if it's available
|
|
17
|
-
try {
|
|
18
|
-
if (AsyncStorage) {
|
|
19
|
-
this._wrap(AsyncStorage, 'setItem', this._wrapAsyncStorage)
|
|
20
|
-
}
|
|
21
|
-
} catch (error) {
|
|
22
|
-
logger.warn('DEBUGGER_LIB', '@react-native-async-storage/async-storage is not available. AsyncStorage instrumentation will be disabled.')
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
disable(): void {
|
|
27
|
-
// Try to unwrap AsyncStorage if it was wrapped
|
|
28
|
-
try {
|
|
29
|
-
if (AsyncStorage) {
|
|
30
|
-
this._unwrap(AsyncStorage, 'setItem')
|
|
31
|
-
}
|
|
32
|
-
} catch (error) {
|
|
33
|
-
// AsyncStorage was not available, nothing to unwrap
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
private _wrapAsyncStorage(originalMethod: any) {
|
|
38
|
-
return async function (this: any, key: string, value: string) {
|
|
39
|
-
const startTime = Date.now()
|
|
40
|
-
try {
|
|
41
|
-
const result = await originalMethod.call(this, key, value)
|
|
42
|
-
|
|
43
|
-
const span = trace.getTracer('react-native').startSpan('AsyncStorage.setItem', {
|
|
44
|
-
attributes: {
|
|
45
|
-
'storage.operation': 'setItem',
|
|
46
|
-
'storage.key': key,
|
|
47
|
-
'storage.value_length': value.length,
|
|
48
|
-
'storage.duration': Date.now() - startTime,
|
|
49
|
-
},
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
span.setStatus({ code: SpanStatusCode.OK })
|
|
53
|
-
span.end()
|
|
54
|
-
|
|
55
|
-
return result
|
|
56
|
-
} catch (error) {
|
|
57
|
-
const span = trace.getTracer('react-native').startSpan('AsyncStorage.setItem', {
|
|
58
|
-
attributes: {
|
|
59
|
-
'storage.operation': 'setItem',
|
|
60
|
-
'storage.key': key,
|
|
61
|
-
'storage.error': true,
|
|
62
|
-
'storage.duration': Date.now() - startTime,
|
|
63
|
-
},
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
67
|
-
span.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage })
|
|
68
|
-
if (error instanceof Error) {
|
|
69
|
-
span.recordException(error)
|
|
70
|
-
}
|
|
71
|
-
span.end()
|
|
72
|
-
|
|
73
|
-
throw error
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { InstrumentationBase } from '@opentelemetry/instrumentation'
|
|
2
|
-
import { trace, SpanStatusCode } from '@opentelemetry/api'
|
|
3
|
-
|
|
4
|
-
export class ReactNavigationInstrumentation extends InstrumentationBase {
|
|
5
|
-
private navigationRef: any = null
|
|
6
|
-
|
|
7
|
-
constructor() {
|
|
8
|
-
super('react-navigation', '1.0.0', {})
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
init(): void {
|
|
12
|
-
// Initialize the instrumentation
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
enable(): void {
|
|
16
|
-
// Enable the instrumentation
|
|
17
|
-
super.enable()
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
setNavigationRef(ref: any) {
|
|
21
|
-
this.navigationRef = ref
|
|
22
|
-
this._setupNavigationListener()
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
private _setupNavigationListener() {
|
|
26
|
-
if (!this.navigationRef) return
|
|
27
|
-
|
|
28
|
-
// Listen to navigation state changes
|
|
29
|
-
this.navigationRef.addListener('state', (e: any) => {
|
|
30
|
-
this._recordNavigationEvent('state_change', e.data)
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
// Listen to focus events
|
|
34
|
-
this.navigationRef.addListener('focus', (e: any) => {
|
|
35
|
-
this._recordNavigationEvent('focus', e.data)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
// Listen to blur events
|
|
39
|
-
this.navigationRef.addListener('blur', (e: any) => {
|
|
40
|
-
this._recordNavigationEvent('blur', e.data)
|
|
41
|
-
})
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
private _recordNavigationEvent(eventType: string, data: any) {
|
|
45
|
-
const span = trace.getTracer('navigation').startSpan(`Navigation.${eventType}`, {
|
|
46
|
-
attributes: {
|
|
47
|
-
'navigation.system': 'ReactNavigation',
|
|
48
|
-
'navigation.operation': eventType,
|
|
49
|
-
'navigation.type': eventType,
|
|
50
|
-
'navigation.timestamp': Date.now(),
|
|
51
|
-
},
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
if (data) {
|
|
55
|
-
if (data.routeName) {
|
|
56
|
-
span.setAttribute('navigation.route_name', data.routeName)
|
|
57
|
-
}
|
|
58
|
-
if (data.params) {
|
|
59
|
-
span.setAttribute('navigation.params', JSON.stringify(data.params))
|
|
60
|
-
}
|
|
61
|
-
if (data.key) {
|
|
62
|
-
span.setAttribute('navigation.key', data.key)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
span.setStatus({ code: SpanStatusCode.OK })
|
|
67
|
-
span.end()
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Manual navigation tracking methods
|
|
71
|
-
recordNavigate(routeName: string, params?: Record<string, any>) {
|
|
72
|
-
const span = trace.getTracer('navigation').startSpan('Navigation.navigate', {
|
|
73
|
-
attributes: {
|
|
74
|
-
'navigation.system': 'ReactNavigation',
|
|
75
|
-
'navigation.operation': 'navigate',
|
|
76
|
-
'navigation.route_name': routeName,
|
|
77
|
-
'navigation.timestamp': Date.now(),
|
|
78
|
-
},
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
if (params) {
|
|
82
|
-
span.setAttribute('navigation.params', JSON.stringify(params))
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
span.setStatus({ code: SpanStatusCode.OK })
|
|
86
|
-
span.end()
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
recordGoBack() {
|
|
90
|
-
const span = trace.getTracer('navigation').startSpan('Navigation.goBack', {
|
|
91
|
-
attributes: {
|
|
92
|
-
'navigation.system': 'ReactNavigation',
|
|
93
|
-
'navigation.operation': 'goBack',
|
|
94
|
-
'navigation.timestamp': Date.now(),
|
|
95
|
-
},
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
span.setStatus({ code: SpanStatusCode.OK })
|
|
99
|
-
span.end()
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
recordReset(routes: any[]) {
|
|
103
|
-
const span = trace.getTracer('navigation').startSpan('Navigation.reset', {
|
|
104
|
-
attributes: {
|
|
105
|
-
'navigation.system': 'ReactNavigation',
|
|
106
|
-
'navigation.operation': 'reset',
|
|
107
|
-
'navigation.routes_count': routes.length,
|
|
108
|
-
'navigation.timestamp': Date.now(),
|
|
109
|
-
},
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
if (routes.length > 0) {
|
|
113
|
-
span.setAttribute('navigation.initial_route', routes[0].name)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
span.setStatus({ code: SpanStatusCode.OK })
|
|
117
|
-
span.end()
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { Gesture } from 'react-native-gesture-handler'
|
|
2
|
-
import { ReactNode } from 'react'
|
|
3
|
-
import { SessionState } from '../types'
|
|
4
|
-
import { GestureInstrumentation } from '../otel/instrumentations/gestureInstrumentation'
|
|
5
|
-
|
|
6
|
-
export interface GestureHandlerRecorderProps {
|
|
7
|
-
children: ReactNode
|
|
8
|
-
sessionState: SessionState | null
|
|
9
|
-
onGestureRecord: (gestureType: string, data: any) => void
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export class GestureHandlerRecorder {
|
|
13
|
-
private gestureInstrumentation: GestureInstrumentation
|
|
14
|
-
private onGestureRecord?: (gestureType: string, data: any) => void
|
|
15
|
-
|
|
16
|
-
constructor() {
|
|
17
|
-
this.gestureInstrumentation = new GestureInstrumentation()
|
|
18
|
-
this.gestureInstrumentation.enable()
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
setGestureCallback(callback: (gestureType: string, data: any) => void) {
|
|
22
|
-
this.onGestureRecord = callback
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Create tap gesture
|
|
26
|
-
createTapGesture() {
|
|
27
|
-
return Gesture.Tap()
|
|
28
|
-
.onStart((event) => {
|
|
29
|
-
this.recordGesture('tap', {
|
|
30
|
-
x: event.x,
|
|
31
|
-
y: event.y,
|
|
32
|
-
timestamp: Date.now(),
|
|
33
|
-
})
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Create pan gesture (for swipes and drags)
|
|
38
|
-
createPanGesture() {
|
|
39
|
-
return Gesture.Pan()
|
|
40
|
-
.onStart((event) => {
|
|
41
|
-
this.recordGesture('pan_start', {
|
|
42
|
-
x: event.x,
|
|
43
|
-
y: event.y,
|
|
44
|
-
timestamp: Date.now(),
|
|
45
|
-
})
|
|
46
|
-
})
|
|
47
|
-
.onUpdate((event) => {
|
|
48
|
-
this.recordGesture('pan_update', {
|
|
49
|
-
x: event.x,
|
|
50
|
-
y: event.y,
|
|
51
|
-
translationX: event.translationX,
|
|
52
|
-
translationY: event.translationY,
|
|
53
|
-
velocityX: event.velocityX,
|
|
54
|
-
velocityY: event.velocityY,
|
|
55
|
-
timestamp: Date.now(),
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
.onEnd((event) => {
|
|
59
|
-
this.recordGesture('pan_end', {
|
|
60
|
-
x: event.x,
|
|
61
|
-
y: event.y,
|
|
62
|
-
translationX: event.translationX,
|
|
63
|
-
translationY: event.translationY,
|
|
64
|
-
velocityX: event.velocityX,
|
|
65
|
-
velocityY: event.velocityY,
|
|
66
|
-
timestamp: Date.now(),
|
|
67
|
-
})
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Create pinch gesture
|
|
72
|
-
createPinchGesture() {
|
|
73
|
-
return Gesture.Pinch()
|
|
74
|
-
.onStart((event) => {
|
|
75
|
-
this.recordGesture('pinch_start', {
|
|
76
|
-
scale: event.scale,
|
|
77
|
-
focalX: event.focalX,
|
|
78
|
-
focalY: event.focalY,
|
|
79
|
-
timestamp: Date.now(),
|
|
80
|
-
})
|
|
81
|
-
})
|
|
82
|
-
.onUpdate((event) => {
|
|
83
|
-
this.recordGesture('pinch_update', {
|
|
84
|
-
scale: event.scale,
|
|
85
|
-
focalX: event.focalX,
|
|
86
|
-
focalY: event.focalY,
|
|
87
|
-
timestamp: Date.now(),
|
|
88
|
-
})
|
|
89
|
-
})
|
|
90
|
-
.onEnd((event) => {
|
|
91
|
-
this.recordGesture('pinch_end', {
|
|
92
|
-
scale: event.scale,
|
|
93
|
-
focalX: event.focalX,
|
|
94
|
-
focalY: event.focalY,
|
|
95
|
-
timestamp: Date.now(),
|
|
96
|
-
})
|
|
97
|
-
})
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Create long press gesture
|
|
101
|
-
createLongPressGesture() {
|
|
102
|
-
return Gesture.LongPress()
|
|
103
|
-
.minDuration(500)
|
|
104
|
-
.onStart((event) => {
|
|
105
|
-
this.recordGesture('long_press', {
|
|
106
|
-
x: event.x,
|
|
107
|
-
y: event.y,
|
|
108
|
-
duration: 500,
|
|
109
|
-
timestamp: Date.now(),
|
|
110
|
-
})
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private recordGesture(gestureType: string, data: any) {
|
|
115
|
-
// Record with OpenTelemetry
|
|
116
|
-
switch (gestureType) {
|
|
117
|
-
case 'tap':
|
|
118
|
-
this.gestureInstrumentation.recordTap(data.x, data.y)
|
|
119
|
-
break
|
|
120
|
-
case 'pan_start':
|
|
121
|
-
case 'pan_update':
|
|
122
|
-
case 'pan_end':
|
|
123
|
-
this.gestureInstrumentation.recordPan(data.translationX || 0, data.translationY || 0)
|
|
124
|
-
break
|
|
125
|
-
case 'pinch_start':
|
|
126
|
-
case 'pinch_update':
|
|
127
|
-
case 'pinch_end':
|
|
128
|
-
this.gestureInstrumentation.recordPinch(data.scale, undefined)
|
|
129
|
-
break
|
|
130
|
-
case 'long_press':
|
|
131
|
-
this.gestureInstrumentation.recordLongPress(data.duration, undefined)
|
|
132
|
-
break
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Record with session recorder
|
|
136
|
-
if (this.onGestureRecord) {
|
|
137
|
-
this.onGestureRecord(gestureType, data)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Create a gesture detector component
|
|
142
|
-
createGestureDetector(children: ReactNode, sessionState: SessionState | null): ReactNode {
|
|
143
|
-
if (sessionState !== SessionState.started) {
|
|
144
|
-
return children
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const tapGesture = this.createTapGesture()
|
|
148
|
-
const panGesture = this.createPanGesture()
|
|
149
|
-
const pinchGesture = this.createPinchGesture()
|
|
150
|
-
const longPressGesture = this.createLongPressGesture()
|
|
151
|
-
|
|
152
|
-
// Note: This would need to be implemented as a proper React component
|
|
153
|
-
// For now, return children directly - the gesture detection would be handled
|
|
154
|
-
// at the app level by wrapping the entire app with GestureHandlerRootView
|
|
155
|
-
return children
|
|
156
|
-
}
|
|
157
|
-
}
|