|
12 | 12 | import androidx.annotation.Nullable; |
13 | 13 | import androidx.core.app.FrameMetricsAggregator; |
14 | 14 |
|
| 15 | +import com.facebook.hermes.instrumentation.HermesSamplingProfiler; |
15 | 16 | import com.facebook.react.bridge.Arguments; |
16 | 17 | import com.facebook.react.bridge.Promise; |
17 | 18 | import com.facebook.react.bridge.ReactApplicationContext; |
|
25 | 26 | import com.facebook.react.bridge.WritableNativeMap; |
26 | 27 |
|
27 | 28 | import java.io.BufferedInputStream; |
| 29 | +import java.io.BufferedReader; |
28 | 30 | import java.io.File; |
29 | 31 | import java.io.FileNotFoundException; |
30 | 32 | import java.io.FileOutputStream; |
| 33 | +import java.io.FileReader; |
31 | 34 | import java.io.InputStream; |
32 | 35 | import java.nio.charset.Charset; |
33 | 36 | import java.util.HashMap; |
@@ -79,6 +82,7 @@ public class RNSentryModuleImpl { |
79 | 82 | private final PackageInfo packageInfo; |
80 | 83 | private FrameMetricsAggregator frameMetricsAggregator = null; |
81 | 84 | private boolean androidXAvailable; |
| 85 | + private boolean debugEnabled = false; |
82 | 86 |
|
83 | 87 | private static boolean didFetchAppStart; |
84 | 88 |
|
@@ -118,6 +122,7 @@ public void initNativeSdk(final ReadableMap rnOptions, Promise promise) { |
118 | 122 |
|
119 | 123 | if (rnOptions.hasKey("debug") && rnOptions.getBoolean("debug")) { |
120 | 124 | options.setDebug(true); |
| 125 | + this.debugEnabled = true; |
121 | 126 | } |
122 | 127 | if (rnOptions.hasKey("dsn") && rnOptions.getString("dsn") != null) { |
123 | 128 | String dsn = rnOptions.getString("dsn"); |
@@ -616,6 +621,48 @@ public void disableNativeFramesTracking() { |
616 | 621 | } |
617 | 622 | } |
618 | 623 |
|
| 624 | + public WritableMap startProfiling() { |
| 625 | + final WritableMap result = new WritableNativeMap(); |
| 626 | + try { |
| 627 | + HermesSamplingProfiler.enable(); |
| 628 | + result.putBoolean("started", true); |
| 629 | + } catch (Throwable e) { |
| 630 | + result.putBoolean("started", false); |
| 631 | + result.putString("error", e.toString()); |
| 632 | + } |
| 633 | + return result; |
| 634 | + } |
| 635 | + |
| 636 | + public WritableMap stopProfiling() { |
| 637 | + final WritableMap result = new WritableNativeMap(); |
| 638 | + try { |
| 639 | + HermesSamplingProfiler.disable(); |
| 640 | + |
| 641 | + final File output = File.createTempFile( |
| 642 | + "sampling-profiler-trace", ".cpuprofile", reactApplicationContext.getCacheDir()); |
| 643 | + |
| 644 | + if (this.debugEnabled) { |
| 645 | + logger.log(SentryLevel.INFO, "Profile saved to: " + output.getAbsolutePath()); |
| 646 | + } |
| 647 | + |
| 648 | + try (final BufferedReader br = new BufferedReader(new FileReader(output));) { |
| 649 | + HermesSamplingProfiler.dumpSampledTraceToFile(output.getPath()); |
| 650 | + |
| 651 | + final StringBuilder text = new StringBuilder(); |
| 652 | + String line; |
| 653 | + while ((line = br.readLine()) != null) { |
| 654 | + text.append(line); |
| 655 | + text.append('\n'); |
| 656 | + } |
| 657 | + |
| 658 | + result.putString("profile", text.toString()); |
| 659 | + } |
| 660 | + } catch (Throwable e) { |
| 661 | + result.putString("error", e.toString()); |
| 662 | + } |
| 663 | + return result; |
| 664 | + } |
| 665 | + |
619 | 666 | private void setEventOriginTag(SentryEvent event) { |
620 | 667 | SdkVersion sdk = event.getSdk(); |
621 | 668 | if (sdk != null) { |
|
0 commit comments