Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reorganized the workspace structure a bit. All example apps are in a separate Example-Apps project. Added two more example projects that cover the most common use cases. More unit tests. Better documentation. Updated example reports. Memory introspection is now controllable. You can disable it for certain classes, or disable it entirely. Minor bug fixes.
- Loading branch information
Showing
168 changed files
with
20,580 additions
and
25,500 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
KSCrash Architecture | ||
==================== | ||
|
||
KSCrash is implemented as a layered architecture. Each layer can in theory be | ||
compiled without the layers adjacent or above. | ||
|
||
+-------------------------------------------------------------+ | ||
| Installation | | ||
| +----------------------------------------------------+ | ||
| | KSCrash | | ||
| +--------------------------------------------------------+ | ||
| | Crash Reporting | Crash Recording | Crash Report Store | | ||
+----+-----------------+-----------------+--------------------+ | ||
| Filters | Sentry | | ||
+----------------------+-----------------+ | ||
|
||
|
||
### Installation | ||
|
||
This top level layer provides a "clean" interface to the crash system. | ||
It is expected that the API at this level will be largely idiomatic to | ||
the backend system it will be communicating with. | ||
|
||
Primary entry points: KSCrashInstallation.h, KSCrashInstallationXYZ.h | ||
|
||
|
||
### KSCrash | ||
|
||
Handles high level configuration and installation of the crash recording and | ||
crash reporting systems. | ||
|
||
Primary entry point: KSCrash.h | ||
|
||
|
||
### Crash Report Store | ||
|
||
Provides storage and retrieval of crash reports and other configuration data. | ||
Also provides file paths for more primitive access by other layers. | ||
|
||
Primary entry point: KSCrashReportStore.h | ||
|
||
|
||
### Crash Recording | ||
|
||
Records a single crash event. This layer is implemented in async-safe C. | ||
|
||
Primary entry point: KSCrashC.h | ||
|
||
|
||
### Crash Reporting | ||
|
||
Processes, transforms, and sends reports to a remote system. | ||
|
||
Primary entry point: KSCrash.h | ||
|
||
|
||
### Sentry | ||
|
||
Traps application errors and passes control to a supplied function. | ||
It handles the following errors: | ||
|
||
* Mach Exception | ||
* Signal | ||
* NSException | ||
* Main Thread Deadlock | ||
|
||
Primary entry point: KSCrashSentry.h | ||
|
||
|
||
### Filters | ||
|
||
Low level interface for transforming, processing, and sending crash reports. | ||
|
||
Primary entry points: KSCrashReportFilter.h, KSCrashReportFilterXYZ.h |
This file was deleted.
Oops, something went wrong.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// | ||
// Prefix header for all source files of the 'Advanced-Example' target in the 'Advanced-Example' project | ||
// | ||
|
||
#import <Availability.h> | ||
|
||
#ifndef __IPHONE_5_0 | ||
#warning "This project uses features only available in iOS SDK 5.0 and later." | ||
#endif | ||
|
||
#ifdef __OBJC__ | ||
#import <UIKit/UIKit.h> | ||
#import <Foundation/Foundation.h> | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// | ||
// AppDelegate.h | ||
// Advanced-Example | ||
// | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
@class KSCrashInstallation; | ||
|
||
@interface AppDelegate : UIResponder <UIApplicationDelegate> | ||
|
||
@property (strong, nonatomic) UIWindow* window; | ||
@property (strong, nonatomic) KSCrashInstallation* crashInstallation; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// | ||
// AppDelegate.m | ||
// Advanced-Example | ||
// | ||
|
||
#import "AppDelegate.h" | ||
|
||
#import <KSCrash/KSCrashInstallationStandard.h> | ||
#import <KSCrash/KSCrashInstallationQuincyHockey.h> | ||
#import <KSCrash/KSCrashInstallationEmail.h> | ||
#import <KSCrash/KSCrash.h> | ||
#import <KSCrash/KSCrashAdvanced.h> | ||
|
||
|
||
/* More advanced crash reporting example. | ||
* | ||
* This example creates an installation (standard, email, quincy, or hockey), | ||
* but defers showing the main VC until crash reporting has completed. | ||
* | ||
* This mitigates issues where the app crashes during initialization (in which | ||
* case you'd never see a crash report). | ||
* | ||
* This example also enables some more advanced features of KSCrash. See | ||
* configureAdvancedSettings. | ||
*/ | ||
|
||
|
||
@implementation AppDelegate | ||
|
||
- (BOOL) application:(__unused UIApplication *) application | ||
didFinishLaunchingWithOptions:(__unused NSDictionary *) launchOptions | ||
{ | ||
[self installCrashHandler]; | ||
|
||
return YES; | ||
} | ||
|
||
// ====================================================================== | ||
#pragma mark - Basic Crash Handling - | ||
// ====================================================================== | ||
|
||
- (void) installCrashHandler | ||
{ | ||
// This can be useful when debugging on the simulator. | ||
// Normally, there's no way to see console messages in the simulator, | ||
// except when running in the debugger, which disables the crash handler. | ||
// This feature redirects KSCrash console messages to a log file instead. | ||
// [[KSCrash sharedInstance] redirectConsoleLogsToDefaultFile]; | ||
|
||
|
||
// Create an installation (choose one) | ||
// KSCrashInstallation* installation = [self makeStandardInstallation]; | ||
self.crashInstallation = [self makeEmailInstallation]; | ||
// self.crashInstallation = [self makeHockeyInstallation]; | ||
// self.crashInstallation = [self makeQuincyInstallation]; | ||
|
||
|
||
// Install the crash handler. This should be done as early as possible. | ||
// This will record any crashes that occur, but it doesn't automatically send them. | ||
[self.crashInstallation install]; | ||
|
||
// You may also optionally configure some more advanced settings if you like. | ||
[self configureAdvancedSettings]; | ||
|
||
// Crash reports will be sent by LoaderVC. | ||
} | ||
|
||
- (KSCrashInstallation*) makeEmailInstallation | ||
{ | ||
NSString* emailAddress = @"your@email.here"; | ||
|
||
KSCrashInstallationEmail* email = [KSCrashInstallationEmail sharedInstance]; | ||
email.recipients = @[emailAddress]; | ||
email.subject = @"Crash Report"; | ||
email.message = @"This is a crash report"; | ||
email.filenameFmt = @"crash-report-%d.txt.gz"; | ||
|
||
[email addConditionalAlertWithTitle:@"Crash Detected" | ||
message:@"The app crashed last time it was launched. Send a crash report?" | ||
yesAnswer:@"Sure!" | ||
noAnswer:@"No thanks"]; | ||
|
||
return email; | ||
} | ||
|
||
- (KSCrashInstallation*) makeHockeyInstallation | ||
{ | ||
NSString* hockeyAppIdentifier = @"PUT_YOUR_HOCKEY_APP_ID_HERE"; | ||
|
||
KSCrashInstallationHockey* hockey = [KSCrashInstallationHockey sharedInstance]; | ||
hockey.appIdentifier = hockeyAppIdentifier; | ||
hockey.userID = @"ABC123"; | ||
hockey.contactEmail = @"nobody@nowhere.com"; | ||
hockey.crashDescription = @"Something broke!"; | ||
|
||
// Don't wait until reachable because the main VC won't show until the process completes. | ||
hockey.waitUntilReachable = NO; | ||
|
||
return hockey; | ||
} | ||
|
||
- (KSCrashInstallation*) makeQuincyInstallation | ||
{ | ||
NSURL* quincyURL = [NSURL URLWithString:@"http://localhost:8888/quincy/crash_v200.php"]; | ||
|
||
KSCrashInstallationQuincy* quincy = [KSCrashInstallationQuincy sharedInstance]; | ||
quincy.url = quincyURL; | ||
quincy.userID = @"ABC123"; | ||
quincy.contactEmail = @"nobody@nowhere.com"; | ||
quincy.crashDescription = @"Something broke!"; | ||
|
||
// Don't wait until reachable because the main VC won't show until the process completes. | ||
quincy.waitUntilReachable = NO; | ||
|
||
return quincy; | ||
} | ||
|
||
- (KSCrashInstallation*) makeStandardInstallation | ||
{ | ||
NSURL* url = [NSURL URLWithString:@"http://put.your.url.here"]; | ||
|
||
KSCrashInstallationStandard* standard = [KSCrashInstallationStandard sharedInstance]; | ||
standard.url = url; | ||
|
||
return standard; | ||
} | ||
|
||
|
||
// ====================================================================== | ||
#pragma mark - Advanced Crash Handling (optional) - | ||
// ====================================================================== | ||
|
||
static void advanced_crash_callback(const KSCrashReportWriter* writer) | ||
{ | ||
// You can add extra user data at crash time if you want. | ||
writer->addBooleanElement(writer, "some_bool_value", NO); | ||
} | ||
|
||
- (void) configureAdvancedSettings | ||
{ | ||
KSCrash* handler = [KSCrash sharedInstance]; | ||
|
||
// Settings in KSCrash.h | ||
handler.zombieCacheSize = 16384; | ||
handler.deadlockWatchdogInterval = 8; | ||
handler.userInfo = @{@"someKey": @"someValue"}; | ||
handler.onCrash = advanced_crash_callback; | ||
handler.printTraceToStdout = YES; | ||
|
||
// Do not introspect class SensitiveInfo (see MainVC) | ||
// When added to the "do not introspect" list, the Objective-C introspector | ||
// will only record the class name, not its contents. | ||
handler.doNotIntrospectClasses = @[@"SensitiveInfo"]; | ||
} | ||
|
||
@end |
File renamed without changes
File renamed without changes
File renamed without changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// | ||
// LoaderVC.h | ||
// Advanced-Example | ||
// | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
@interface LoaderVC : UIViewController | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// | ||
// LoaderVC.m | ||
// Advanced-Example | ||
// | ||
|
||
#import "LoaderVC.h" | ||
|
||
#import "AppDelegate.h" | ||
#import <KSCrash/KSCrashInstallation.h> | ||
|
||
/** | ||
* Defers application loading until all error reports have been sent. | ||
* This allows error reports to be sent even if the app's initialization | ||
* code is causing a crash. | ||
* | ||
* Normally you'd just have this view display Default.png so that it looks | ||
* no different from the launch view. | ||
*/ | ||
@implementation LoaderVC | ||
|
||
- (void) viewDidAppear:(BOOL) animated | ||
{ | ||
[super viewDidAppear:animated]; | ||
|
||
// Send all outstanding reports, then show the main view controller. | ||
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate; | ||
[appDelegate.crashInstallation sendAllReportsWithCompletion:^(NSArray* reports, BOOL completed, NSError* error) | ||
{ | ||
if(completed) | ||
{ | ||
NSLog(@"Sent %d reports", [reports count]); | ||
} | ||
else | ||
{ | ||
NSLog(@"Failed to send reports: %@", error); | ||
} | ||
|
||
// If you added an alert to the installation, it will interfere with replacing | ||
// the root view controller. Delaying by 0.3 seconds mitigates this. | ||
[self performSelector:@selector(showMainVC) withObject:nil afterDelay:0.3]; | ||
}]; | ||
|
||
} | ||
|
||
- (void) showMainVC | ||
{ | ||
UIViewController* vc = [self.storyboard instantiateViewControllerWithIdentifier:@"MainVC"]; | ||
[UIApplication sharedApplication].keyWindow.rootViewController = vc; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// | ||
// MainVC.h | ||
// Advanced-Example | ||
// | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
@interface MainVC : UIViewController | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// | ||
// MainVC.m | ||
// Advanced-Example | ||
// | ||
|
||
#import "MainVC.h" | ||
|
||
|
||
/** | ||
* Some sensitive info that should not be printed out at any time. | ||
* | ||
* If you have Objective-C introspection turned on, it would normally | ||
* introspect this class, unless you add it to the list of | ||
* "do not introspect classes" in KSCrash. We do precisely this in | ||
* -[AppDelegate configureAdvancedSettings] | ||
*/ | ||
@interface SensitiveInfo: NSObject | ||
|
||
@property(nonatomic, readwrite, strong) NSString* password; | ||
|
||
@end | ||
|
||
@implementation SensitiveInfo | ||
|
||
@end | ||
|
||
|
||
|
||
@interface MainVC () | ||
|
||
@property(nonatomic, readwrite, strong) SensitiveInfo* info; | ||
|
||
@end | ||
|
||
@implementation MainVC | ||
|
||
- (id) initWithCoder:(NSCoder *)aDecoder | ||
{ | ||
if((self = [super initWithCoder:aDecoder])) | ||
{ | ||
// This info could be leaked during introspection unless you tell KSCrash to ignore it. | ||
// See -[AppDelegate configureAdvancedSettings] for more info. | ||
self.info = [SensitiveInfo new]; | ||
self.info.password = @"it's a secret!"; | ||
} | ||
return self; | ||
} | ||
|
||
- (IBAction) onCrash:(__unused id) sender | ||
{ | ||
char* invalid = (char*)-1; | ||
*invalid = 1; | ||
} | ||
|
||
@end |
File renamed without changes.
Oops, something went wrong.