Skip to content

Commit

Permalink
Send logs and keys are they are set
Browse files Browse the repository at this point in the history
  • Loading branch information
axel-op committed Jul 4, 2020
1 parent 1ae9cab commit 1b8cdb9
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 59 deletions.
1 change: 1 addition & 0 deletions packages/firebase_crashlytics/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* `getVersion`
* `isDebuggable`
* **Breaking change**: the methods `setInt`, `setDouble`, `setString` and `setBool` have been replaced by `setCustomKey`.
* Logs and keys are sent to Crashlytics as they're set.
* Fixes a bug that prevented keys from being set on iOS devices.

## 0.1.4+1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,6 @@ public static void registerWith(Registrar registrar) {
public void onMethodCall(MethodCall call, Result result) {
final FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
if (call.method.equals("Crashlytics#onError")) {
// Add logs.
final List<String> logs = call.argument("logs");
for (String l : logs) {
crashlytics.log(l);
}

// Set keys.
final Map<String, Object> keys = call.argument("keys");
for (String key : keys.keySet()) {
crashlytics.setCustomKey(key, (String) keys.get(key));
}

// Report crash.
final String dartExceptionMessage = (String) call.argument("exception");
final Exception exception = new Exception(dartExceptionMessage);
Expand Down Expand Up @@ -93,6 +81,15 @@ public void onMethodCall(MethodCall call, Result result) {
} else if (call.method.equals("Crashlytics#setUserIdentifier")) {
crashlytics.setUserId((String) call.argument("identifier"));
result.success(null);
} else if (call.method.equals("Crashlytics#setKey")) {
final String key = (String) call.argument("key");
final String value = (String) call.argument("value");
crashlytics.setCustomKey(key, value);
result.success(null);
} else if (call.method.equals("Crashlytics#log")) {
final String msg = (String) call.argument("log");
crashlytics.log(msg);
result.success(null);
} else {
result.notImplemented();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,6 @@ - (instancetype)init {

- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
if ([@"Crashlytics#onError" isEqualToString:call.method]) {
// Add logs.
NSArray *logs = call.arguments[@"logs"];
for (NSString *log in logs) {
[[FIRCrashlytics crashlytics] logWithFormat:@"%@", log];
}

// Set keys.
NSDictionary *keys = call.arguments[@"keys"];
for (NSString *key in keys) {
[[FIRCrashlytics crashlytics] setCustomValue:keys[key] forKey:key];
}

// Add additional information from the Flutter framework to the exception reported in
// Crashlytics.
NSString *information = call.arguments[@"information"];
Expand Down Expand Up @@ -78,6 +66,15 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
} else if ([@"Crashlytics#setUserIdentifier" isEqualToString:call.method]) {
[[FIRCrashlytics crashlytics] setUserID:call.arguments[@"identifier"]];
result(nil);
} else if ([@"Crashlytics#setKey" isEqualToString:call.method]) {
NSString *key = call.arguments[@"key"];
NSString *value = call.arguments[@"value"];
[[FIRCrashlytics crashlytics] setCustomValue:value forKey:key];
result(nil);
} else if ([@"Crashlytics#log" isEqualToString:call.method]) {
NSString *msg = call.arguments[@"log"];
[[FIRCrashlytics crashlytics] logWithFormat:@"%@", msg];
result(nil);
} else {
result(FlutterMethodNotImplemented);
}
Expand Down
62 changes: 27 additions & 35 deletions packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,7 @@ class Crashlytics {
/// default this is false.
var enableInDevMode = false;

/// Keys to be included with report.
final _keys = <String, String>{};

/// Logs to be included with report.
final _logs = ListQueue<String>(15);
var _logSize = 0;
bool get _shouldReport => !kDebugMode || enableInDevMode;

@visibleForTesting
static const MethodChannel channel =
Expand All @@ -43,41 +38,44 @@ class Crashlytics {
/// Submits a report of a non-fatal error.
///
/// For errors generated by the Flutter framework, use [recordFlutterError] instead.
Future<void> recordError(dynamic exception, StackTrace stack,
{dynamic context}) async {
Future<void> recordError(
dynamic exception,
StackTrace stack, {
dynamic context,
}) async {
print('Error caught by Crashlytics plugin <recordError>:');

_recordError(exception, stack, context: context);
}

void crash() {
throw StateError('Error thrown by Crashlytics plugin');
}

/// Add text logging that will be sent with your next report. `msg` will be
/// printed to the console when in debug mode. Each report has a rolling max
/// of 64k of logs, older logs are removed to allow newer logs to fit within
/// the limit.
void log(String msg) {
_logSize += Uint8List.fromList(msg.codeUnits).length;
_logs.add(msg);
// Remove oldest log till logSize is no more than 64K.
while (_logSize > 65536) {
final String first = _logs.removeFirst();
_logSize -= Uint8List.fromList(first.codeUnits).length;
}
/// Add text logging that will be sent to Crashlytics.
Future<void> log(String msg) async {
if (!_shouldReport) return;
ArgumentError.checkNotNull(msg, 'msg');
return channel.invokeMethod<void>(
'Crashlytics#log',
<String, dynamic>{'log': msg},
);
}

/// Sets a [value] to be associated with a given [key] for your crash data.
///
/// The [value] will be converted to a string by calling [toString] on it.
/// An error will be thrown if it is null.
void setCustomKey(String key, dynamic value) {
Future<void> setCustomKey(String key, dynamic value) async {
if (!_shouldReport) return;
ArgumentError.checkNotNull(key, 'key');
ArgumentError.checkNotNull(value, 'value');
// Check that only 64 keys are set.
if (_keys.containsKey(key) || _keys.length <= 64) {
_keys[key] = value.toString();
}
return channel.invokeMethod<void>(
'Crashlytics#setKey',
<String, dynamic>{
'key': key,
'value': value.toString(),
},
);
}

/// Specify a user identifier which will be visible in the Crashlytics UI.
Expand Down Expand Up @@ -142,12 +140,7 @@ class Crashlytics {
Iterable<DiagnosticsNode> information,
bool printDetails,
}) async {
bool inDebugMode = false;
if (!enableInDevMode) {
assert(inDebugMode = true);
}

printDetails ??= inDebugMode;
printDetails ??= kDebugMode;

final String _information = (information == null || information.isEmpty)
? ''
Expand All @@ -168,7 +161,8 @@ class Crashlytics {
// that Flutter developers are used to seeing.
if (stack != null) print('\n$stack');
}
if (!inDebugMode || enableInDevMode) {

if (_shouldReport) {
// The stack trace can be null. To avoid the following exception:
// Invalid argument(s): Cannot create a Trace from null.
// We can check for null and provide an empty stack trace.
Expand All @@ -190,8 +184,6 @@ class Crashlytics {
'context': '$context',
'information': _information,
'stackTraceElements': stackTraceElements,
'logs': _logs.toList(),
'keys': _keys,
});

// Print result.
Expand Down

0 comments on commit 1b8cdb9

Please sign in to comment.