53

How can I get Crashlytics to receive a log without my app crashing? I have the following code:

if(!context.managedObjectContext save:&error) {
    CLS_LOG(@"%@",error.description)
}

When an error occurs, I want the Crashlytics server to receive the error but the app should continue running.

I do not need the log right away. I would be happy to get the log on the next restart. I just do not want to have to trigger a crash in my app to receive the log.

Is this possible?

jscs
  • 63,694
  • 13
  • 151
  • 195
jack
  • 1,861
  • 4
  • 31
  • 52
  • You don't. This is not what it's intended it. Try flurry, they allow you to send 'check point' messages. – CW0007007 Jul 25 '14 at 09:48
  • 2
    That would mean I would need to use both flurry and Crashlytics. I do think I have a valid use case. Sometimes the error is serious but doesn't warrant a crash so it would be nice to get the error with crashlytics. but of course you do have a point – jack Jul 25 '14 at 10:00
  • 2
    I use both. Bit of a pain but it's better to use tools are they're intended. At least in my opinion. Rather than 'hacking' them. – CW0007007 Jul 25 '14 at 10:10
  • 1
    Possible duplicate of [Crashlytics iOS - log caught exception](http://stackoverflow.com/questions/23118742/crashlytics-ios-log-caught-exception) – Mike Bonnell Jan 12 '16 at 19:33
  • https://docs.fabric.io/ios/crashlytics/enhanced-reports.html – onmyway133 May 02 '16 at 13:14

10 Answers10

60

With the new update from crashlytics you can now use:

[[FIRCrashlytics crashlytics] recordError:error];

And in Swift:

Crashlytics.crashlytics().record(error: error)

You can check the documentation here.

0x384c0
  • 2,256
  • 1
  • 17
  • 14
Tiago Almeida
  • 14,081
  • 3
  • 67
  • 82
14

Kinda old question, but now you can use Answers which is part of the Fabric suit (Crashlytics is part of Fabric as well):

enter image description here

Fabric can be found here. And further documentation here.

Rui Peres
  • 25,741
  • 9
  • 87
  • 137
  • 3
    This answer is outdated. Tiago Almeida answer is the way to go. – lupidan Feb 25 '16 at 12:44
  • 3
    @Lupi not it's not: https://docs.fabric.io/ios/answers/answers-events.html#custom-event. It's a valid solution. – Rui Peres Feb 25 '16 at 16:02
  • 2
    Answers is more related to Marketing and Big Data, definitely not for error tracking. – lupidan Feb 26 '16 at 15:29
  • 3
    @Lupi: There is a cost to the recordError due to stack unwinding not being optional. Additionally as others have noted, the recordError is only sent on next app launch. In cases such as counting in near real-time number of certain error occurrences, Answers could be a viable & preferred solution as Fabric's documentation outlines under Performance Considerations: https://docs.fabric.io/apple/crashlytics/logged-errors.html#performance-considerations – Nobosi Jul 07 '17 at 18:02
8

I tried the below lines and it works like charm. In try-catch block use the below lines in your catch block

@try {
// line of code here
}
@catch (NSException *exception) {
NSUncaughtExceptionHandler *handler = NSGetUncaughtExceptionHandler();
handler(exception);
}

as explained at http://support.crashlytics.com/knowledgebase/articles/222764-can-i-use-a-custom-exception-handler

[UPDATE]

Now in fabric's crashlytics we can use simple function [Crashlytics recordCustomExceptionName:reason:frameArray:] for sending handled exceptions

@try {
// line of code here
}
@catch (NSException *exception) {
    NSArray *stack = [exception callStackReturnAddresses];
    [[Crashlytics sharedInstance] recordCustomExceptionName: exception.name
                                                 reason: exception.reason
                                             frameArray: stack];
}

as explained at https://twittercommunity.com/t/crashlytics-ios-how-to-send-non-fatal-exceptions-without-app-crash/34592/32

Aanabidden
  • 375
  • 6
  • 18
  • 1
    Swift doens't support exceptions or try/catch for NSExceptions. You can write a class in Objective-C which takes an NSString parameter for the exception name and call it from swift? – plivesey Oct 30 '15 at 16:52
  • You can call NSSetUncaughtExceptionHandler from swift – thibaut noah Oct 23 '17 at 12:47
4

For me the method .recordError() didn't helped, because it don't log the user information. Or i just didn't found where to watch it. Using recordCustomExceptionName fit to me. There is an example of implementation of the both ways:

func logMessage(_ message: String) {
    let userInfo = ["message" : message]
    let error = NSError(domain: "AppErrorDomain", code: 1, userInfo: userInfo)
    Crashlytics.sharedInstance().recordCustomExceptionName("API Error", reason: message, frameArray: [])
    Crashlytics.sharedInstance().recordError(error, withAdditionalUserInfo: userInfo)
}
Nike Kov
  • 12,630
  • 8
  • 75
  • 122
2

Swift 5, Crashlytics SDK 4.0.0-beta.6:

let exceptionModel = ExceptionModel(name: "exception title", reason: "details")
Crashlytics.crashlytics().record(exceptionModel: exceptionModel)

...similar for NSError, with whatever you want to see in the Crashlytics dashboard.

let error = NSError(domain: "error title", code: 0, userInfo: ["message":"some details"])
Crashlytics.crashlytics().record(error: error)
wildcat12
  • 975
  • 6
  • 13
1

iOS log non-fatal exception

official doc

Crashlytics.crashlytics().record(error: error)

Also please take a look at the testing phase. Actually Firebase recommends:

  • don't use debug mode
  • logged error is sent on the next app launch
  • you can use -FIRDebugEnabled in a schema arguments[About] and find Completed report submission in logs to be sure that it is sent
  • wait more then 5 minutes(~1 hour in my case)
  • I could find log in dashboard only from a real device(not simulator)
  • If you used -FIRDebugEnabled you can still see logs after disabling or removing this argument. To fix it use -FIRDebugDisabled argument
yoAlex5
  • 29,217
  • 8
  • 193
  • 205
  • Thanks a lot! This saved me so much time. I was debugging it for the 2 days trying to find out why doesn't it send reports. All I needed to do is relaunch app... – ilyavysotski Aug 17 '23 at 11:15
-3

In reference from Crashlytics documents.

try {
  myMethodThatThrows();
} catch (Exception e) {
  Crashlytics.logException(e);
  // handle your exception here!
}

https://docs.fabric.io/android/crashlytics/caught-exceptions.html?caught%20exceptions#caught-exceptions

Muhammad Aamir Ali
  • 20,419
  • 10
  • 66
  • 57
-4

As far as I know, if you dont protect your code correctly, your application will crash anyway. Crashlylytics, take this crashes and show them to you in a "readable" mode in the web application they have designed. If there is no crash, crashlytics will take anything. You can grab an exception in your code :

@try{
....
}
@catch(NSException ex){...}

in the critical parts, but you should always do that if you are afraid your application is going to crash or you find a potential error which can allow your application have a bad behavior and acting up. You can always force in your exception to send or track this error.

Hope it helps

AlfuryDB
  • 289
  • 1
  • 4
  • 1
    This doesn't even remotely address the OP's question. – Jordan Nov 08 '16 at 16:39
  • Maybe if you read when it was posted and how Crashlytics and the different platforms have evolved, it would have sense. I think is better to see the dates before to vote negative to someone. Thanks – AlfuryDB Nov 09 '16 at 16:24
  • 2
    No, it wouldn't have. OP asked how to get a report for non-fatal errors from Crashlytics, which wasn't an option at the time. Your answer was how to prevent the app from crashing in the first place. Totally unrelated. – Jordan Nov 09 '16 at 18:16
-4

Crashlytics is a crash tracking service, if you need to track custom messages choose other analytics service.

avdyushin
  • 1,906
  • 17
  • 21
-4

The trick is to use the following :

http://support.crashlytics.com/knowledgebase/articles/202805-logging-caught-exceptions

Just use this :

Crashlytics.logException(new Exception("my custom log for crashLytics !!!"));

I use this and I get my non-fatal crash in about 5 minutes !

Tobliug
  • 2,992
  • 30
  • 28