Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement crashedLastRun #4014

Merged
merged 9 commits into from
Aug 26, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Features

- Add `Sentry.crashedLastRun()` ([#4014](https://github.com/getsentry/sentry-react-native/pull/4014))
- `TimeToInitialDisplay` and `TimeToFullDisplay` start the time to display spans on mount ([#4020](https://github.com/getsentry/sentry-react-native/pull/4020))

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,10 @@ public String fetchNativePackageName() {
return packageInfo.packageName;
}

public void crashedLastRun(Promise promise) {
promise.resolve(Sentry.isCrashedLastRun());
}

private void setEventOriginTag(SentryEvent event) {
SdkVersion sdk = event.getSdk();
if (sdk != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,9 @@ public void captureReplay(boolean isHardCrash, Promise promise) {
public String getCurrentReplayId() {
return this.impl.getCurrentReplayId();
}

@Override
public void crashedLastRun(Promise promise) {
this.impl.crashedLastRun(promise);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,9 @@ public void captureReplay(boolean isHardCrash, Promise promise) {
public String getCurrentReplayId() {
return this.impl.getCurrentReplayId();
}

@ReactMethod
public void crashedLastRun(Promise promise) {
this.impl.crashedLastRun(promise);
}
}
6 changes: 6 additions & 0 deletions ios/RNSentry.mm
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,12 @@ - (NSDictionary*) fetchNativeStackFramesBy: (NSArray<NSNumber*>*)instructionsAdd
#endif
}

RCT_EXPORT_METHOD(crashedLastRun:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
resolve(@([SentrySDK crashedLastRun]));
}

// Thanks to this guard, we won't compile this code when we build for the old architecture.
#ifdef RCT_NEW_ARCH_ENABLED
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
Expand Down
7 changes: 7 additions & 0 deletions samples/react-native/src/Screens/ErrorsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ const ErrorsScreen = (_props: Props) => {
Sentry.nativeCrash();
}}
/>
<Button
title="Get Crashed Last Run"
onPress={async () => {
const crashed = await Sentry.crashedLastRun();
console.log('Crashed last run:', crashed);
}}
/>
<Button
title="Set Scope Properties"
onPress={() => {
Expand Down
1 change: 1 addition & 0 deletions src/js/NativeRNSentry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface Spec extends TurboModule {
initNativeReactNavigationNewFrameTracking(): Promise<void>;
captureReplay(isHardCrash: boolean): Promise<string | undefined | null>;
getCurrentReplayId(): string | undefined | null;
crashedLastRun(): Promise<boolean | null>;
krystofwoldrich marked this conversation as resolved.
Show resolved Hide resolved
}

export type NativeStackFrame = {
Expand Down
7 changes: 7 additions & 0 deletions src/js/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ export class ReactNativeClient extends BaseClient<ReactNativeClientOptions> {
this._initNativeSdk();
}

/**
* Returns if the app crashed in the last run.
*/
public crashedLastRun(): Promise<boolean | null> {
return NATIVE.crashedLastRun();
}

/**
* Sets up the integrations
*/
Expand Down
1 change: 1 addition & 0 deletions src/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export {
captureUserFeedback,
withScope,
configureScope,
crashedLastRun,
} from './sdk';
export { TouchEventBoundary, withTouchEventBoundary } from './touchevents';

Expand Down
11 changes: 11 additions & 0 deletions src/js/sdk.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,14 @@ export function configureScope(callback: (scope: Scope) => void): ReturnType<Hub
};
getCurrentHub().configureScope(safeCallback);
}

/**
* Returns if the app crashed in the last run.
*/
export async function crashedLastRun(): Promise<boolean | null> {
const client = getCurrentHub().getClient<ReactNativeClient>();
if (client) {
return client.crashedLastRun();
}
return null;
}
13 changes: 13 additions & 0 deletions src/js/wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ interface SentryNativeWrapper {

captureReplay(isHardCrash: boolean): Promise<string | null>;
getCurrentReplayId(): string | null;

crashedLastRun(): Promise<boolean | null>;
}

const EOL = utf8ToBytes('\n');
Expand Down Expand Up @@ -642,6 +644,17 @@ export const NATIVE: SentryNativeWrapper = {
return RNSentry.getCurrentReplayId() || null;
},

async crashedLastRun(): Promise<boolean | null> {
if (!this.enableNative) {
return null;
}
if (!this._isModuleLoaded(RNSentry)) {
return null;
}

return RNSentry.crashedLastRun();
krystofwoldrich marked this conversation as resolved.
Show resolved Hide resolved
},

/**
* Gets the event from envelopeItem and applies the level filter to the selected event.
* @param data An envelope item containing the event.
Expand Down
Loading