KSCrash is a powerful crash reporting library with a lot of extended features such as on-device symbolication. It offers an extensible plugin-like architecture to integrate with your favorite issue tracking platform, based on what KSCrash calls
sinks. A sink is kind of a
push endpoint for crash reports generated by KSCrash. In addition, KSCrash can be configured with no sink to automatically catch and store crash reports; KSCrash offers a set of APIs to query and retrieve stored crash reports.
JIRA Mobile Connect is a free, open-source library for collecting user feedback directly from your mobile app to JIRA issue tracking platform. It offers automated crash reporting using
PLCrashReporter wich is, in my opinion, a bit outdated and falls short in features.
If you are an iOS developer using JIRA and want to ease and improve your automated crash reporting system, integrating JMC with KSCrash will save you lots of headaches and pain.
Push or pull
You can use KSCrash using push or pull crash report extraction. Using push, KSCrash is initialized using a sink that will be called when reports are available. Using pull, KSCrash is initialized with no sink, and some other code should query it to retrieve and process reports.
If you are not interested in any JMC feature apart from crash reporting, you can use push architecture writing a KSCrash sink that uses JMCCrashTransport class to send crashes to JIRA, but it's a bit tricky since JMCCrashTransport is not designed to be used directly and it has dependencies upon top level library classes such as JMC.
JMC uses a pull architecture for crash report extraction from PLCrashReporter. Thankfully, there's only one single point of integration between JMC and PLCrashReporter: the CrashReporter class. CrashReporter is a singleton that offers the following interface:
- (BOOL) hasPendingCrashReport;
- (NSArray*) crashReports;
- (void) cleanCrashReports;
Writing a new implementation of CrashReporter is easy, since KSCrash offers direct implementations of all three services. But KSCrash reports are returned in NSDictionary format and JMC expects you to return an array of NSStrings, so some processing should be taken to write the human readable report.
- (void)cleanCrashReports
{
[[KSCrash instance] deleteAllReports];
}
-(BOOL)hasPendingCrashReport{
return [[KSCrash instance] reportCount]>0;
}
In addition to sinks, KSCrash offers filters for report processing. Filters take an array of reports, process them and output them; usually yo configure a filter chain, where a filter takes input from another filter output, with a sink at the endpoint. But filters can be used on their own to do any sort of report processing, and KSCrash comes with a set of predefined filters. One of these filters transforms NSDictionary reports to NSString reports mimicking Apple's crash report format: KSCRashReportFilterAppleFmt.
- (NSArray *)crashReports
{
KSCrashReportFilterAppleFmt *appleFormatFilter = [KSCrashReportFilterAppleFmt filterWithReportStyle:KSAppleReportStyleSymbolicated];
__block NSArray *result=nil;
/*
WARNING: this code works since KSCrashReportFilterAppleFmt works synchronously. Using an asynchronous filter will result in undefined behaviour.
To use async filters, make sure this method (crashReports) is not called on main thread and use GCD semaphores
*/
[appleFormatFilter filterReports:[[KSCrash instance] allReports] onCompletion:^(NSArray *filteredReports, BOOL completed, NSError *error) {
result=filteredReports;
}];
return result;
}
Note the warning. Filters take a completion block but there is no default behavior on how or when will the block be executed. The Apple format filter executes the block synchronously, but other filters/sinks may execute it asynchronously. To make it work with asynchronous filters you should use GCD semaphores and queues and make sure your code does not execute in the main thread since the semaphore could block it; you should never block the main thread, and even if you are thinking about it just forget: the filter/sink may use the main thread and you would be causing a deadlock.
ARC notes:
- KSCrash source files are ARC agnostic, it can be compiled using ARC or non-ARC
- JMC source files are non-ARC
- My CrashReport class code is ARC
So remember to set the appropriate -fno-objc-arc or -fobjc-arc flags as needed depending on your project global settings.
You can get the code for CrashReport class from a bitbucket
repository.