Skip to content

Commit 5ba6409

Browse files
Merge dc9ca95 into fd21b24
2 parents fd21b24 + dc9ca95 commit 5ba6409

File tree

15 files changed

+473
-4
lines changed

15 files changed

+473
-4
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Fixes
6+
7+
- Enhanced accuracy of time-to-display spans. ([#4042](https://github.com/getsentry/sentry-react-native/pull/4042))
8+
39
## 5.33.1
410

511
### Internal

android/src/main/java/io/sentry/react/RNSentryModuleImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,13 @@ public class RNSentryModuleImpl {
135135
/** Max trace file size in bytes. */
136136
private long maxTraceFileSize = 5 * 1024 * 1024;
137137

138+
private final RNSentryTimeToDisplay timeToDisplay;
139+
138140
public RNSentryModuleImpl(ReactApplicationContext reactApplicationContext) {
139141
packageInfo = getPackageInfo(reactApplicationContext);
140142
this.reactApplicationContext = reactApplicationContext;
141143
this.emitNewFrameEvent = createEmitNewFrameEvent();
144+
this.timeToDisplay = new RNSentryTimeToDisplay();
142145
}
143146

144147
private ReactApplicationContext getReactApplicationContext() {
@@ -693,6 +696,10 @@ public void disableNativeFramesTracking() {
693696
}
694697
}
695698

699+
public void getNewScreenTimeToDisplay(Promise promise) {
700+
timeToDisplay.GetTimeToDisplay(promise);
701+
}
702+
696703
private String getProfilingTracesDirPath() {
697704
if (cacheDirPath == null) {
698705
cacheDirPath = new File(getReactApplicationContext().getCacheDir(), "sentry/react").getAbsolutePath();

android/src/main/java/io/sentry/react/RNSentryPackage.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,4 @@ public List<ViewManager> createViewManagers(
5555
new RNSentryOnDrawReporterManager(reactContext)
5656
);
5757
}
58-
5958
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.sentry.react;
2+
3+
import com.facebook.react.bridge.Promise;
4+
5+
import android.view.Choreographer;
6+
7+
import androidx.annotation.NonNull;
8+
9+
import org.jetbrains.annotations.NotNull;
10+
import io.sentry.SentryDate;
11+
import io.sentry.SentryDateProvider;
12+
import io.sentry.android.core.SentryAndroidDateProvider;
13+
14+
public class RNSentryTimeToDisplay {
15+
16+
public void GetTimeToDisplay(Promise promise) {
17+
Choreographer choreographer = Choreographer.getInstance();
18+
19+
// Invoke the callback after the frame is rendered
20+
choreographer.postFrameCallback(frameTimeNanos -> {
21+
final @NotNull SentryDateProvider dateProvider = new SentryAndroidDateProvider();
22+
23+
final SentryDate endDate = dateProvider.now();
24+
25+
promise.resolve(endDate.nanoTimestamp() / 1e9);
26+
});
27+
}
28+
}

android/src/newarch/java/io/sentry/react/RNSentryModule.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,9 @@ public String getCurrentReplayId() {
173173
public void crashedLastRun(Promise promise) {
174174
this.impl.crashedLastRun(promise);
175175
}
176+
177+
@Override
178+
public void getNewScreenTimeToDisplay(Promise promise) {
179+
this.impl.getNewScreenTimeToDisplay(promise);
180+
}
176181
}

android/src/oldarch/java/io/sentry/react/RNSentryModule.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,9 @@ public String getCurrentReplayId() {
173173
public void crashedLastRun(Promise promise) {
174174
this.impl.crashedLastRun(promise);
175175
}
176+
177+
@ReactMethod()
178+
public void getNewScreenTimeToDisplay(Promise promise) {
179+
this.impl.getNewScreenTimeToDisplay(promise);
180+
}
176181
}

ios/RNSentry.mm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#import <dlfcn.h>
22
#import "RNSentry.h"
3+
#import "RNSentryTimeToDisplay.h"
34

45
#if __has_include(<React/RCTConvert.h>)
56
#import <React/RCTConvert.h>
@@ -62,6 +63,7 @@ + (void)storeEnvelope:(SentryEnvelope *)envelope;
6263
@implementation RNSentry {
6364
bool sentHybridSdkDidBecomeActive;
6465
bool hasListeners;
66+
RNSentryTimeToDisplay *_timeToDisplay;
6567
}
6668

6769
- (dispatch_queue_t)methodQueue
@@ -106,6 +108,8 @@ + (BOOL)requiresMainQueueSetup {
106108
sentHybridSdkDidBecomeActive = true;
107109
}
108110

111+
_timeToDisplay = [[RNSentryTimeToDisplay alloc] init];
112+
109113
#if SENTRY_TARGET_REPLAY_SUPPORTED
110114
[RNSentryReplay postInit];
111115
#endif
@@ -776,4 +780,9 @@ - (NSDictionary*) fetchNativeStackFramesBy: (NSArray<NSNumber*>*)instructionsAdd
776780
}
777781
#endif
778782

783+
RCT_EXPORT_METHOD(getNewScreenTimeToDisplay:(RCTPromiseResolveBlock)resolve
784+
rejecter:(RCTPromiseRejectBlock)reject) {
785+
[_timeToDisplay getTimeToDisplay:resolve];
786+
}
787+
779788
@end

ios/RNSentryTimeToDisplay.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#import <React/RCTBridgeModule.h>
2+
3+
@interface RNSentryTimeToDisplay : NSObject
4+
5+
- (void)getTimeToDisplay:(RCTResponseSenderBlock)callback;
6+
7+
@end

ios/RNSentryTimeToDisplay.m

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#import "RNSentryTimeToDisplay.h"
2+
#import <QuartzCore/QuartzCore.h>
3+
#import <React/RCTLog.h>
4+
5+
@implementation RNSentryTimeToDisplay
6+
{
7+
CADisplayLink *displayLink;
8+
RCTResponseSenderBlock resolveBlock;
9+
}
10+
11+
// Rename requestAnimationFrame to getTimeToDisplay
12+
- (void)getTimeToDisplay:(RCTResponseSenderBlock)callback
13+
{
14+
// Store the resolve block to use in the callback.
15+
resolveBlock = callback;
16+
17+
#if TARGET_OS_IOS
18+
// Create and add a display link to get the callback after the screen is rendered.
19+
displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
20+
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
21+
#else
22+
resolveBlock(@[]); // Return nothing if not iOS.
23+
#endif
24+
}
25+
26+
#if TARGET_OS_IOS
27+
- (void)handleDisplayLink:(CADisplayLink *)link {
28+
// Get the current time
29+
NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970] * 1000.0; // Convert to milliseconds
30+
31+
// Ensure the callback is valid and pass the current time back
32+
if (resolveBlock) {
33+
resolveBlock(@[@(currentTime)]); // Call the callback with the current time
34+
resolveBlock = nil; // Clear the block after it's called
35+
}
36+
37+
// Invalidate the display link to stop future callbacks
38+
[displayLink invalidate];
39+
displayLink = nil;
40+
}
41+
#endif
42+
43+
@end

src/js/NativeRNSentry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ import type { UnsafeObject } from './utils/rnlibrariesinterface';
99
export interface Spec extends TurboModule {
1010
addListener: (eventType: string) => void;
1111
removeListeners: (id: number) => void;
12+
getNewScreenTimeToDisplay(): Promise<number | undefined | null>;
1213
addBreadcrumb(breadcrumb: UnsafeObject): void;
1314
captureEnvelope(
1415
bytes: string,
1516
options: {
1617
hardCrashed: boolean;
1718
},
1819
): Promise<boolean>;
20+
1921
captureScreenshot(): Promise<NativeScreenshot[] | undefined | null>;
2022
clearBreadcrumbs(): void;
2123
crash(): void;

0 commit comments

Comments
 (0)