@truewatchtech/react-native-mobile 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FTMobileReactNativeSDK.podspec +7 -5
- package/android/build.gradle +10 -3
- package/android/src/main/java/com/ft/sdk/reactnative/FTLogImpl.java +10 -2
- package/android/src/main/java/com/ft/sdk/reactnative/FTMobileImpl.java +45 -10
- package/android/src/main/java/com/ft/sdk/reactnative/FTRUMImpl.java +131 -6
- package/android/src/main/java/com/ft/sdk/reactnative/FTTraceImpl.java +10 -3
- package/android/src/main/java/com/ft/sdk/reactnative/JsLongTaskMonitor.java +281 -0
- package/android/src/main/java/com/ft/sdk/reactnative/ViewTiming.java +17 -0
- package/android/src/main/java/com/ft/sdk/reactnative/VisitorIdConfigMapper.java +50 -0
- package/android/src/main/java/com/ft/sdk/reactnative/utils/ReactNativeUtils.java +5 -12
- package/android/src/newarch/java/com/ft/sdk/reactnative/FTMobileModule.java +14 -5
- package/android/src/newarch/java/com/ft/sdk/reactnative/FTRUMModule.java +44 -1
- package/android/src/newarch/java/com/ft/sdk/reactnative/FTTraceModule.java +14 -0
- package/android/src/oldarch/java/com/ft/sdk/reactnative/FTMobileModule.java +7 -2
- package/android/src/oldarch/java/com/ft/sdk/reactnative/FTRUMModule.java +39 -1
- package/android/src/oldarch/java/com/ft/sdk/reactnative/FTTraceModule.java +12 -0
- package/android/src/rnpost70/java/com/ft/sdk/reactnative/ReactJsThreadExecutor.java +21 -0
- package/android/src/rnpre70/java/com/ft/sdk/reactnative/ReactJsThreadExecutor.java +37 -0
- package/android/src/test/java/com/ft/sdk/reactnative/FTMobileImplTest.java +53 -0
- package/android/src/test/java/com/ft/sdk/reactnative/FTRUMModuleTest.java +117 -0
- package/android/src/test/java/com/ft/sdk/reactnative/JsLongTaskMonitorTest.java +446 -0
- package/android/src/test/java/com/ft/sdk/reactnative/utils/ReactNativeUtilsTest.java +33 -0
- package/ios/FTJSLongTaskMonitor.h +51 -0
- package/ios/FTJSLongTaskMonitor.m +250 -0
- package/ios/FTMobileReactNative.mm +54 -18
- package/ios/FTReactNativeLog.mm +9 -5
- package/ios/FTReactNativeRUM.mm +196 -31
- package/ios/FTReactNativeResource.h +4 -0
- package/ios/FTReactNativeResource.m +64 -0
- package/ios/FTReactNativeTrace.mm +59 -14
- package/ios/FTReactNativeUtils.m +10 -15
- package/ios/FTReactNativeViewTiming.h +18 -0
- package/ios/FTReactNativeWebSocket.h +10 -0
- package/ios/FTReactNativeWebSocket.mm +201 -0
- package/ios/FTWebSocketMetadataStore.h +25 -0
- package/ios/FTWebSocketMetadataStore.m +622 -0
- package/ios/FTWebSocketResourceData.h +20 -0
- package/ios/FTWebSocketResourceData.m +106 -0
- package/lib/commonjs/ft_logger.js +3 -1
- package/lib/commonjs/ft_logger.js.map +1 -1
- package/lib/commonjs/ft_mobile_agent.js +47 -4
- package/lib/commonjs/ft_mobile_agent.js.map +1 -1
- package/lib/commonjs/ft_rum.js +65 -5
- package/lib/commonjs/ft_rum.js.map +1 -1
- package/lib/commonjs/ft_tracing.js +14 -4
- package/lib/commonjs/ft_tracing.js.map +1 -1
- package/lib/commonjs/index.js +21 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/rum/FTBabelInteractionTracking.js +72 -0
- package/lib/commonjs/rum/FTBabelInteractionTracking.js.map +1 -0
- package/lib/commonjs/rum/FTBabelUtils.js +87 -0
- package/lib/commonjs/rum/FTBabelUtils.js.map +1 -0
- package/lib/commonjs/rum/FTRumActionTracking.js +10 -39
- package/lib/commonjs/rum/FTRumActionTracking.js.map +1 -1
- package/lib/commonjs/rum/FTRumActionTrackingContext.js +50 -0
- package/lib/commonjs/rum/FTRumActionTrackingContext.js.map +1 -0
- package/lib/commonjs/rum/FTRumViewTracking.js +147 -0
- package/lib/commonjs/rum/FTRumViewTracking.js.map +1 -0
- package/lib/commonjs/rum/FTRumWebSocketNative.js +73 -0
- package/lib/commonjs/rum/FTRumWebSocketNative.js.map +1 -0
- package/lib/commonjs/rum/FTRumWebSocketTiming.js +73 -0
- package/lib/commonjs/rum/FTRumWebSocketTiming.js.map +1 -0
- package/lib/commonjs/rum/FTRumWebSocketTracking.js +506 -0
- package/lib/commonjs/rum/FTRumWebSocketTracking.js.map +1 -0
- package/lib/commonjs/rum/longTasksUtils.js +25 -0
- package/lib/commonjs/rum/longTasksUtils.js.map +1 -0
- package/lib/commonjs/specs/NativeFTMobileReactNative.js.map +1 -1
- package/lib/commonjs/specs/NativeFTReactNativeRUM.js.map +1 -1
- package/lib/commonjs/specs/NativeFTReactNativeTrace.js.map +1 -1
- package/lib/commonjs/specs/NativeFTReactNativeWebSocket.js +11 -0
- package/lib/commonjs/specs/NativeFTReactNativeWebSocket.js.map +1 -0
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/commonjs/visitorIdConfig.js +37 -0
- package/lib/commonjs/visitorIdConfig.js.map +1 -0
- package/lib/module/ft_logger.js +3 -1
- package/lib/module/ft_logger.js.map +1 -1
- package/lib/module/ft_mobile_agent.js +47 -4
- package/lib/module/ft_mobile_agent.js.map +1 -1
- package/lib/module/ft_rum.js +65 -5
- package/lib/module/ft_rum.js.map +1 -1
- package/lib/module/ft_tracing.js +14 -2
- package/lib/module/ft_tracing.js.map +1 -1
- package/lib/module/index.js +4 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/rum/FTBabelInteractionTracking.js +66 -0
- package/lib/module/rum/FTBabelInteractionTracking.js.map +1 -0
- package/lib/module/rum/FTBabelUtils.js +80 -0
- package/lib/module/rum/FTBabelUtils.js.map +1 -0
- package/lib/module/rum/FTRumActionTracking.js +10 -39
- package/lib/module/rum/FTRumActionTracking.js.map +1 -1
- package/lib/module/rum/FTRumActionTrackingContext.js +43 -0
- package/lib/module/rum/FTRumActionTrackingContext.js.map +1 -0
- package/lib/module/rum/FTRumViewTracking.js +140 -0
- package/lib/module/rum/FTRumViewTracking.js.map +1 -0
- package/lib/module/rum/FTRumWebSocketNative.js +62 -0
- package/lib/module/rum/FTRumWebSocketNative.js.map +1 -0
- package/lib/module/rum/FTRumWebSocketTiming.js +67 -0
- package/lib/module/rum/FTRumWebSocketTiming.js.map +1 -0
- package/lib/module/rum/FTRumWebSocketTracking.js +499 -0
- package/lib/module/rum/FTRumWebSocketTracking.js.map +1 -0
- package/lib/module/rum/longTasksUtils.js +18 -0
- package/lib/module/rum/longTasksUtils.js.map +1 -0
- package/lib/module/specs/NativeFTMobileReactNative.js.map +1 -1
- package/lib/module/specs/NativeFTReactNativeRUM.js.map +1 -1
- package/lib/module/specs/NativeFTReactNativeTrace.js.map +1 -1
- package/lib/module/specs/NativeFTReactNativeWebSocket.js +8 -0
- package/lib/module/specs/NativeFTReactNativeWebSocket.js.map +1 -0
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/module/visitorIdConfig.js +31 -0
- package/lib/module/visitorIdConfig.js.map +1 -0
- package/lib/typescript/ft_logger.d.ts +11 -1
- package/lib/typescript/ft_mobile_agent.d.ts +28 -0
- package/lib/typescript/ft_rum.d.ts +42 -5
- package/lib/typescript/ft_tracing.d.ts +9 -1
- package/lib/typescript/index.d.ts +5 -1
- package/lib/typescript/rum/FTBabelInteractionTracking.d.ts +30 -0
- package/lib/typescript/rum/FTBabelUtils.d.ts +1 -0
- package/lib/typescript/rum/FTRumActionTracking.d.ts +0 -2
- package/lib/typescript/rum/FTRumActionTrackingContext.d.ts +11 -0
- package/lib/typescript/rum/FTRumViewTracking.d.ts +32 -0
- package/lib/typescript/rum/FTRumWebSocketNative.d.ts +22 -0
- package/lib/typescript/rum/FTRumWebSocketTiming.d.ts +7 -0
- package/lib/typescript/rum/FTRumWebSocketTracking.d.ts +54 -0
- package/lib/typescript/rum/longTasksUtils.d.ts +8 -0
- package/lib/typescript/specs/NativeFTMobileReactNative.d.ts +15 -0
- package/lib/typescript/specs/NativeFTReactNativeRUM.d.ts +11 -1
- package/lib/typescript/specs/NativeFTReactNativeTrace.d.ts +12 -0
- package/lib/typescript/specs/NativeFTReactNativeWebSocket.d.ts +13 -0
- package/lib/typescript/version.d.ts +1 -1
- package/lib/typescript/visitorIdConfig.d.ts +11 -0
- package/package.json +6 -4
- package/src/ft_logger.tsx +11 -1
- package/src/ft_mobile_agent.tsx +79 -7
- package/src/ft_rum.tsx +111 -7
- package/src/ft_tracing.tsx +24 -2
- package/src/index.tsx +8 -0
- package/src/rum/FTBabelInteractionTracking.ts +124 -0
- package/src/rum/FTBabelUtils.tsx +99 -0
- package/src/rum/FTRumActionTracking.tsx +14 -43
- package/src/rum/FTRumActionTrackingContext.ts +68 -0
- package/src/rum/FTRumViewTracking.ts +179 -0
- package/src/rum/FTRumWebSocketNative.ts +107 -0
- package/src/rum/FTRumWebSocketTiming.ts +82 -0
- package/src/rum/FTRumWebSocketTracking.ts +722 -0
- package/src/rum/longTasksUtils.ts +17 -0
- package/src/specs/NativeFTMobileReactNative.ts +18 -0
- package/src/specs/NativeFTReactNativeRUM.ts +19 -1
- package/src/specs/NativeFTReactNativeTrace.ts +12 -0
- package/src/specs/NativeFTReactNativeWebSocket.ts +33 -0
- package/src/version.ts +1 -1
- package/src/visitorIdConfig.ts +123 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
typedef void (^FTJSLongTaskFrameCallback)(CFTimeInterval timestamp);
|
|
6
|
+
|
|
7
|
+
@protocol FTJSLongTaskQueue <NSObject>
|
|
8
|
+
- (BOOL)dispatchBlock:(dispatch_block_t)block;
|
|
9
|
+
@end
|
|
10
|
+
|
|
11
|
+
@protocol FTJSLongTaskFrameScheduler <NSObject>
|
|
12
|
+
// The monitor serializes start/stop; start runs on the JS thread, while stop
|
|
13
|
+
// must release resources synchronously even when that thread is unavailable.
|
|
14
|
+
- (void)start;
|
|
15
|
+
- (void)stop;
|
|
16
|
+
@end
|
|
17
|
+
|
|
18
|
+
@protocol FTJSLongTaskFrameSchedulerFactory <NSObject>
|
|
19
|
+
- (id<FTJSLongTaskFrameScheduler>)createSchedulerWithCallback:(FTJSLongTaskFrameCallback)callback;
|
|
20
|
+
@end
|
|
21
|
+
|
|
22
|
+
@protocol FTJSLongTaskReporter <NSObject>
|
|
23
|
+
- (void)reportLongTaskWithDurationNanoseconds:(int64_t)durationNanoseconds property:(NSDictionary *)property;
|
|
24
|
+
@end
|
|
25
|
+
|
|
26
|
+
@interface FTJSLongTaskMonitor : NSObject
|
|
27
|
+
|
|
28
|
+
- (instancetype)initWithQueue:(id<FTJSLongTaskQueue>)queue
|
|
29
|
+
schedulerFactory:(id<FTJSLongTaskFrameSchedulerFactory>)schedulerFactory
|
|
30
|
+
reporter:(id<FTJSLongTaskReporter>)reporter NS_DESIGNATED_INITIALIZER;
|
|
31
|
+
- (instancetype)init NS_UNAVAILABLE;
|
|
32
|
+
|
|
33
|
+
- (void)setThresholdMilliseconds:(double)thresholdMilliseconds;
|
|
34
|
+
// Replaces the snapshot for future detections; does not change monitor lifecycle.
|
|
35
|
+
- (void)setBridgeContext:(NSDictionary *)context;
|
|
36
|
+
- (void)start;
|
|
37
|
+
- (void)stop;
|
|
38
|
+
// Completion runs on the calling thread after resources have been released.
|
|
39
|
+
- (void)stopWithCompletion:(nullable dispatch_block_t)completion;
|
|
40
|
+
// Prevents automatic restarts until a nonzero threshold is configured again.
|
|
41
|
+
- (void)disableWithCompletion:(nullable dispatch_block_t)completion;
|
|
42
|
+
|
|
43
|
+
@end
|
|
44
|
+
|
|
45
|
+
@class RCTBridge;
|
|
46
|
+
|
|
47
|
+
@interface FTJSLongTaskMonitor (Production)
|
|
48
|
+
+ (instancetype)monitorWithBridge:(RCTBridge *)bridge;
|
|
49
|
+
@end
|
|
50
|
+
|
|
51
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
#import "FTJSLongTaskMonitor.h"
|
|
2
|
+
|
|
3
|
+
#import <QuartzCore/CADisplayLink.h>
|
|
4
|
+
#import <TrueWatchSDK/FTExternalDataManager.h>
|
|
5
|
+
#import <React/RCTBridge.h>
|
|
6
|
+
#import <React/RCTBridge+Private.h>
|
|
7
|
+
#import <React/RCTJSThread.h>
|
|
8
|
+
|
|
9
|
+
static const double FTNanosecondsPerSecond = 1000000000.0;
|
|
10
|
+
|
|
11
|
+
@interface FTReactBridgeJSQueue : NSObject <FTJSLongTaskQueue>
|
|
12
|
+
@property (nonatomic, weak) RCTBridge *bridge;
|
|
13
|
+
- (instancetype)initWithBridge:(RCTBridge *)bridge;
|
|
14
|
+
@end
|
|
15
|
+
|
|
16
|
+
@implementation FTReactBridgeJSQueue
|
|
17
|
+
- (instancetype)initWithBridge:(RCTBridge *)bridge {
|
|
18
|
+
self = [super init];
|
|
19
|
+
if (self) {
|
|
20
|
+
_bridge = bridge;
|
|
21
|
+
}
|
|
22
|
+
return self;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
- (BOOL)dispatchBlock:(dispatch_block_t)block {
|
|
26
|
+
RCTBridge *bridge = self.bridge;
|
|
27
|
+
if (bridge == nil) {
|
|
28
|
+
return NO;
|
|
29
|
+
}
|
|
30
|
+
@try {
|
|
31
|
+
// RCTBridgeProxy.valid is always NO, including while bridgeless RN is active.
|
|
32
|
+
[bridge dispatchBlock:block queue:RCTJSThread];
|
|
33
|
+
return YES;
|
|
34
|
+
} @catch (NSException *exception) {
|
|
35
|
+
// Bridge teardown may race a start request. Monitoring must not take down the host.
|
|
36
|
+
return NO;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
@end
|
|
40
|
+
|
|
41
|
+
// The display link retains this callback target, not the scheduler that owns it.
|
|
42
|
+
@interface FTJSLongTaskDisplayLinkTarget : NSObject
|
|
43
|
+
@property (nonatomic, copy) FTJSLongTaskFrameCallback callback;
|
|
44
|
+
@end
|
|
45
|
+
|
|
46
|
+
@implementation FTJSLongTaskDisplayLinkTarget
|
|
47
|
+
- (void)displayLinkDidFire:(CADisplayLink *)displayLink {
|
|
48
|
+
self.callback(displayLink.timestamp);
|
|
49
|
+
}
|
|
50
|
+
@end
|
|
51
|
+
|
|
52
|
+
@interface FTCADisplayLinkScheduler : NSObject <FTJSLongTaskFrameScheduler>
|
|
53
|
+
@property (nonatomic, copy) FTJSLongTaskFrameCallback callback;
|
|
54
|
+
@property (nonatomic, strong, nullable) CADisplayLink *displayLink;
|
|
55
|
+
- (instancetype)initWithCallback:(FTJSLongTaskFrameCallback)callback;
|
|
56
|
+
@end
|
|
57
|
+
|
|
58
|
+
@implementation FTCADisplayLinkScheduler
|
|
59
|
+
- (instancetype)initWithCallback:(FTJSLongTaskFrameCallback)callback {
|
|
60
|
+
self = [super init];
|
|
61
|
+
if (self) {
|
|
62
|
+
_callback = [callback copy];
|
|
63
|
+
}
|
|
64
|
+
return self;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
- (void)start {
|
|
68
|
+
[self stop];
|
|
69
|
+
FTJSLongTaskDisplayLinkTarget *target = [FTJSLongTaskDisplayLinkTarget new];
|
|
70
|
+
target.callback = self.callback;
|
|
71
|
+
self.displayLink = [CADisplayLink displayLinkWithTarget:target selector:@selector(displayLinkDidFire:)];
|
|
72
|
+
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
- (void)stop {
|
|
76
|
+
// CADisplayLink.invalidate is thread safe and releases its run loop and target
|
|
77
|
+
// references without requiring a live JS queue.
|
|
78
|
+
[self.displayLink invalidate];
|
|
79
|
+
self.displayLink = nil;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
- (void)dealloc {
|
|
83
|
+
[_displayLink invalidate];
|
|
84
|
+
}
|
|
85
|
+
@end
|
|
86
|
+
|
|
87
|
+
@interface FTCADisplayLinkSchedulerFactory : NSObject <FTJSLongTaskFrameSchedulerFactory>
|
|
88
|
+
@end
|
|
89
|
+
|
|
90
|
+
@implementation FTCADisplayLinkSchedulerFactory
|
|
91
|
+
- (id<FTJSLongTaskFrameScheduler>)createSchedulerWithCallback:(FTJSLongTaskFrameCallback)callback {
|
|
92
|
+
return [[FTCADisplayLinkScheduler alloc] initWithCallback:callback];
|
|
93
|
+
}
|
|
94
|
+
@end
|
|
95
|
+
|
|
96
|
+
@interface FTNativeLongTaskReporter : NSObject <FTJSLongTaskReporter>
|
|
97
|
+
@end
|
|
98
|
+
|
|
99
|
+
@implementation FTNativeLongTaskReporter
|
|
100
|
+
- (void)reportLongTaskWithDurationNanoseconds:(int64_t)durationNanoseconds property:(NSDictionary *)property {
|
|
101
|
+
[[FTExternalDataManager sharedManager]
|
|
102
|
+
addLongTaskWithStack:@""
|
|
103
|
+
duration:@(durationNanoseconds)
|
|
104
|
+
property:property];
|
|
105
|
+
}
|
|
106
|
+
@end
|
|
107
|
+
|
|
108
|
+
@interface FTJSLongTaskMonitor ()
|
|
109
|
+
@property (nonatomic, strong) id<FTJSLongTaskQueue> queue;
|
|
110
|
+
@property (nonatomic, strong) id<FTJSLongTaskFrameSchedulerFactory> schedulerFactory;
|
|
111
|
+
@property (nonatomic, strong) id<FTJSLongTaskReporter> reporter;
|
|
112
|
+
@property (nonatomic, strong) NSObject *stateLock;
|
|
113
|
+
@property (nonatomic, assign) NSTimeInterval thresholdSeconds;
|
|
114
|
+
@property (nonatomic, assign) NSUInteger generation;
|
|
115
|
+
@property (nonatomic, assign) BOOL requestedRunning;
|
|
116
|
+
@property (nonatomic, strong, nullable) id<FTJSLongTaskFrameScheduler> scheduler;
|
|
117
|
+
@property (nonatomic, assign) NSUInteger activeGeneration;
|
|
118
|
+
@property (nonatomic, assign) CFTimeInterval lastFrameTimestamp;
|
|
119
|
+
@property (atomic, copy) NSDictionary *bridgeContext;
|
|
120
|
+
@end
|
|
121
|
+
|
|
122
|
+
@implementation FTJSLongTaskMonitor
|
|
123
|
+
|
|
124
|
+
+ (instancetype)monitorWithBridge:(RCTBridge *)bridge {
|
|
125
|
+
return [[self alloc]
|
|
126
|
+
initWithQueue:[[FTReactBridgeJSQueue alloc] initWithBridge:bridge]
|
|
127
|
+
schedulerFactory:[FTCADisplayLinkSchedulerFactory new]
|
|
128
|
+
reporter:[FTNativeLongTaskReporter new]];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
- (instancetype)initWithQueue:(id<FTJSLongTaskQueue>)queue
|
|
132
|
+
schedulerFactory:(id<FTJSLongTaskFrameSchedulerFactory>)schedulerFactory
|
|
133
|
+
reporter:(id<FTJSLongTaskReporter>)reporter {
|
|
134
|
+
self = [super init];
|
|
135
|
+
if (self) {
|
|
136
|
+
_queue = queue;
|
|
137
|
+
_schedulerFactory = schedulerFactory;
|
|
138
|
+
_reporter = reporter;
|
|
139
|
+
_stateLock = [NSObject new];
|
|
140
|
+
_bridgeContext = @{};
|
|
141
|
+
}
|
|
142
|
+
return self;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
- (void)setThresholdMilliseconds:(double)thresholdMilliseconds {
|
|
146
|
+
@synchronized (self.stateLock) {
|
|
147
|
+
self.thresholdSeconds = thresholdMilliseconds <= 0 ? 0 : thresholdMilliseconds / 1000.0;
|
|
148
|
+
if (thresholdMilliseconds <= 0) {
|
|
149
|
+
[self stopLocked];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
- (void)start {
|
|
155
|
+
NSUInteger startGeneration;
|
|
156
|
+
@synchronized (self.stateLock) {
|
|
157
|
+
if (self.thresholdSeconds == 0) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
self.requestedRunning = YES;
|
|
161
|
+
startGeneration = ++self.generation;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
__weak typeof(self) weakSelf = self;
|
|
165
|
+
BOOL dispatched = [self.queue dispatchBlock:^{
|
|
166
|
+
// A pending block must not keep a destroyed monitor (and its queue) alive.
|
|
167
|
+
typeof(self) strongSelf = weakSelf;
|
|
168
|
+
if (strongSelf == nil) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
@synchronized (strongSelf.stateLock) {
|
|
172
|
+
if (strongSelf.generation != startGeneration || !strongSelf.requestedRunning) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
[strongSelf.scheduler stop];
|
|
176
|
+
strongSelf.scheduler = [strongSelf.schedulerFactory createSchedulerWithCallback:^(CFTimeInterval timestamp) {
|
|
177
|
+
[weakSelf handleFrameTimestamp:timestamp generation:startGeneration];
|
|
178
|
+
}];
|
|
179
|
+
strongSelf.activeGeneration = startGeneration;
|
|
180
|
+
strongSelf.lastFrameTimestamp = 0;
|
|
181
|
+
[strongSelf.scheduler start];
|
|
182
|
+
}
|
|
183
|
+
}];
|
|
184
|
+
if (!dispatched) {
|
|
185
|
+
@synchronized (self.stateLock) {
|
|
186
|
+
if (self.generation == startGeneration) {
|
|
187
|
+
[self stopLocked];
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
- (void)stop {
|
|
194
|
+
[self stopWithCompletion:nil];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
- (void)disableWithCompletion:(dispatch_block_t)completion {
|
|
198
|
+
@synchronized (self.stateLock) {
|
|
199
|
+
self.thresholdSeconds = 0;
|
|
200
|
+
[self stopLocked];
|
|
201
|
+
}
|
|
202
|
+
if (completion != nil) {
|
|
203
|
+
completion();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
- (void)stopWithCompletion:(dispatch_block_t)completion {
|
|
208
|
+
@synchronized (self.stateLock) {
|
|
209
|
+
[self stopLocked];
|
|
210
|
+
}
|
|
211
|
+
if (completion != nil) {
|
|
212
|
+
completion();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Caller holds stateLock, also used by scheduler installation and frame callbacks.
|
|
217
|
+
// Cleanup deliberately never dispatches to RN: an invalid proxy may silently drop it.
|
|
218
|
+
- (void)stopLocked {
|
|
219
|
+
self.requestedRunning = NO;
|
|
220
|
+
self.generation++;
|
|
221
|
+
[self.scheduler stop];
|
|
222
|
+
self.scheduler = nil;
|
|
223
|
+
self.activeGeneration = 0;
|
|
224
|
+
self.lastFrameTimestamp = 0;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
- (void)handleFrameTimestamp:(CFTimeInterval)timestamp generation:(NSUInteger)generation {
|
|
228
|
+
@synchronized (self.stateLock) {
|
|
229
|
+
if (!self.requestedRunning || self.generation != generation ||
|
|
230
|
+
self.activeGeneration != generation || self.scheduler == nil) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (self.lastFrameTimestamp != 0) {
|
|
234
|
+
NSTimeInterval duration = timestamp - self.lastFrameTimestamp;
|
|
235
|
+
if (duration > self.thresholdSeconds) {
|
|
236
|
+
int64_t durationNanoseconds = (int64_t)(duration * FTNanosecondsPerSecond);
|
|
237
|
+
// Capture at detection; later updates must not change an already reported event.
|
|
238
|
+
NSDictionary *property = self.bridgeContext;
|
|
239
|
+
[self.reporter reportLongTaskWithDurationNanoseconds:durationNanoseconds property:property];
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
self.lastFrameTimestamp = timestamp;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
- (void)dealloc {
|
|
247
|
+
[_scheduler stop];
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
@end
|
|
@@ -7,13 +7,15 @@
|
|
|
7
7
|
//
|
|
8
8
|
|
|
9
9
|
#import "FTMobileReactNative.h"
|
|
10
|
+
#import <TrueWatchSDK/FTSDKAgent.h>
|
|
10
11
|
#import <React/RCTConvert.h>
|
|
11
|
-
#import <
|
|
12
|
-
#import <
|
|
13
|
-
#import <
|
|
14
|
-
#import <
|
|
15
|
-
#import <
|
|
16
|
-
#import <
|
|
12
|
+
#import <TrueWatchSDK/FTMobileAgent.h>
|
|
13
|
+
#import <TrueWatchSDK/FTSDKConfig+Private.h>
|
|
14
|
+
#import <TrueWatchSDK/FTThreadDispatchManager.h>
|
|
15
|
+
#import <TrueWatchSDK/FTConstants.h>
|
|
16
|
+
#import <TrueWatchSDK/FTJSONUtil.h>
|
|
17
|
+
#import <TrueWatchSDK/FTRemoteConfigModel+Private.h>
|
|
18
|
+
#import "FTWebSocketMetadataStore.h"
|
|
17
19
|
|
|
18
20
|
static NSString *const FTRemoteConfigCallbackEvent = @"ft_remote_config_callback";
|
|
19
21
|
|
|
@@ -274,12 +276,33 @@ RCT_EXPORT_MODULE()
|
|
|
274
276
|
if ([override.allKeys containsObject:@"logSampleRate"]) {
|
|
275
277
|
model.logSampleRate = @([RCTConvert double:override[@"logSampleRate"]]);
|
|
276
278
|
}
|
|
279
|
+
if ([override.allKeys containsObject:@"sessionSamplingRate"]) {
|
|
280
|
+
model.sessionSamplingRate = @([RCTConvert double:override[@"sessionSamplingRate"]]);
|
|
281
|
+
}
|
|
282
|
+
if ([override.allKeys containsObject:@"sessionOnErrorSamplingRate"]) {
|
|
283
|
+
model.sessionOnErrorSamplingRate = @([RCTConvert double:override[@"sessionOnErrorSamplingRate"]]);
|
|
284
|
+
}
|
|
285
|
+
if ([override.allKeys containsObject:@"traceSamplingRate"]) {
|
|
286
|
+
model.traceSamplingRate = @([RCTConvert double:override[@"traceSamplingRate"]]);
|
|
287
|
+
}
|
|
288
|
+
if ([override.allKeys containsObject:@"logSamplingRate"]) {
|
|
289
|
+
model.logSamplingRate = @([RCTConvert double:override[@"logSamplingRate"]]);
|
|
290
|
+
}
|
|
291
|
+
if ([override.allKeys containsObject:@"sessionReplaySamplingRate"]) {
|
|
292
|
+
model.sessionReplaySamplingRate = @([RCTConvert double:override[@"sessionReplaySamplingRate"]]);
|
|
293
|
+
}
|
|
294
|
+
if ([override.allKeys containsObject:@"sessionReplayOnErrorSamplingRate"]) {
|
|
295
|
+
model.sessionReplayOnErrorSamplingRate = @([RCTConvert double:override[@"sessionReplayOnErrorSamplingRate"]]);
|
|
296
|
+
}
|
|
277
297
|
if ([override.allKeys containsObject:@"logLevelFilters"]) {
|
|
278
298
|
model.logLevelFilters = [RCTConvert NSArray:override[@"logLevelFilters"]];
|
|
279
299
|
}
|
|
280
300
|
if ([override.allKeys containsObject:@"logEnableCustomLog"]) {
|
|
281
301
|
model.logEnableCustomLog = @([RCTConvert double:override[@"logEnableCustomLog"]]);
|
|
282
302
|
}
|
|
303
|
+
if ([override.allKeys containsObject:@"logEnableWebViewLog"] && override[@"logEnableWebViewLog"] != [NSNull null]) {
|
|
304
|
+
model.logEnableWebViewLog = @([RCTConvert BOOL:override[@"logEnableWebViewLog"]]);
|
|
305
|
+
}
|
|
283
306
|
|
|
284
307
|
NSString *ruleId = [RCTConvert NSString:rule[@"id"]];
|
|
285
308
|
[appliedRuleIds addObject:ruleId.length > 0 ? ruleId : [NSString stringWithFormat:@"rule_%lu", (unsigned long)idx]];
|
|
@@ -319,6 +342,12 @@ RCT_REMAP_METHOD(bindRUMUserData,
|
|
|
319
342
|
[self bindRUMUserData:userId userName:userName userEmail:userName extra:extra resolve:resolve reject:reject];
|
|
320
343
|
}
|
|
321
344
|
|
|
345
|
+
RCT_REMAP_METHOD(resetVisitorId,
|
|
346
|
+
resetVisitorIdResolver:(RCTPromiseResolveBlock)resolve
|
|
347
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
348
|
+
[self resetVisitorId:resolve reject:reject];
|
|
349
|
+
}
|
|
350
|
+
|
|
322
351
|
RCT_REMAP_METHOD(unbindRUMUserData,
|
|
323
352
|
unbindRUMUserData_Resolver:(RCTPromiseResolveBlock)resolve
|
|
324
353
|
rejecter:(RCTPromiseRejectBlock)reject
|
|
@@ -373,17 +402,16 @@ RCT_REMAP_METHOD(clearAllData,
|
|
|
373
402
|
#endif
|
|
374
403
|
- (void)sdkConfig:(NSDictionary *)context resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
|
375
404
|
[FTThreadDispatchManager performBlockDispatchMainSyncSafe:^{
|
|
376
|
-
|
|
405
|
+
FTSDKConfig *config;
|
|
377
406
|
NSString *datakitUrl = [RCTConvert NSString:context[@"datakitUrl"]];
|
|
378
407
|
NSString *dataWayUrl = [RCTConvert NSString:context[@"datawayUrl"]];
|
|
379
408
|
NSString *clientToken = [RCTConvert NSString:context[@"clientToken"]];
|
|
380
409
|
if(dataWayUrl && dataWayUrl.length>0 && clientToken && clientToken.length>0){
|
|
381
|
-
config = [[
|
|
410
|
+
config = [[FTSDKConfig alloc]initWithDatawayUrl:dataWayUrl clientToken:clientToken];
|
|
382
411
|
}else if(datakitUrl && datakitUrl.length>0){
|
|
383
|
-
config = [[
|
|
412
|
+
config = [[FTSDKConfig alloc]initWithDatakitUrl:datakitUrl];
|
|
384
413
|
}else{
|
|
385
|
-
|
|
386
|
-
return;
|
|
414
|
+
config = [[FTSDKConfig alloc]init];
|
|
387
415
|
}
|
|
388
416
|
if ([context.allKeys containsObject:@"debug"]) {
|
|
389
417
|
config.enableSDKDebugLog = [RCTConvert BOOL:context[@"debug"]];
|
|
@@ -427,6 +455,9 @@ RCT_REMAP_METHOD(clearAllData,
|
|
|
427
455
|
if ([context.allKeys containsObject:@"dataFilters"]) {
|
|
428
456
|
config.dataFilters = [RCTConvert NSDictionary:context[@"dataFilters"]];
|
|
429
457
|
}
|
|
458
|
+
if ([context.allKeys containsObject:@"allowWebViewHost"]) {
|
|
459
|
+
config.allowWebViewHost = [RCTConvert NSArray:context[@"allowWebViewHost"]];
|
|
460
|
+
}
|
|
430
461
|
if ([context.allKeys containsObject:@"globalContext"]) {
|
|
431
462
|
config.globalContext = [RCTConvert NSDictionary:context[@"globalContext"]];
|
|
432
463
|
}
|
|
@@ -490,6 +521,7 @@ RCT_REMAP_METHOD(clearAllData,
|
|
|
490
521
|
};
|
|
491
522
|
}
|
|
492
523
|
[FTMobileAgent startWithConfigOptions:config];
|
|
524
|
+
[FTWebSocketMetadataStore sdkDidStart];
|
|
493
525
|
resolve(nil);
|
|
494
526
|
}];
|
|
495
527
|
}
|
|
@@ -526,6 +558,11 @@ RCT_REMAP_METHOD(clearAllData,
|
|
|
526
558
|
[[FTMobileAgent sharedInstance] unbindUser];
|
|
527
559
|
resolve(nil);
|
|
528
560
|
}
|
|
561
|
+
- (void)resetVisitorId:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
|
562
|
+
[FTSDKAgent resetVisitorID];
|
|
563
|
+
resolve(nil);
|
|
564
|
+
}
|
|
565
|
+
|
|
529
566
|
- (void)clearAllData:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
|
530
567
|
[FTMobileAgent clearAllData];
|
|
531
568
|
resolve(nil);
|
|
@@ -537,6 +574,7 @@ RCT_REMAP_METHOD(clearAllData,
|
|
|
537
574
|
}
|
|
538
575
|
|
|
539
576
|
- (void)shutDown:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
|
577
|
+
[FTWebSocketMetadataStore shutDown];
|
|
540
578
|
[FTMobileAgent shutDown];
|
|
541
579
|
resolve(nil);
|
|
542
580
|
}
|
|
@@ -553,9 +591,8 @@ RCT_REMAP_METHOD(clearAllData,
|
|
|
553
591
|
|
|
554
592
|
}];
|
|
555
593
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
rejecter:(RCTPromiseRejectBlock)reject){
|
|
594
|
+
RCT_EXPORT_METHOD(updateRemoteConfig:(RCTPromiseResolveBlock)resolve
|
|
595
|
+
reject:(RCTPromiseRejectBlock)reject){
|
|
559
596
|
if (!_remoteConfigurationEnabled) {
|
|
560
597
|
reject(@"E_REMOTE_CONFIG_DISABLED", @"Remote configuration is not enabled.", nil);
|
|
561
598
|
return;
|
|
@@ -580,11 +617,10 @@ RCT_REMAP_METHOD(updateRemoteConfig,
|
|
|
580
617
|
return nil;
|
|
581
618
|
}];
|
|
582
619
|
}
|
|
583
|
-
|
|
584
|
-
interval:(int)interval
|
|
620
|
+
RCT_EXPORT_METHOD(updateRemoteConfigWithMiniUpdateInterval:(double)interval
|
|
585
621
|
rules:(NSArray *)rules
|
|
586
|
-
|
|
587
|
-
|
|
622
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
623
|
+
reject:(RCTPromiseRejectBlock)reject){
|
|
588
624
|
if (!_remoteConfigurationEnabled) {
|
|
589
625
|
reject(@"E_REMOTE_CONFIG_DISABLED", @"Remote configuration is not enabled.", nil);
|
|
590
626
|
return;
|
package/ios/FTReactNativeLog.mm
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
//
|
|
8
8
|
|
|
9
9
|
#import "FTReactNativeLog.h"
|
|
10
|
-
#import <
|
|
10
|
+
#import <TrueWatchSDK/FTMobileAgent.h>
|
|
11
11
|
#import <React/RCTConvert.h>
|
|
12
|
-
#import <
|
|
12
|
+
#import <TrueWatchSDK/FTLogger+Private.h>
|
|
13
13
|
@implementation FTReactNativeLog
|
|
14
14
|
RCT_EXPORT_MODULE()
|
|
15
15
|
|
|
@@ -42,8 +42,13 @@ RCT_REMAP_METHOD(logWithStatusString,
|
|
|
42
42
|
|
|
43
43
|
- (void)logConfig:(NSDictionary *)context resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
|
44
44
|
FTLoggerConfig *logger = [[FTLoggerConfig alloc]init];
|
|
45
|
-
if ([context.allKeys containsObject:@"
|
|
46
|
-
|
|
45
|
+
if ([context.allKeys containsObject:@"logSamplingRate"]) {
|
|
46
|
+
logger.logSamplingRate = [RCTConvert double:context[@"logSamplingRate"]];
|
|
47
|
+
} else if ([context.allKeys containsObject:@"sampleRate"]) {
|
|
48
|
+
logger.logSamplingRate = [RCTConvert double:context[@"sampleRate"]] * 100;
|
|
49
|
+
}
|
|
50
|
+
if ([context.allKeys containsObject:@"enableWebViewLog"]) {
|
|
51
|
+
logger.enableWebViewLog = [RCTConvert BOOL:context[@"enableWebViewLog"]];
|
|
47
52
|
}
|
|
48
53
|
NSArray<NSNumber *>*filters = [RCTConvert NSNumberArray:context[@"logLevelFilters"]];
|
|
49
54
|
if (filters) {
|
|
@@ -76,4 +81,3 @@ RCT_REMAP_METHOD(logWithStatusString,
|
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
@end
|
|
79
|
-
|