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

sync Java to C #937

Merged
merged 17 commits into from
Sep 28, 2020
Merged

sync Java to C #937

merged 17 commits into from
Sep 28, 2020

Conversation

bruno-garcia
Copy link
Member

@bruno-garcia bruno-garcia commented Sep 22, 2020

PoC Java -> native scope sync

TODO:

  • Write tests
  • Measure perf
  • Add the other scope data

So far:

Crumbs:
image

user:
image

Tags:

image

@bruno-garcia bruno-garcia marked this pull request as draft September 22, 2020 01:18
Copy link
Member

@Swatinem Swatinem left a comment

Choose a reason for hiding this comment

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

I bet this is only the beginning and you will add a lot more hooks?


import io.sentry.protocol.User;

public interface IScopeObserver {
Copy link
Contributor

Choose a reason for hiding this comment

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

M: we'd need to implement the other fields too, like extra, fingerprint... and also to remove them, like removeTag...

Copy link
Member Author

Choose a reason for hiding this comment

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

The customer only asked about user,tag and breadcrumbs but yeah, for completion we'd have to add a bunch more stuff

Copy link
Contributor

Choose a reason for hiding this comment

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

or to document pretty well what we sync and what we don't, I'm fine either way.

Copy link
Member Author

Choose a reason for hiding this comment

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

Could be an option. Specially if it'll require lots of JNI calls to sync stuff.

Copy link
Contributor

Choose a reason for hiding this comment

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

tags start with the min. necessary to unblock folks and see how it goes, we can implement the others later then.
starting with tags, extras, user, and breadcrumbs.

…eObserver.java

Co-authored-by: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com>
}

// TODO: make this a method
if (data) {
Copy link
Contributor

Choose a reason for hiding this comment

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

@Swatinem do you know an easier way to do this? from Map<String, Object> on java to sentry-native?

Copy link
Member

Choose a reason for hiding this comment

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

damn, I have no idea. But if you put this into a method, you can at least goto fail and have a few finalizers (those DeleteLocalRef) there. That should at least take care of the nesting.

Those jclass/jmethodID things can probably be done someplace else and cached inside a struct. I hope the pointers returned from there are stable across GC?

I can imagine something like:

struct {
jclass map;
jmethodID map_entrySet;
jclass set;
jmethodID set_iterator;
…
}

Also, why do you need entrySet, can’t you get an iterator from Map directly?

Copy link
Contributor

Choose a reason for hiding this comment

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

for the last question, no, https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#entrySet--

the suggestions above really make sense, I will experiment with just parsing the map as a String, let's see how it goes, last case I'd do this way, thanks

}
const char* valueStr = (*env)->GetStringUTFChars(env, value, NULL);
if (!valueStr) { // Out of memory
(*env)->ReleaseStringUTFChars(env, key, keyStr);
Copy link
Member

Choose a reason for hiding this comment

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

We never called this for any of the other cases. should we?

Copy link
Contributor

Choose a reason for hiding this comment

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

it'd not be a bad idea, but those values are set by us and quite small Strs length, here could be arbitrary data set by customers like a full JSON response, that's why it's so important, good catch.

}

// TODO: make this a method
if (data) {
Copy link
Member

Choose a reason for hiding this comment

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

damn, I have no idea. But if you put this into a method, you can at least goto fail and have a few finalizers (those DeleteLocalRef) there. That should at least take care of the nesting.

Those jclass/jmethodID things can probably be done someplace else and cached inside a struct. I hope the pointers returned from there are stable across GC?

I can imagine something like:

struct {
jclass map;
jmethodID map_entrySet;
jclass set;
jmethodID set_iterator;
…
}

Also, why do you need entrySet, can’t you get an iterator from Map directly?

@@ -11,8 +11,257 @@ struct transport_options {

struct transport_options g_transport_options;

JNIEXPORT void JNICALL
Copy link
Contributor

Choose a reason for hiding this comment

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

we don't need to check NPEs here, because on Java the thread-safe list dont accept null keys and values

@@ -25,27 +274,35 @@ static void send_envelope(sentry_envelope_t *envelope, void *unused_data) {
sentry_envelope_write_to_file(envelope, outbox_path);
}

JNIEXPORT void JNICALL Java_io_sentry_android_ndk_SentryNdk_initSentryNative(JNIEnv *env, jclass cls, jobject sentry_sdk_options) {
JNIEXPORT void JNICALL
Java_io_sentry_android_ndk_SentryNdk_initSentryNative(JNIEnv *env, jclass cls,
Copy link
Contributor

Choose a reason for hiding this comment

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

just indentation, ignore it

private final @NotNull List<IScopeObserver> observers = new ArrayList<>();

/** Enable the Java -> NDK Scope sync */
private boolean enableScopeSync;
Copy link
Contributor

Choose a reason for hiding this comment

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

opt-in by default

Copy link
Member Author

@bruno-garcia bruno-garcia left a comment

Choose a reason for hiding this comment

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

:shipit:?

@bruno-garcia bruno-garcia marked this pull request as ready for review September 25, 2020 13:50
@codecov-commenter
Copy link

codecov-commenter commented Sep 25, 2020

Codecov Report

❗ No coverage uploaded for pull request base (main@77ee2aa). Click here to learn what that means.
The diff coverage is 97.05%.

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #937   +/-   ##
=======================================
  Coverage        ?   71.23%           
  Complexity      ?     1245           
=======================================
  Files           ?      126           
  Lines           ?     4575           
  Branches        ?      472           
=======================================
  Hits            ?     3259           
  Misses          ?     1067           
  Partials        ?      249           
Impacted Files Coverage Δ Complexity Δ
sentry/src/main/java/io/sentry/Breadcrumb.java 93.18% <ø> (ø) 19.00 <0.00> (?)
sentry/src/main/java/io/sentry/NoOpSerializer.java 44.44% <0.00%> (ø) 4.00 <0.00> (?)
sentry/src/main/java/io/sentry/GsonSerializer.java 100.00% <100.00%> (ø) 12.00 <1.00> (?)
sentry/src/main/java/io/sentry/Scope.java 91.66% <100.00%> (ø) 52.00 <0.00> (?)
sentry/src/main/java/io/sentry/SentryOptions.java 78.88% <100.00%> (ø) 79.00 <4.00> (?)
...y/src/main/java/io/sentry/protocol/DebugImage.java 3.33% <0.00%> (ø) 1.00% <0.00%> (?%)
...src/main/java/io/sentry/SentryExecutorService.java 100.00% <0.00%> (ø) 6.00% <0.00%> (?%)
...rc/main/java/io/sentry/SentryExceptionFactory.java 92.68% <0.00%> (ø) 8.00% <0.00%> (?%)
...ry/src/main/java/io/sentry/protocol/Mechanism.java 37.93% <0.00%> (ø) 6.00% <0.00%> (?%)
...c/main/java/io/sentry/transport/NoOpTransport.java 40.00% <0.00%> (ø) 2.00% <0.00%> (?%)
... and 121 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 77ee2aa...1c685e6. Read the comment docs.

@marandaneto marandaneto requested a review from a team September 28, 2020 08:52
Comment on lines +128 to +132
// we create an object because the Java layer parses it as a Map
sentry_value_t dataObject = sentry_value_new_object();
sentry_value_set_by_key(dataObject, "data", sentry_value_new_string(charData));

sentry_value_set_by_key(crumb, "data", dataObject);
Copy link
Contributor

Choose a reason for hiding this comment

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

this could be improved if we expose something like sentry_value_from_json
cc @Swatinem

Copy link
Contributor

@marandaneto marandaneto left a comment

Choose a reason for hiding this comment

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

I approve myself!

@bruno-garcia bruno-garcia merged commit a87e484 into main Sep 28, 2020
@bruno-garcia bruno-garcia deleted the feat/java-native-scope-sync branch September 28, 2020 12:21
@bruno-garcia
Copy link
Member Author

Thanks for building this @marandaneto !!:rocket:

*/
@Override
public String serialize(final @NotNull Map<String, Object> data) throws Exception {
Objects.requireNonNull(data, "The SentryEnvelope object is required.");
Copy link
Member

Choose a reason for hiding this comment

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

I guess the exception needs better wording :-D

if (data) {
const char *charData = (*env)->GetStringUTFChars(env, data, 0);

// we create an object because the Java layer parses it as a Map
Copy link
Member

Choose a reason for hiding this comment

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

hm, was that there already? I don’t see it in this PR

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

Successfully merging this pull request may close these issues.

4 participants