-
Notifications
You must be signed in to change notification settings - Fork 9.7k
[firebase_crashlytics]Firebase Crashlytics plugin #1080
Conversation
|
||
### iOS Integration | ||
|
||
Add the Crachlytics run scripts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Crashlytics
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks fixed.
...a/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing this!
Setup `Crashlytics`: | ||
```dart | ||
void main() { | ||
// Set reportInDevMode to true to see reports while in debug mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would put backticks around reportInDevMode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
void main() { | ||
// Set reportInDevMode to true to see reports while in debug mode | ||
// This is only to be used for confirming that reports are being | ||
// submitted as expected. It is not intended to be used in production. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would change "It is not intended to be used in production" to "It is not intended to be used for everyday development."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
void main() { | ||
// Set reportInDevMode to true to see reports while in debug mode | ||
// This is only to be used for confirming that reports are being | ||
// submitted as expected. It should not intended to be used in production. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same feedback here, the "not intended to be used in production" comment confused me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
import 'package:firebase_crashlytics/firebase_crashlytics.dart'; | ||
|
||
void main() { | ||
// Set reportInDevMode to true to see reports while in debug mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Backticks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
class Crashlytics { | ||
static final Crashlytics instance = Crashlytics(); | ||
|
||
/// Set to true to have Errors sent to Crashlytics while in debug mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't capitalize errors. I would clarify that you mean Flutter debug mode. You might also say that it defaults to false.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
static final Crashlytics instance = Crashlytics(); | ||
|
||
/// Set to true to have Errors sent to Crashlytics while in debug mode. | ||
bool reportInDevMode = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would call it enableInDebugMode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
throw StateError('Error thrown by Crashlytics plugin'); | ||
} | ||
|
||
Future<bool> isDebuggable() async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs dartdoc. Clarify that this means debuggability of the OEM parts of the app, not the Flutter app.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used doc from Android, but will have to dig a bit deeper to get more info on what this means in both a Android and iOS context.
/// Logs to be included with report. | ||
@visibleForTesting | ||
final ListQueue<String> logs = ListQueue<String>(15); | ||
int logSize = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is private and should have an underscore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
/// Logs to be included with report. | ||
@visibleForTesting | ||
final ListQueue<String> logs = ListQueue<String>(15); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is private and should have an underscore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this has an underscore how will I use it in tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not part of the public API, it's an implementation detail and shouldn't be used in tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
I got a bit eager waiting for this to get merged, so I migrating a project from
|
Consider updating |
} | ||
} | ||
|
||
void setBool(String key, bool value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setInt
, setBool
& setDouble
are purely convenience methods on native SDKs (iOS/Android) and internally the SDK's convert these to a string value.
Perhaps it would be better to simplify this and have a singular method in Dart that accepts a bool
, double
, int
or String
value and this method converts to a String in dart and calls only one native method (setString
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Salakar thanks for the feedback. We are trying to keep the plugins interface as close to the native ones as possible. So we will stick with the separate methods for now.
setKey(key, value); | ||
} | ||
|
||
void setDouble(String key, double value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setInt
, setBool
& setDouble
are purely convenience methods on native SDKs (iOS/Android) and internally the SDK's convert these to a string value.
Perhaps it would be better to simplify this and have a singular method in Dart that accepts a bool
, double
, int
or String
value and this method converts to a String in dart and calls only one native method (setString
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Salakar thanks for the feedback. We are trying to keep the plugins interface as close to the native ones as possible. So we will stick with the separate methods for now.
setKey(key, value); | ||
} | ||
|
||
void setInt(String key, int value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setInt
, setBool
& setDouble
are purely convenience methods on native SDKs (iOS/Android) and internally the SDK's convert these to a string value.
Perhaps it would be better to simplify this and have a singular method in Dart that accepts a bool
, double
, int
or String
value and this method converts to a String in dart and calls only one native method (setString
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Salakar thanks for the feedback. We are trying to keep the plugins interface as close to the native ones as possible. So we will stick with the separate methods for now.
} | ||
|
||
void crash() { | ||
throw StateError('Error thrown by Crashlytics plugin'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this not delegate to the native SDK methods to ensure a full fatal crash (app terminates) as Crashlytics only submits reports after a termination and subsequent app startup - wouldn't the Dart/Flutter error handler capture this in debug/dev and thus preventing this termination behaviour?
iOS: [[Crashlytics sharedInstance] crash];
Android: (new CrashTest()).crashAsyncTask(50);
(crash off main thread to avoid being captured by error handlers in dev/debug)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Salakar This was considered, however most Flutter level crashes don't result in the underlying native application crashing, so throwing an error here was an attempt to represent the types of crashes likely to happen an a Flutter app and how the report will ultimately be submitted to Crashlytics.
|
||
dependencies { | ||
implementation 'com.google.firebase:firebase-core:16.0.6' | ||
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No Crashlytics NDK support to capture low-level errors such as in Flutter Engine?
Dependency: implementation 'com.crashlytics.sdk.android:crashlytics-ndk:2.0.5'
Users build.gradle
(documentation step only):
crashlytics {
enableNdk true
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like that should be separate dependency
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Salakar thanks for the suggestion, we can definitely add this in a future version.
@hpoul thanks for the feedback:
|
Cirrus is all green, PR has stale CI status. See finished builds here: |
Make sure to call FirebaseApp.initializeApp(Context) first. | ||
``` | ||
|
||
*Note:* When you are debugging on android, use a device or AVD with Google Play services. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: capitalize Android
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
} | ||
|
||
void setKey(String key, dynamic value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still needs dartdocs
|
||
/// Logs to be included with report. | ||
@visibleForTesting | ||
final ListQueue<String> logs = ListQueue<String>(15); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not part of the public API, it's an implementation detail and shouldn't be used in tests.
// TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. | ||
// https://github.com/flutter/flutter/issues/26431 | ||
// ignore: strong_mode_implicit_dynamic_method | ||
await channel.invokeMethod('Crashlytics#log', <String, dynamic>{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a lot of unnecessary async waiting, especially if you have big logs. Can we send everything to the native side as an array argument to onError and log it there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed since logs are sent as part of error reporting.
// TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. | ||
// https://github.com/flutter/flutter/issues/26431 | ||
// ignore: strong_mode_implicit_dynamic_method | ||
await channel.invokeMethod('Crashlytics#setInt', crashlyticsKey); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be a bit more concise to send over the params map and switch on the type of the data on the native side, so that you're defining fewer MethodCall invocations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
0b1189b
to
e3f8209
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor style nit, lgtm otherwise
return result; | ||
} | ||
|
||
/// Returns the Kit Version. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be clearer to say Crashlytics SDK version instead of Kit version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
crashlytics.log('foo'); | ||
await crashlytics.onError(details); | ||
expect(log[0].method, 'Crashlytics#onError'); | ||
expect(log[0].arguments['exception'], 'foo exception'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be more readable and consistent with other tests to write this as a single expect comparing log with an array of maps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds like StackTrace.current might make it hard to use the isMethodCall matcher, in which case this is fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After chat with @collinjackson we will leave this as is, since Stacktrace.current
will likely not be the same on each execution.
4da42b1
to
a2ec4a4
Compare
* Add Crashlytics support
Add plugin to FlutterFire that will report Dart side errors as non-fatal errors to the Firebase console.
Fixes: flutter/flutter#14765