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

Add API to retrieve Android scope data #2814

Merged
merged 10 commits into from Jul 18, 2023
Merged

Add API to retrieve Android scope data #2814

merged 10 commits into from Jul 18, 2023

Conversation

markushi
Copy link
Member

@markushi markushi commented Jul 3, 2023

📜 Description

Fixes #2808

More discussion on this one: getsentry/team-mobile#11

💡 Motivation and Context

Enable pulling scope data via InternalSentrySdk.serializeScope(scope: Scope) : Map<String, Any>

In order to not re-implement all our protocol serialization logic again, I extracted some interfaces to abstract away the underlying mechanism (Classic JsonObjectWriter + new MapObjectWriter).

I tried to keep the changes to a minimum, but there are still a few rough edges:

  • The ObjectWriter interface methods all throw IOExceptions because the underlying Gson impl does it
  • A few @SuppressWarnings("unchecked") in MapObjectWriter due to the dynamic nature of Map<String, Any>
  • Some *ObjectWriter.serialize Date/TimeZone/Collection code is duplicate

💚 How did you test it?

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

#skip-changelog

@github-actions
Copy link
Contributor

github-actions bot commented Jul 3, 2023

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 5f44d96

To better reflect how cocoa works and have a more central API for hybrid
SDKs
@github-actions
Copy link
Contributor

github-actions bot commented Jul 5, 2023

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 278.74 ms 370.67 ms 91.93 ms
Size 1.72 MiB 2.29 MiB 574.43 KiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
9246ed4 275.63 ms 321.31 ms 45.69 ms
f274c79 334.86 ms 348.54 ms 13.68 ms
c03a05e 390.40 ms 419.35 ms 28.94 ms
9246ed4 281.79 ms 352.08 ms 70.29 ms
8820c5c 330.60 ms 416.86 ms 86.26 ms
adf8fe3 300.49 ms 357.36 ms 56.87 ms
0310da5 381.20 ms 404.50 ms 23.30 ms
dc67004 273.86 ms 346.37 ms 72.51 ms
496bdfd 272.86 ms 407.33 ms 134.48 ms
caf50ec 302.36 ms 325.25 ms 22.89 ms

App size

Revision Plain With Sentry Diff
9246ed4 1.72 MiB 2.28 MiB 572.22 KiB
f274c79 1.72 MiB 2.29 MiB 575.01 KiB
c03a05e 1.72 MiB 2.29 MiB 574.43 KiB
9246ed4 1.72 MiB 2.28 MiB 572.22 KiB
8820c5c 1.72 MiB 2.28 MiB 571.82 KiB
adf8fe3 1.72 MiB 2.29 MiB 575.24 KiB
0310da5 1.72 MiB 2.28 MiB 573.45 KiB
dc67004 1.72 MiB 2.28 MiB 573.45 KiB
496bdfd 1.72 MiB 2.28 MiB 571.82 KiB
caf50ec 1.72 MiB 2.29 MiB 575.24 KiB

Previous results on branch: feat/hybrid-scope-sync

Startup times

Revision Plain With Sentry Diff
7954f77 292.20 ms 362.88 ms 70.68 ms
cce67e0 282.84 ms 331.51 ms 48.67 ms
6524670 298.71 ms 317.40 ms 18.69 ms
d307d12 264.82 ms 340.51 ms 75.69 ms
59444c6 294.98 ms 360.68 ms 65.70 ms
b6de74f 351.85 ms 364.75 ms 12.90 ms

App size

Revision Plain With Sentry Diff
7954f77 1.72 MiB 2.29 MiB 574.99 KiB
cce67e0 1.72 MiB 2.29 MiB 574.30 KiB
6524670 1.72 MiB 2.29 MiB 574.59 KiB
d307d12 1.72 MiB 2.29 MiB 574.99 KiB
59444c6 1.72 MiB 2.29 MiB 574.59 KiB
b6de74f 1.72 MiB 2.29 MiB 574.59 KiB

@codecov
Copy link

codecov bot commented Jul 5, 2023

Codecov Report

Patch coverage: 84.02% and project coverage change: +0.15 🎉

Comparison is base (dc67004) 81.15% compared to head (2860fa1) 81.30%.

❗ Current head 2860fa1 differs from pull request most recent head 5f44d96. Consider uploading reports for the commit 5f44d96 to get more accurate results

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #2814      +/-   ##
============================================
+ Coverage     81.15%   81.30%   +0.15%     
- Complexity     4501     4615     +114     
============================================
  Files           348      352       +4     
  Lines         16685    17013     +328     
  Branches       2268     2298      +30     
============================================
+ Hits          13540    13832     +292     
- Misses         2198     2233      +35     
- Partials        947      948       +1     
Impacted Files Coverage Δ
sentry/src/main/java/io/sentry/Breadcrumb.java 85.04% <ø> (ø)
.../src/main/java/io/sentry/JsonObjectSerializer.java 84.21% <ø> (ø)
...ry/src/main/java/io/sentry/ProfilingTraceData.java 78.51% <ø> (ø)
.../main/java/io/sentry/ProfilingTransactionData.java 52.52% <ø> (ø)
...entry/src/main/java/io/sentry/SentryBaseEvent.java 90.90% <ø> (ø)
.../src/main/java/io/sentry/SentryEnvelopeHeader.java 96.92% <ø> (ø)
.../main/java/io/sentry/SentryEnvelopeItemHeader.java 87.95% <ø> (ø)
sentry/src/main/java/io/sentry/SentryEvent.java 89.36% <ø> (ø)
sentry/src/main/java/io/sentry/SentryItemType.java 87.50% <ø> (ø)
sentry/src/main/java/io/sentry/SentryLevel.java 100.00% <ø> (ø)
... and 43 more

... and 29 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@krystofwoldrich
Copy link
Member

RN implementation using the serializer is here getsentry/sentry-react-native#3170.

I've noticed there is very little data returned from the Android scope, only Breadcrumbs and items synced from RN to Android are present (redux state and routing navigation tag).

{
  "breadcrumbs": [
    {
      "category": "app.lifecycle",
      "level": "info",
      "timestamp": "2023-07-10T07:11:12.875Z",
      "type": "session",
      "data": {
        "state": "start"
      }
    }
  ],
  "contexts": {
    "state": {
      "state": {
        "value": {
          "counter": 0
        },
        "type": "redux"
      }
    }
  },
  "fingerprint": [],
  "user": null,
  "extras": {},
  "tags": {
    "routing.route.name": "Home"
  },
  "level": null
}

@marandaneto
Copy link
Contributor

@krystofwoldrich there's a lot of data missing, InternalSentrySdk.serializeScope is just one part of the data you need.
For example, all the data set on DefaultAndroidEventProcessor, MainEventProcessor, etc, and every data that is set when captureEvent is captured should be returned as well.
I don't think that InternalSentrySdk.serializeScope is a good naming as well since we need more data than just the scope's data.

@krystofwoldrich
Copy link
Member

@marandaneto Yes, I agree,

I think something like InternalSentrySdk.getEventScope, InternalSentrySdk.getFullScope, or InternalSentrySdk.getAndroidScope would make sense.

@markushi markushi marked this pull request as ready for review July 11, 2023 06:07
}

return sideLoadedInfo;
return new SideLoadedInfo(installerPackageName == null, installerPackageName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can put the check inside the constructor, so that you can pass only one parameter

@krystofwoldrich
Copy link
Member

I tested the latest version with RN and I'm getting all data as before the change. 👍🚀

@stefanosiano
Copy link
Member

just few comments, but looks good overall.
I'll have another look to confirm.
As a side note, for the next time, may you try to split all your changes across separate PRs? That would make it easier and faster to review.

Copy link
Member

@stefanosiano stefanosiano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@markushi markushi merged commit beba014 into main Jul 18, 2023
19 checks passed
@markushi markushi deleted the feat/hybrid-scope-sync branch July 18, 2023 04:53
@Nullable
public static Scope getCurrentScope() {
final @NotNull AtomicReference<Scope> scopeRef = new AtomicReference<>();
HubAdapter.getInstance().withScope(scopeRef::set);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@markushi See

// don't ref. to method reference, theres a bug on it
// noinspection Convert2MethodRef

This has an issue with some specific use cases, please avoid method references.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also check if the source code has any more references to ::.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this is a problem? I see more than 50 occurrences in our code. Most of them are backend-related, but there are also some which do get executed on Android devices (e.g. JsonObjectDeserializer)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I've written that comment myself, its a problem on Android only during desugaring, mainly because of older AGP versions (Hi RN and Flutter).
If there are more on Android code, they should be removed, that's why this comment #2814 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@markushi can you raise a new issue for replacing all :: references that run on Android code?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 created an issue here, #2848

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following this logic, we should also get rid of all default methods in interfaces, because this is also part of the desugaring. We use those quite heavily. The fact, that nobody has reported any problems so far kinda confirms that there's noone of our customers on AGP lower than 3.0. Is still worth considering this limitation?
image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@romtsn no, we decided and use Java 8 features, the min. version of AGP isn't a problem here, the method reference was a bug on the AGP desugaring and not "not supported" if not version >= X.
If default has a bug in one of the AGP versions that are above the min. required, then yes, we'd get rid of default methods for compatibility, which is not the case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, what was the version where the bug has been fixed? If it's 3.0.1 I'd say we are still good to not consider it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't recall, but why do we even bother if we can keep 100% compatibility by having just a few chars more? () -> {}

@@ -6,18 +6,85 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public final class JsonObjectWriter extends JsonWriter {
public final class JsonObjectWriter implements ObjectWriter {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is public and not annotated as internal, technically a breaking change, was that intentional?
What's the motivation for the renaming?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a required change in order to serialize protocol classes to either Json or Map<>. IMHO it's an oversight that this class is not marked as apistatus.internal. If we consider this a breaking change we should talk to Karl/Krystof as this PR is blocking the RN profiling feature.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree its an oversight, but the class/interface was used in pretty much every class of the protocol.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Nullable
public static Scope getCurrentScope() {
final @NotNull AtomicReference<Scope> scopeRef = new AtomicReference<>();
HubAdapter.getInstance().withScope(scopeRef::set);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, withScope has side effects and isn't intended to be used on Android, since it's a single hub/scope.
It's being even removed from a few SDKs in favor of the scope lambda -> captureException(scope {})
This might have side effects, I know @romtsn dislikes this API and already had issues with it as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional, as it returns a safe copy of the current scope. I already talked to Roman about this, this is probably the only good use-case for using withScope 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

H: withScope isn't thread-safe because it's meant to run in a single thread.
Android is single hub/scope.
If another thread set something on the scope while the push has been executed but not the pop yet, the data is set in the wrong scope, IMO this is still a bug, and withScope should never be used in Android.
This API was a mistake and is already deprecated in a few SDKs as mentioned, in favor of the scope lambda.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@markushi this is marked as resolved but it's not AFAIK.
the usage of withScope is still there, mind sharing a commit link or PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this PR solved that, but looking closer at the code the withScope is used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Provide APIs to retrieve scope data for Hybrid SDKs
6 participants