Skip to content

Conversation

@ueman
Copy link
Collaborator

@ueman ueman commented Feb 13, 2021

📜 Description

This PR migrates the Dart part of this Sentry SDK to null safety.

Some notes:

  • Darts migrate tool is really helpful
  • mockito makes a lot of problems with non-nullable fields. It's basically useless for them.
  • Some tests failed because mockito can't handle non-nullable fields. They were rewritten
  • Some mocks were written manually. They're kinda inspired by the bloc library tests for nullsafety
  • CI builds with Dart & Flutter beta
  • dynamic can hold null values by default, even without a ?
  • https://dart.dev/null-safety/migration-guide

A lot of test were touched so they should be reviewed carefully.
Most of the user facing APIs accept null values. However events, messages or exceptions are getting dropped if they are null.
So the question is should the API allow null values? I would guess so because it makes the API a little bit more user friendly but I'm kinda torn on that. For now null values are allowed.

💡 Motivation and Context

#247

💚 How did you test it?

  • Tests are passing
  • Manual tests with Dart example
  • Manual tests with Flutter example

📝 Checklist

  • I reviewed submitted code
  • I added tests to verify changes
  • I updated the docs if needed
  • All tests passing
  • No breaking changes

🔮 Next steps

  • Migrate the Sentry Flutter SDK to nullsafety
  • Version number should be changed because this is a breaking change
  • Decide how mocks should be written in the future
  • Re-enable CI on stable once Dart and Flutter releases their null safe versions.

@codecov-io
Copy link

codecov-io commented Feb 14, 2021

Codecov Report

Merging #298 (44a8206) into main (2497fe8) will decrease coverage by 5.54%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #298      +/-   ##
==========================================
- Coverage   86.52%   80.97%   -5.55%     
==========================================
  Files          52        5      -47     
  Lines        1751      226    -1525     
==========================================
- Hits         1515      183    -1332     
+ Misses        236       43     -193     
Impacted Files Coverage Δ
flutter/lib/src/sentry_flutter_options.dart 58.69% <100.00%> (ø)
dart/lib/src/throwable_mechanism.dart
dart/lib/src/platform_checker.dart
dart/lib/src/transport/encode.dart
dart/lib/src/version.dart
dart/lib/src/diagnostic_logger.dart
dart/lib/src/transport/noop_transport.dart
dart/lib/src/protocol/sentry_level.dart
dart/lib/src/utils.dart
dart/lib/src/integration.dart
... and 1 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 2497fe8...44a8206. Read the comment docs.

class Message {
/// The fully formatted message. If missing, Sentry will try to interpolate the message.
final String formatted;
final String? formatted;
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would leave it as optional because it gets filled from nullable fields, such as SentryClient.captureMessage(...) and the message could be null.

Copy link
Contributor

Choose a reason for hiding this comment

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

SentryClient.captureMessage(null) should not raise an event at all, it's not going to be useful.
if we create a Message without a formatted field, it'll cause a backend error during ingestion.

Copy link
Contributor

Choose a reason for hiding this comment

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

just reforcing this, captureMessage(String?) is fine, but we'll bail out before creating a Message, so formatted should be non nulable to not generate a backend error

Copy link
Member

@bruno-garcia bruno-garcia Feb 23, 2021

Choose a reason for hiding this comment

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

I think captureMessage shouldn't take null

The code can gracefully handle a null (programming error) but the annotation should be that a message is required.

For all the public API when we need to value to do something meaningful

Copy link
Contributor

Choose a reason for hiding this comment

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

this would give a lot of boilerplate or force an error on the users code, think about?

final str = getthisfromApi();
// str is nullable
Sentry.captureMessage(str!); // could cause an error on app's code.

// doing this would be annoying
if (str != null) {
Sentry.captureMessage(str!);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

as a Message is created only after capturing, hence the field formatted should not be nullable

@ueman
Copy link
Collaborator Author

ueman commented Feb 22, 2021

sometimes we are not using const for [] or {}, is there a reason or must forgot about them?

const [] makes the list immutable, so there's no way to add anything.

2nd is sometimes we're copying the reference when mutating the event, previously not, is there a reason?

Yep, I've added the explanation to your review. But for all other which don't want to search:
Because the passed instance is non-nullable but because of the processing it can now be nullable. Thus we need to declare a new variable which is nullable.

@marandaneto
Copy link
Contributor

sometimes we are not using const for [] or {}, is there a reason or must forgot about them?

const [] makes the list immutable, so there's no way to add anything.

2nd is sometimes we're copying the reference when mutating the event, previously not, is there a reason?

Yep, I've added the explanation to your review. But for all other which don't want to search:
Because the passed instance is non-nullable but because of the processing it can now be nullable. Thus we need to declare a new variable which is nullable.

got it, thanks, hard to get these things during code review if not trying out :)

@marandaneto marandaneto changed the base branch from main to feat/null-safety February 22, 2021 15:31
@marandaneto
Copy link
Contributor

@ueman I've created the feat/null-safety branch and now we have a few conflicts because of a bug fix :(
after working on them, we could merge and cut a release :)

…/nullsafety

# Conflicts:
#	dart/lib/src/hub.dart
#	dart/lib/src/hub_adapter.dart
#	dart/lib/src/noop_hub.dart
#	dart/lib/src/noop_sentry_client.dart
#	dart/lib/src/sentry_client.dart
#	dart/test/hub_test.dart
#	dart/test/sentry_client_test.dart
String formatted,
String template,
List<dynamic> params,
String? formatted,
Copy link
Contributor

Choose a reason for hiding this comment

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

sentry: ">=4.0.0 <5.0.0"
package_info: ^0.4.0
# this should point to pub
sentry: ^4.0.5
Copy link
Contributor

Choose a reason for hiding this comment

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

would not be better to keep between compatible versions?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It has to be changed anyway before you release this even if I change it to ">=4.0.0 <5.0.0". As Sentry should probably be 5.0.0-prerelease.0 and at that time there is no sentry with a 5.0.0 release. There's also no reason to release a sentry_flutter because it's not null safe yet.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Or am I overlooking something?

Copy link
Contributor

Choose a reason for hiding this comment

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

we can discuss versioning in another PR, lets merge it, my question was more about, why changing from >= ... < to ^...

@ueman
Copy link
Collaborator Author

ueman commented Feb 23, 2021

We're now at a point where the discussion is more about the API and if it should take nulls or not than the underlying null safety changes. Does it make sense to merge this and do these changes yourself? I'm not quite sure I am the right person to decide on it 😅

@bruno-garcia
Copy link
Member

Sounds good to me but it's up to @marandaneto.
I didn't review the PR though just added a comment.

@marandaneto
Copy link
Contributor

there are only 3 comments open 2 of them are the same, about Message.formatted that should not be nullable.
the other one is a question, after that, LGTM

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.

@ueman thanks a lot for this, a lot of back and forth but its also a change in the whole code base so yeah.
happy to merge :)

@marandaneto marandaneto merged commit 423d367 into getsentry:feat/null-safety Feb 24, 2021
@ueman
Copy link
Collaborator Author

ueman commented Feb 24, 2021

Also thanks alot for the review.

@marandaneto marandaneto mentioned this pull request Mar 6, 2021
7 tasks
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