[error-handler] Replace Sentry with Bugsnag

This commit is contained in:
Pedro Piñera 2018-04-24 15:58:09 +02:00
parent 3306382693
commit 474e1774c3
52 changed files with 161 additions and 2221 deletions

View File

@ -2,4 +2,4 @@ GH_TOKEN=xxxx
ENCRYPTION_SECRET=xxxx
CERT_PASSWORD=xxxx
SENTRY_AUTH_TOKEN=xxx
SENTRY_DSN=xxxx
SENTRY_DSN=xxxx

3
.gitignore vendored
View File

@ -99,4 +99,5 @@ keys/dsa_priv.pem
certs/dist.cer
certs/dist.p12
certs/xcbuddy_dist.provisionprofile
.idea/
.idea/
Carthage/Checkouts

View File

@ -25,6 +25,10 @@
B918A2312093680600E64FBE /* MockErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = B918A2302093680600E64FBE /* MockErrorHandler.swift */; };
B91FF331206AB4E6005EA520 /* xcbuddy in Copy CLI */ = {isa = PBXBuildFile; fileRef = B915ECF6206395DA004B6630 /* xcbuddy */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
B92BF9FE2075608B00EE4EBD /* Data+TestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B92BF9FD2075608B00EE4EBD /* Data+TestData.swift */; };
B949A5DA208F69AB00898F2B /* ErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = B949A5D9208F69AB00898F2B /* ErrorHandler.swift */; };
B949A5DC208F69F400898F2B /* Bugsnag.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B949A5DB208F69F400898F2B /* Bugsnag.framework */; };
B949A5DD208F6A0800898F2B /* Bugsnag.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B949A5DB208F69F400898F2B /* Bugsnag.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B949A5DE208F6A1000898F2B /* Bugsnag.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B949A5DB208F69F400898F2B /* Bugsnag.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B94C7FC12062B8A8009BF596 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B94C7FB72062B8A7009BF596 /* Assets.xcassets */; };
B94C7FC22062B8A8009BF596 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = B94C7FB82062B8A7009BF596 /* MainMenu.xib */; };
B94C7FC62062B8A8009BF596 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94C7FC02062B8A8009BF596 /* AppDelegate.swift */; };
@ -103,6 +107,8 @@
B9F1EDF8208D22D900477835 /* TargetValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1EDF7208D22D900477835 /* TargetValidator.swift */; };
B9F1EDFB208D24F700477835 /* ProjectValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1EDFA208D24F700477835 /* ProjectValidatorTests.swift */; };
B9F1EDFD208D26B200477835 /* GraphValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1EDFC208D26B200477835 /* GraphValidator.swift */; };
B9F1EE00208E2D7F00477835 /* BuildifyError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1EDFF208E2D7F00477835 /* BuildifyError.swift */; };
B9F1EE02208E2E2B00477835 /* CommandLineErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1EE01208E2E2B00477835 /* CommandLineErrorHandler.swift */; };
B9FB2DBF2086506E00BC2FB3 /* Basic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9FB2DBB20864FF800BC2FB3 /* Basic.framework */; };
B9FB2DC62086515F00BC2FB3 /* Basic.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B9FB2DBB20864FF800BC2FB3 /* Basic.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B9FB2DC72086516500BC2FB3 /* POSIX.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B9FB2DC02086507200BC2FB3 /* POSIX.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@ -243,6 +249,8 @@
B92BF9F620755B8500EE4EBD /* MockManifestLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockManifestLoader.swift; sourceTree = "<group>"; };
B92BF9FA20755D5300EE4EBD /* MockFileHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockFileHandler.swift; sourceTree = "<group>"; };
B92BF9FD2075608B00EE4EBD /* Data+TestData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+TestData.swift"; sourceTree = "<group>"; };
B949A5D9208F69AB00898F2B /* ErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorHandler.swift; sourceTree = "<group>"; };
B949A5DB208F69F400898F2B /* Bugsnag.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Bugsnag.framework; path = Carthage/Build/Mac/Bugsnag.framework; sourceTree = SOURCE_ROOT; };
B94C7F972062B829009BF596 /* xcbuddy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = xcbuddy.app; sourceTree = BUILT_PRODUCTS_DIR; };
B94C7FB72062B8A7009BF596 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
B94C7FB92062B8A7009BF596 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
@ -318,6 +326,8 @@
B9F1EDF7208D22D900477835 /* TargetValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetValidator.swift; sourceTree = "<group>"; };
B9F1EDFA208D24F700477835 /* ProjectValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectValidatorTests.swift; sourceTree = "<group>"; };
B9F1EDFC208D26B200477835 /* GraphValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphValidator.swift; sourceTree = "<group>"; };
B9F1EDFF208E2D7F00477835 /* BuildifyError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildifyError.swift; sourceTree = "<group>"; };
B9F1EE01208E2E2B00477835 /* CommandLineErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandLineErrorHandler.swift; sourceTree = "<group>"; };
B9FB2DBB20864FF800BC2FB3 /* Basic.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Basic.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B9FB2DBD2086502100BC2FB3 /* Utility.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Utility.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B9FB2DC02086507200BC2FB3 /* POSIX.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = POSIX.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@ -438,6 +448,7 @@
B915ED3E2063B04C004B6630 /* Sources */ = {
isa = PBXGroup;
children = (
B9F1EDFE208E2D6400477835 /* Errors */,
B9F1EDF4208D215600477835 /* Validator */,
B95895F1208A2A9E00F00ACF /* Generator */,
B9B6299C20864E2300EE9E07 /* App */,
@ -669,6 +680,16 @@
path = Validator;
sourceTree = "<group>";
};
B9F1EDFE208E2D6400477835 /* Errors */ = {
isa = PBXGroup;
children = (
B9F1EDFF208E2D7F00477835 /* BuildifyError.swift */,
B9F1EE01208E2E2B00477835 /* CommandLineErrorHandler.swift */,
B949A5D9208F69AB00898F2B /* ErrorHandler.swift */,
);
path = Errors;
sourceTree = "<group>";
};
B9FB2DCD2086538E00BC2FB3 /* Loader */ = {
isa = PBXGroup;
children = (
@ -937,9 +958,12 @@
B918A22E20935EE900E64FBE /* ErrorHandler.swift in Sources */,
B9B629AC20864E3A00EE9E07 /* FileHandler.swift in Sources */,
B9553DEA2090690000050311 /* Shell.swift in Sources */,
B9F1EE00208E2D7F00477835 /* BuildifyError.swift in Sources */,
B95895F3208A2ACF00F00ACF /* ProjectGenerator.swift in Sources */,
B9FB2DE52086544900BC2FB3 /* Workspace.swift in Sources */,
B9B629C120864E7D00EE9E07 /* DumpCommand.swift in Sources */,
B9F1EE02208E2E2B00477835 /* CommandLineErrorHandler.swift in Sources */,
B949A5DA208F69AB00898F2B /* ErrorHandler.swift in Sources */,
B9FB2DE42086544900BC2FB3 /* Config.swift in Sources */,
B9FB2DDF208653E000BC2FB3 /* GraphNode.swift in Sources */,
B9FB2DEB2086544900BC2FB3 /* Product.swift in Sources */,
@ -1125,6 +1149,7 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/App/Frameworks",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = App/xcbuddykit/Info.plist;
@ -1153,6 +1178,7 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/App/Frameworks",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = App/xcbuddykit/Info.plist;
@ -1197,6 +1223,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
BUGSNAG_API_KEY = "$(BUGSNAG_API_KEY)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@ -1254,6 +1281,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
BUGSNAG_API_KEY = "$(BUGSNAG_API_KEY)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@ -1295,6 +1323,7 @@
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_SWIFT_FLAGS = "-Xcc -fmodule-map-file=$(SRCROOT)/.build/checkouts/swift-package-manager.git--5789260357088934756/Sources/clibc/include/module.modulemap";
SDKROOT = macosx;
SENTRY_DSN = "$(SENTRY_DSN)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
};
name = Release;
@ -1304,6 +1333,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
BUGSNAG_API_KEY = "$(BUGSNAG_API_KEY)";
CODE_SIGN_ENTITLEMENTS = App/xcbuddy.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
CODE_SIGN_STYLE = Manual;
@ -1333,6 +1363,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
BUGSNAG_API_KEY = "$(BUGSNAG_API_KEY)";
CODE_SIGN_ENTITLEMENTS = App/xcbuddy.entitlements;
CODE_SIGN_IDENTITY = "Developer ID Application";
CODE_SIGN_STYLE = Manual;

View File

@ -1 +0,0 @@
Versions/Current/Headers

View File

@ -1 +0,0 @@
Versions/Current/Modules

View File

@ -1 +0,0 @@
Versions/Current/PrivateHeaders

View File

@ -1 +0,0 @@
Versions/Current/Resources

View File

@ -1 +0,0 @@
Versions/Current/Sentry

View File

@ -1,62 +0,0 @@
//
// Sentry.h
// Sentry
//
// Created by Daniel Griesser on 02/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
//! Project version number for Sentry.
FOUNDATION_EXPORT double SentryVersionNumber;
//! Project version string for Sentry.
FOUNDATION_EXPORT const unsigned char SentryVersionString[];
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryClient.h>
#import <Sentry/SentrySwizzle.h>
#import <Sentry/SentryNSURLRequest.h>
#import <Sentry/SentrySerializable.h>
#import <Sentry/SentryEvent.h>
#import <Sentry/SentryThread.h>
#import <Sentry/SentryException.h>
#import <Sentry/SentryStacktrace.h>
#import <Sentry/SentryFrame.h>
#import <Sentry/SentryUser.h>
#import <Sentry/SentryDebugMeta.h>
#import <Sentry/SentryContext.h>
#import <Sentry/SentryBreadcrumb.h>
#import <Sentry/SentryBreadcrumbStore.h>
#import <Sentry/SentryJavaScriptBridgeHelper.h>
#else
#import "SentryClient.h"
#import "SentrySwizzle.h"
#import "SentryNSURLRequest.h"
#import "SentrySerializable.h"
#import "SentryEvent.h"
#import "SentryThread.h"
#import "SentryException.h"
#import "SentryStacktrace.h"
#import "SentryFrame.h"
#import "SentryUser.h"
#import "SentryDebugMeta.h"
#import "SentryContext.h"
#import "SentryBreadcrumb.h"
#import "SentryBreadcrumbStore.h"
#import "SentryJavaScriptBridgeHelper.h"
#endif

View File

@ -1,69 +0,0 @@
//
// SentryBreadcrumb.h
// Sentry
//
// Created by Daniel Griesser on 22/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#import <Sentry/SentrySerializable.h>
#else
#import "SentryDefines.h"
#import "SentrySerializable.h"
#endif
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(Breadcrumb)
@interface SentryBreadcrumb : NSObject <SentrySerializable>
SENTRY_NO_INIT
/**
* Level of breadcrumb
*/
@property(nonatomic) enum SentrySeverity level;
/**
* Category of bookmark, can be any string
*/
@property(nonatomic, copy) NSString *category;
/**
* NSDate when the breadcrumb happened
*/
@property(nonatomic, strong) NSDate *_Nullable timestamp;
/**
* Type of breadcrumb, can be e.g.: http, empty, user, navigation
* This will be used as icon of the breadcrumb
*/
@property(nonatomic, copy) NSString *_Nullable type;
/**
* Message for the breadcrumb
*/
@property(nonatomic, copy) NSString *_Nullable message;
/**
* Arbitrary additional data that will be sent with the breadcrumb
*/
@property(nonatomic, strong) NSDictionary<NSString *, id> *_Nullable data;
/**
* Initializer for SentryBreadcrumb
*
* @param level SentrySeverity
* @param category String
* @return SentryBreadcrumb
*/
- (instancetype)initWithLevel:(enum SentrySeverity)level category:(NSString *)category;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,64 +0,0 @@
//
// SentryBreadcrumbStore.h
// Sentry
//
// Created by Daniel Griesser on 22/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#import <Sentry/SentrySerializable.h>
#else
#import "SentryDefines.h"
#import "SentrySerializable.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@class SentryBreadcrumb, SentryFileManager;
NS_SWIFT_NAME(BreadcrumbStore)
@interface SentryBreadcrumbStore : NSObject <SentrySerializable>
SENTRY_NO_INIT
/*
* This property defines how many breadcrumbs should be stored.
* Change this to reflect you needs.
*/
@property(nonatomic, assign) NSUInteger maxBreadcrumbs;
/**
* Init SentryBreadcrumbStore, should only be used internally
*
* @param fileManager SentryFileManager
* @return SentryBreadcrumbStore
*/
- (instancetype)initWithFileManager:(SentryFileManager *)fileManager;
/**
* Add a SentryBreadcrumb to the store
* @param crumb SentryBreadcrumb
*/
- (void)addBreadcrumb:(SentryBreadcrumb *)crumb;
/**
* Deletes all stored SentryBreadcrumbs
*/
- (void)clear;
/**
* Returns the number of stored SentryBreadcrumbs
* This number can be higher than maxBreadcrumbs since we
* only remove breadcrumbs over the limit once we sent them
* @return number of SentryBreadcrumb
*/
- (NSUInteger)count;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,210 +0,0 @@
//
// SentryClient.h
// Sentry
//
// Created by Daniel Griesser on 02/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#else
#import "SentryDefines.h"
#endif
@class SentryEvent, SentryBreadcrumbStore, SentryUser, SentryThread;
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(Client)
@interface SentryClient : NSObject
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
/**
* Return a version string e.g: 1.2.3 (3)
*/
@property(nonatomic, class, readonly, copy) NSString *versionString;
/**
* Return a string sentry-cocoa
*/
@property(nonatomic, class, readonly, copy) NSString *sdkName;
/**
* Set logLevel for the current client default kSentryLogLevelError
*/
@property(nonatomic, class) SentryLogLevel logLevel;
/**
* Set global user -> thus will be sent with every event
*/
@property(nonatomic, strong) SentryUser *_Nullable user;
/**
* Set global tags -> these will be sent with every event
*/
@property(nonatomic, strong) NSDictionary<NSString *, NSString *> *_Nullable tags;
/**
* Set global extra -> these will be sent with every event
*/
@property(nonatomic, strong) NSDictionary<NSString *, id> *_Nullable extra;
/**
* This will be filled on every startup with a dictionary with extra, tags, user which will be used
* when sending the crashreport
*/
@property(nonatomic, strong) NSDictionary<NSString *, id> *_Nullable lastContext;
/**
* Contains the last successfully sent event
*/
@property(nonatomic, strong) SentryEvent *_Nullable lastEvent;
/**
* Contains the last successfully sent event
*/
@property(nonatomic, strong) SentryBreadcrumbStore *breadcrumbs;
/**
* This block can be used to modify the event before it will be serialized and sent
*/
@property(nonatomic, copy) SentryBeforeSerializeEvent _Nullable beforeSerializeEvent;
/**
* This block can be used to modify the request before its put on the request queue.
* Can be used e.g. to set additional http headers before sending
*/
@property(nonatomic, copy) SentryBeforeSendRequest _Nullable beforeSendRequest;
/**
* This block can be used to prevent the event from being sent.
* @return BOOL
*/
@property(nonatomic, copy) SentryShouldSendEvent _Nullable shouldSendEvent;
/**
* Returns the shared sentry client
* @return sharedClient if it was set before
*/
@property(nonatomic, class) SentryClient *_Nullable sharedClient;
/**
* Defines the sample rate of SentryClient, should be a float between 0.0 and 1.0
* Setting this property sets shouldSendEvent callback and applies a random event sampler.
*/
@property(nonatomic) float sampleRate;
/**
* This block can be used to prevent the event from being deleted after a failed send attempt.
* Default is it will only be stored once after you hit a rate limit or there is no internet connect/cannot connect.
* Also note that if an event fails to be sent again after it was queued, it will be discarded regardless.
* @return BOOL YES = store and try again later, NO = delete
*/
@property(nonatomic, copy) SentryShouldQueueEvent _Nullable shouldQueueEvent;
/**
* Initializes a SentryClient. Pass your private DSN string.
*
* @param dsn DSN string of sentry
* @param error NSError reference object
* @return SentryClient
*/
- (_Nullable instancetype)initWithDsn:(NSString *)dsn
didFailWithError:(NSError *_Nullable *_Nullable)error;
/**
* This automatically adds breadcrumbs for different user actions.
*/
- (void)enableAutomaticBreadcrumbTracking;
/**
* Sends and event to sentry. Internally calls @selector(sendEvent:useClientProperties:withCompletionHandler:) with
* useClientProperties: YES. CompletionHandler will be called if set.
* @param event SentryEvent that should be sent
* @param completionHandler SentryRequestFinished
*/
- (void)sendEvent:(SentryEvent *)event withCompletionHandler:(_Nullable SentryRequestFinished)completionHandler
NS_SWIFT_NAME(send(event:completion:));
/**
* This function stores an event to disk. It will be send with the next batch.
* This function is mainly used for react native.
* @param event SentryEvent that should be sent
*/
- (void)storeEvent:(SentryEvent *)event;
/**
* Clears all context related variables tags, extra and user
*/
- (void)clearContext;
/// KSCrash
/// Functions below will only do something if KSCrash is linked
/**
* This forces a crash, useful to test the KSCrash integration
*
*/
- (void)crash;
/**
* This function tries to start the KSCrash handler, return YES if successfully started
* otherwise it will return false and set error
*
* @param error if KSCrash is not available error will be set
* @return successful
*/
- (BOOL)startCrashHandlerWithError:(NSError *_Nullable *_Nullable)error;
/**
* Report a custom, user defined exception. Only works if KSCrash is linked.
* This can be useful when dealing with scripting languages.
*
* If terminateProgram is true, all sentries will be uninstalled and the application will
* terminate with an abort().
*
* @param name The exception name (for namespacing exception types).
* @param reason A description of why the exception occurred.
* @param language A unique language identifier.
* @param lineOfCode A copy of the offending line of code (nil = ignore).
* @param stackTrace An array of frames (dictionaries or strings) representing the call stack leading to the exception (nil = ignore).
* @param logAllThreads If YES, suspend all threads and log their state. Note that this incurs a
* performance penalty, so it's best to use only on fatal errors.
* @param terminateProgram If YES, do not return from this function call. Terminate the program instead.
*/
- (void)reportUserException:(NSString *)name
reason:(NSString *)reason
language:(NSString *)language
lineOfCode:(NSString *)lineOfCode
stackTrace:(NSArray *)stackTrace
logAllThreads:(BOOL)logAllThreads
terminateProgram:(BOOL)terminateProgram;
/**
* Returns true if the app crashed before launching now
*/
- (BOOL)crashedLastLaunch;
/**
* This will snapshot the whole stacktrace at the time when its called. This stacktrace will be attached with the next sent event.
* Please note to also call appendStacktraceToEvent in the callback in order to send the stacktrace with the event.
*/
- (void)snapshotStacktrace:(void (^)(void))snapshotCompleted;
/**
* This appends the stored stacktrace (if existant) to the event.
*
* @param event SentryEvent event
*/
- (void)appendStacktraceToEvent:(SentryEvent *)event;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,44 +0,0 @@
//
// SentryContext.h
// Sentry
//
// Created by Daniel Griesser on 18/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentrySerializable.h>
#else
#import "SentrySerializable.h"
#endif
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(Context)
@interface SentryContext : NSObject <SentrySerializable>
/**
* Operating System information in contexts
*/
@property(nonatomic, strong) NSDictionary<NSString *, id> *_Nullable osContext;
/**
* Device information in contexts
*/
@property(nonatomic, strong) NSDictionary<NSString *, id> *_Nullable deviceContext;
/**
* App information in contexts
*/
@property(nonatomic, strong) NSDictionary<NSString *, id> *_Nullable appContext;
- (instancetype)init;
+ (instancetype)new NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,17 +0,0 @@
//
// SentryCrashExceptionApplication.h
// Sentry
//
// Created by Daniel Griesser on 31.08.17.
// Copyright © 2017 Sentry. All rights reserved.
//
#if TARGET_OS_OSX
#import <Cocoa/Cocoa.h>
@interface SentryCrashExceptionApplication : NSApplication
#else
#import <Foundation/Foundation.h>
@interface SentryCrashExceptionApplication : NSObject
#endif
@end

View File

@ -1,82 +0,0 @@
//
// SentryDebugMeta.h
// Sentry
//
// Created by Daniel Griesser on 10/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentrySerializable.h>
#else
#import "SentrySerializable.h"
#endif
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(DebugMeta)
@interface SentryDebugMeta : NSObject <SentrySerializable>
/**
* UUID of image
*/
@property(nonatomic, copy) NSString *_Nullable uuid;
/**
* Type of debug meta, mostly just apple
*/
@property(nonatomic, copy) NSString *_Nullable type;
/**
* CPU type of image
*/
@property(nonatomic, copy) NSNumber *_Nullable cpuType;
/**
* CPU Sub type of image
*/
@property(nonatomic, copy) NSNumber *_Nullable cpuSubType;
/**
* Name of the image
*/
@property(nonatomic, copy) NSString *_Nullable name;
/**
* Image size
*/
@property(nonatomic, copy) NSNumber *_Nullable imageSize;
/**
* Image VM address
*/
@property(nonatomic, copy) NSString *_Nullable imageVmAddress;
/**
* Image address
*/
@property(nonatomic, copy) NSString *_Nullable imageAddress;
/**
* Major version of the image
*/
@property(nonatomic, copy) NSNumber *_Nullable majorVersion;
/**
* Minor version of the image
*/
@property(nonatomic, copy) NSNumber *_Nullable minorVersion;
/**
* Revision version of the image
*/
@property(nonatomic, copy) NSNumber *_Nullable revisionVersion;
- (instancetype)init;
+ (instancetype)new NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,99 +0,0 @@
//
// SentryDefines.h
// Sentry
//
// Created by Daniel Griesser on 02/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#ifdef __cplusplus
#define SENTRY_EXTERN extern "C" __attribute__((visibility ("default")))
#else
#define SENTRY_EXTERN extern __attribute__((visibility ("default")))
#endif
#if TARGET_OS_IOS || TARGET_OS_TV
#define SENTRY_HAS_UIDEVICE 1
#else
#define SENTRY_HAS_UIDEVICE 0
#endif
#if SENTRY_HAS_UIDEVICE
#define SENTRY_HAS_UIKIT 1
#else
#define SENTRY_HAS_UIKIT 0
#endif
#define WITH_KSCRASH \
(__has_include(<KSCrash/KSCrash.h>) || __has_include("KSCrash.h"))
#define SENTRY_NO_INIT \
- (instancetype)init NS_UNAVAILABLE; \
+ (instancetype)new NS_UNAVAILABLE;
@class SentryEvent, SentryNSURLRequest;
/**
* Block used for returning after a request finished
*/
typedef void (^SentryRequestFinished)(NSError *_Nullable error);
/**
* Block used for request operation finished, shouldDiscardEvent is YES if event should be deleted
* regardless if an error occured or not
*/
typedef void (^SentryRequestOperationFinished)(NSHTTPURLResponse *_Nullable response, NSError *_Nullable error);
/**
* Block can be used to mutate event before its send
*/
typedef void (^SentryBeforeSerializeEvent)(SentryEvent *_Nonnull event);
/**
* Block can be used to mutate NSURLRequest e.g.: add headers before request is executed
*/
typedef void (^SentryBeforeSendRequest)(SentryNSURLRequest *_Nonnull request);
/**
* Block can be used to prevent the event from being sent
*/
typedef BOOL (^SentryShouldSendEvent)(SentryEvent *_Nonnull event);
/**
* Block can be used to determine if an event should be queued and stored locally.
* It will be tried to send again after next successful send.
* Note that this will only be called once the event is created and send manully.
* Once it has been queued once it will be discarded if it fails again.
*/
typedef BOOL (^SentryShouldQueueEvent)(SentryEvent *_Nonnull event, NSHTTPURLResponse *_Nullable response, NSError *_Nullable error);
/**
* Loglevel
*/
typedef NS_ENUM(NSInteger, SentryLogLevel) {
kSentryLogLevelNone = 1,
kSentryLogLevelError,
kSentryLogLevelDebug,
kSentryLogLevelVerbose
};
/**
* Level of severity
*/
typedef NS_ENUM(NSInteger, SentrySeverity) {
kSentrySeverityFatal = 0,
kSentrySeverityError = 1,
kSentrySeverityWarning = 2,
kSentrySeverityInfo = 3,
kSentrySeverityDebug = 4,
};
/**
* Static internal helper to convert enum to string
*/
static NSString *_Nonnull const SentrySeverityNames[] = {
@"fatal",
@"error",
@"warning",
@"info",
@"debug",
};

View File

@ -1,160 +0,0 @@
//
// SentryEvent.h
// Sentry
//
// Created by Daniel Griesser on 05/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#import <Sentry/SentrySerializable.h>
#else
#import "SentryDefines.h"
#import "SentrySerializable.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@class SentryThread, SentryException, SentryStacktrace, SentryUser, SentryDebugMeta, SentryContext;
NS_SWIFT_NAME(Event)
@interface SentryEvent : NSObject <SentrySerializable>
SENTRY_NO_INIT
/**
* This will be set by the initializer. Should be an UUID with the "-".
*/
@property(nonatomic, copy) NSString *eventId;
/**
* Message of the event
*/
@property(nonatomic, copy) NSString *message;
/**
* NSDate of when the event occured
*/
@property(nonatomic, strong) NSDate *timestamp;
/**
* SentrySeverity of the event
*/
@property(nonatomic) enum SentrySeverity level;
/**
* Platform this will be used for symbolicating on the server should be "cocoa"
*/
@property(nonatomic, copy) NSString *platform;
/**
* Define the logger name
*/
@property(nonatomic, copy) NSString *_Nullable logger;
/**
* Define the server name
*/
@property(nonatomic, copy) NSString *_Nullable serverName;
/**
* This property will be filled before the event is sent. Do not change it otherwise you know what you are doing.
*/
@property(nonatomic, copy) NSString *_Nullable releaseName;
/**
* This property will be filled before the event is sent. Do not change it otherwise you know what you are doing.
*/
@property(nonatomic, copy) NSString *_Nullable dist;
/**
* The environment used for this event
*/
@property(nonatomic, copy) NSString *_Nullable environment;
/**
* Arbitrary key:value (string:string ) data that will be shown with the event
*/
@property(nonatomic, strong) NSDictionary<NSString *, NSString *> *_Nullable tags;
/**
* Arbitrary additional information that will be sent with the event
*/
@property(nonatomic, strong) NSDictionary<NSString *, id> *_Nullable extra;
/**
* Information about the sdk can be something like this. This will be set for you
* Don't touch it if you not know what you are doing.
*
* {
* version: "3.3.3",
* name: "sentry-cocoa",
* integrations: [
* "react-native"
* ]
* }
*/
@property(nonatomic, strong) NSDictionary<NSString *, id> *_Nullable sdk;
/**
* Modules of the event
*/
@property(nonatomic, strong) NSDictionary<NSString *, NSString *> *_Nullable modules;
/**
* Set the fingerprint of an event to determine the grouping
*/
@property(nonatomic, strong) NSArray<NSString *> *_Nullable fingerprint;
/**
* Set the SentryUser for the event
*/
@property(nonatomic, strong) SentryUser *_Nullable user;
/**
* This object contains meta information, will be set automatically overwrite only if you know what you are doing
*/
@property(nonatomic, strong) SentryContext *_Nullable context;
/**
* Contains SentryThread if an crash occurred of it's an user reported exception
*/
@property(nonatomic, strong) NSArray<SentryThread *> *_Nullable threads;
/**
* General information about the SentryException, usually there is only one exception in the array
*/
@property(nonatomic, strong) NSArray<SentryException *> *_Nullable exceptions;
/**
* Separate SentryStacktrace that can be sent with the event, besides threads
*/
@property(nonatomic, strong) SentryStacktrace *_Nullable stacktrace;
/**
* Containing images loaded during runtime
*/
@property(nonatomic, strong) NSArray<SentryDebugMeta *> *_Nullable debugMeta;
/**
* This contains all breadcrumbs available at the time when the event occurred/will be sent
*/
@property(nonatomic, strong) NSDictionary<NSString *, id> *_Nullable breadcrumbsSerialized;
/**
* This property is there for setting main bundle of the app
*/
@property(nonatomic, strong) NSDictionary *infoDict;
/**
* Init an SentryEvent will set all needed fields by default
* @param level SentrySeverity
* @return SentryEvent
*/
- (instancetype)initWithLevel:(enum SentrySeverity)level;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,67 +0,0 @@
//
// SentryException.h
// Sentry
//
// Created by Daniel Griesser on 05/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#import <Sentry/SentrySerializable.h>
#else
#import "SentryDefines.h"
#import "SentrySerializable.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@class SentryThread;
NS_SWIFT_NAME(Exception)
@interface SentryException : NSObject <SentrySerializable>
SENTRY_NO_INIT
/**
* The name of the exception
*/
@property(nonatomic, copy) NSString *value;
/**
* Type of the exception
*/
@property(nonatomic, copy) NSString *type;
/**
* Additional information about the exception
*/
@property(nonatomic, strong) NSDictionary<NSString *, id> *_Nullable mechanism;
/**
* Can be set to define the module
*/
@property(nonatomic, copy) NSString *_Nullable module;
/**
* Determines if the exception was reported by a user BOOL
*/
@property(nonatomic, copy) NSNumber *_Nullable userReported;
/**
* SentryThread of the SentryException
*/
@property(nonatomic, strong) SentryThread *_Nullable thread;
/**
* Initialize an SentryException with value and type
* @param value String
* @param type String
* @return SentryException
*/
- (instancetype)initWithValue:(NSString *)value type:(NSString *)type;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,80 +0,0 @@
//
// SentryFrame.h
// Sentry
//
// Created by Daniel Griesser on 05/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentrySerializable.h>
#else
#import "SentrySerializable.h"
#endif
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(Frame)
@interface SentryFrame : NSObject <SentrySerializable>
/**
* SymbolAddress of the frame
*/
@property(nonatomic, copy) NSString *_Nullable symbolAddress;
/**
* Filename is used only for reporting JS frames
*/
@property(nonatomic, copy) NSString *_Nullable fileName;
/**
* Function name of the frame
*/
@property(nonatomic, copy) NSString *_Nullable function;
/**
* Module of the frame, mostly unused
*/
@property(nonatomic, copy) NSString *_Nullable module;
/**
* Corresponding package
*/
@property(nonatomic, copy) NSString *_Nullable package;
/**
* ImageAddress if the image related to the frame
*/
@property(nonatomic, copy) NSString *_Nullable imageAddress;
/**
* Set the platform for the individual frame, will use platform of the event.
* Mostly used for react native crashes.
*/
@property(nonatomic, copy) NSString *_Nullable platform;
/**
* InstructionAddress of the frame
*/
@property(nonatomic, copy) NSString *_Nullable instructionAddress;
/**
* User for react native, will be ignored for cocoa frames
*/
@property(nonatomic, copy) NSNumber *_Nullable lineNumber;
/**
* User for react native, will be ignored for cocoa frames
*/
@property(nonatomic, copy) NSNumber *_Nullable columnNumber;
- (instancetype)init;
+ (instancetype)new NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,34 +0,0 @@
//
// SentryJavaScriptBridgeHelper.h
// Sentry
//
// Created by Daniel Griesser on 23.10.17.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#else
#import "SentryDefines.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@class SentryEvent, SentryUser, SentryFrame, SentryBreadcrumb;
@interface SentryJavaScriptBridgeHelper : NSObject
SENTRY_NO_INIT
+ (SentryEvent *)createSentryEventFromJavaScriptEvent:(NSDictionary *)jsonEvent;
+ (SentryBreadcrumb *)createSentryBreadcrumbFromJavaScriptBreadcrumb:(NSDictionary *)jsonBreadcrumb;
+ (SentryLogLevel)sentryLogLevelFromJavaScriptLevel:(int)level;
+ (SentryUser *_Nullable)createSentryUserFromJavaScriptUser:(NSDictionary *)user;
+ (NSArray *)parseJavaScriptStacktrace:(NSString *)stacktrace;
+ (NSDictionary *)sanitizeDictionary:(NSDictionary *)dictionary;
+ (NSArray<SentryFrame *> *)convertReactNativeStacktrace:(NSArray *)stacktrace;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,27 +0,0 @@
//
// SentryNSURLRequest.h
// Sentry
//
// Created by Daniel Griesser on 05/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class SentryDsn, SentryEvent;
@interface SentryNSURLRequest : NSMutableURLRequest
- (_Nullable instancetype)initStoreRequestWithDsn:(SentryDsn *)dsn
andEvent:(SentryEvent *)event
didFailWithError:(NSError *_Nullable *_Nullable)error;
- (_Nullable instancetype)initStoreRequestWithDsn:(SentryDsn *)dsn
andData:(NSData *)data
didFailWithError:(NSError *_Nullable *_Nullable)error;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,22 +0,0 @@
//
// SentrySerializable.h
// Sentry
//
// Created by Daniel Griesser on 08/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@protocol SentrySerializable <NSObject>
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
- (NSDictionary<NSString *, id> *)serialize;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,53 +0,0 @@
//
// SentryStacktrace.h
// Sentry
//
// Created by Daniel Griesser on 05/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#import <Sentry/SentrySerializable.h>
#else
#import "SentryDefines.h"
#import "SentrySerializable.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@class SentryFrame;
NS_SWIFT_NAME(Stacktrace)
@interface SentryStacktrace : NSObject <SentrySerializable>
SENTRY_NO_INIT
/**
* Array of all SentryFrame in the stacktrace
*/
@property(nonatomic, strong) NSArray<SentryFrame *> *frames;
/**
* Registers of the thread for additional information used on the server
*/
@property(nonatomic, strong) NSDictionary<NSString *, NSString *> *registers;
/**
* Initialize a SentryStacktrace with frames and registers
* @param frames NSArray
* @param registers NSArray
* @return SentryStacktrace
*/
- (instancetype)initWithFrames:(NSArray<SentryFrame *> *)frames
registers:(NSDictionary<NSString *, NSString *> *)registers;
/**
* This will be called internally, is used to remove duplicated frames for certain crashes.
*/
- (void)fixDuplicateFrames;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,371 +0,0 @@
//
// SentrySwizzle.h
// Sentry
//
// Created by Daniel Griesser on 31/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
// Original implementation by Yan Rabovik on 05.09.13 https://github.com/rabovik/RSSwizzle
#import <Foundation/Foundation.h>
#pragma mark - Macros Based API
/// A macro for wrapping the return type of the swizzled method.
#define SentrySWReturnType(type) type
/// A macro for wrapping arguments of the swizzled method.
#define SentrySWArguments(arguments...) _SentrySWArguments(arguments)
/// A macro for wrapping the replacement code for the swizzled method.
#define SentrySWReplacement(code...) code
/// A macro for casting and calling original implementation.
/// May be used only in SentrySwizzleInstanceMethod or SentrySwizzleClassMethod macros.
#define SentrySWCallOriginal(arguments...) _SentrySWCallOriginal(arguments)
#pragma mark └ Swizzle Instance Method
/**
Swizzles the instance method of the class with the new implementation.
Example for swizzling `-(int)calculate:(int)number;` method:
@code
SentrySwizzleInstanceMethod(classToSwizzle,
@selector(calculate:),
SentrySWReturnType(int),
SentrySWArguments(int number),
SentrySWReplacement(
{
// Calling original implementation.
int res = SentrySWCallOriginal(number);
// Returning modified return value.
return res + 1;
}), 0, NULL);
@endcode
Swizzling frequently goes along with checking whether this particular class (or one of its superclasses) has been already swizzled. Here the `SentrySwizzleMode` and `key` parameters can help. See +[SentrySwizzle swizzleInstanceMethod:inClass:newImpFactory:mode:key:] for details.
Swizzling is fully thread-safe.
@param classToSwizzle The class with the method that should be swizzled.
@param selector Selector of the method that should be swizzled.
@param SentrySWReturnType The return type of the swizzled method wrapped in the SentrySWReturnType macro.
@param SentrySWArguments The arguments of the swizzled method wrapped in the SentrySWArguments macro.
@param SentrySWReplacement The code of the new implementation of the swizzled method wrapped in the SentrySWReplacement macro.
@param SentrySwizzleMode The mode is used in combination with the key to indicate whether the swizzling should be done for the given class. You can pass 0 for SentrySwizzleModeAlways.
@param key The key is used in combination with the mode to indicate whether the swizzling should be done for the given class. May be NULL if the mode is SentrySwizzleModeAlways.
@return YES if successfully swizzled and NO if swizzling has been already done for given key and class (or one of superclasses, depends on the mode).
*/
#define SentrySwizzleInstanceMethod(classToSwizzle, \
selector, \
SentrySWReturnType, \
SentrySWArguments, \
SentrySWReplacement, \
SentrySwizzleMode, \
key) \
_SentrySwizzleInstanceMethod(classToSwizzle, \
selector, \
SentrySWReturnType, \
_SentrySWWrapArg(SentrySWArguments), \
_SentrySWWrapArg(SentrySWReplacement), \
SentrySwizzleMode, \
key)
#pragma mark └ Swizzle Class Method
/**
Swizzles the class method of the class with the new implementation.
Example for swizzling `+(int)calculate:(int)number;` method:
@code
SentrySwizzleClassMethod(classToSwizzle,
@selector(calculate:),
SentrySWReturnType(int),
SentrySWArguments(int number),
SentrySWReplacement(
{
// Calling original implementation.
int res = SentrySWCallOriginal(number);
// Returning modified return value.
return res + 1;
}));
@endcode
Swizzling is fully thread-safe.
@param classToSwizzle The class with the method that should be swizzled.
@param selector Selector of the method that should be swizzled.
@param SentrySWReturnType The return type of the swizzled method wrapped in the SentrySWReturnType macro.
@param SentrySWArguments The arguments of the swizzled method wrapped in the SentrySWArguments macro.
@param SentrySWReplacement The code of the new implementation of the swizzled method wrapped in the SentrySWReplacement macro.
*/
#define SentrySwizzleClassMethod(classToSwizzle, \
selector, \
SentrySWReturnType, \
SentrySWArguments, \
SentrySWReplacement) \
_SentrySwizzleClassMethod(classToSwizzle, \
selector, \
SentrySWReturnType, \
_SentrySWWrapArg(SentrySWArguments), \
_SentrySWWrapArg(SentrySWReplacement))
#pragma mark - Main API
/**
A function pointer to the original implementation of the swizzled method.
*/
typedef void (*SentrySwizzleOriginalIMP)(void /* id, SEL, ... */);
/**
SentrySwizzleInfo is used in the new implementation block to get and call original implementation of the swizzled method.
*/
@interface SentrySwizzleInfo : NSObject
/**
Returns the original implementation of the swizzled method.
It is actually either an original implementation if the swizzled class implements the method itself; or a super implementation fetched from one of the superclasses.
@note You must always cast returned implementation to the appropriate function pointer when calling.
@return A function pointer to the original implementation of the swizzled method.
*/
- (SentrySwizzleOriginalIMP)getOriginalImplementation;
/// The selector of the swizzled method.
@property(nonatomic, readonly) SEL selector;
@end
/**
A factory block returning the block for the new implementation of the swizzled method.
You must always obtain original implementation with swizzleInfo and call it from the new implementation.
@param swizzleInfo An info used to get and call the original implementation of the swizzled method.
@return A block that implements a method.
Its signature should be: `method_return_type ^(id self, method_args...)`.
The selector is not available as a parameter to this block.
*/
typedef id (^SentrySwizzleImpFactoryBlock)(SentrySwizzleInfo *swizzleInfo);
typedef NS_ENUM(NSUInteger, SentrySwizzleMode) {
/// SentrySwizzle always does swizzling.
SentrySwizzleModeAlways = 0,
/// SentrySwizzle does not do swizzling if the same class has been swizzled earlier with the same key.
SentrySwizzleModeOncePerClass = 1,
/// SentrySwizzle does not do swizzling if the same class or one of its superclasses have been swizzled earlier with the same key.
/// @note There is no guarantee that your implementation will be called only once per method call. If the order of swizzling is: first inherited class, second superclass, then both swizzlings will be done and the new implementation will be called twice.
SentrySwizzleModeOncePerClassAndSuperclasses = 2
};
@interface SentrySwizzle : NSObject
#pragma mark └ Swizzle Instance Method
/**
Swizzles the instance method of the class with the new implementation.
Original implementation must always be called from the new implementation. And because of the the fact that for safe and robust swizzling original implementation must be dynamically fetched at the time of calling and not at the time of swizzling, swizzling API is a little bit complicated.
You should pass a factory block that returns the block for the new implementation of the swizzled method. And use swizzleInfo argument to retrieve and call original implementation.
Example for swizzling `-(int)calculate:(int)number;` method:
@code
SEL selector = @selector(calculate:);
[SentrySwizzle
swizzleInstanceMethod:selector
inClass:classToSwizzle
newImpFactory:^id(SentrySwizzleInfo *swizzleInfo) {
// This block will be used as the new implementation.
return ^int(__unsafe_unretained id self, int num){
// You MUST always cast implementation to the correct function pointer.
int (*originalIMP)(__unsafe_unretained id, SEL, int);
originalIMP = (__typeof(originalIMP))[swizzleInfo getOriginalImplementation];
// Calling original implementation.
int res = originalIMP(self,selector,num);
// Returning modified return value.
return res + 1;
};
}
mode:SentrySwizzleModeAlways
key:NULL];
@endcode
Swizzling frequently goes along with checking whether this particular class (or one of its superclasses) has been already swizzled. Here the `mode` and `key` parameters can help.
Here is an example of swizzling `-(void)dealloc;` only in case when neither class and no one of its superclasses has been already swizzled with our key. However "Deallocating ..." message still may be logged multiple times per method call if swizzling was called primarily for an inherited class and later for one of its superclasses.
@code
static const void *key = &key;
SEL selector = NSSelectorFromString(@"dealloc");
[SentrySwizzle
swizzleInstanceMethod:selector
inClass:classToSwizzle
newImpFactory:^id(SentrySwizzleInfo *swizzleInfo) {
return ^void(__unsafe_unretained id self){
NSLog(@"Deallocating %@.",self);
void (*originalIMP)(__unsafe_unretained id, SEL);
originalIMP = (__typeof(originalIMP))[swizzleInfo getOriginalImplementation];
originalIMP(self,selector);
};
}
mode:SentrySwizzleModeOncePerClassAndSuperclasses
key:key];
@endcode
Swizzling is fully thread-safe.
@param selector Selector of the method that should be swizzled.
@param classToSwizzle The class with the method that should be swizzled.
@param factoryBlock The factory block returning the block for the new implementation of the swizzled method.
@param mode The mode is used in combination with the key to indicate whether the swizzling should be done for the given class.
@param key The key is used in combination with the mode to indicate whether the swizzling should be done for the given class. May be NULL if the mode is SentrySwizzleModeAlways.
@return YES if successfully swizzled and NO if swizzling has been already done for given key and class (or one of superclasses, depends on the mode).
*/
+ (BOOL)swizzleInstanceMethod:(SEL)selector
inClass:(Class)classToSwizzle
newImpFactory:(SentrySwizzleImpFactoryBlock)factoryBlock
mode:(SentrySwizzleMode)mode
key:(const void *)key;
#pragma mark └ Swizzle Class method
/**
Swizzles the class method of the class with the new implementation.
Original implementation must always be called from the new implementation. And because of the the fact that for safe and robust swizzling original implementation must be dynamically fetched at the time of calling and not at the time of swizzling, swizzling API is a little bit complicated.
You should pass a factory block that returns the block for the new implementation of the swizzled method. And use swizzleInfo argument to retrieve and call original implementation.
Example for swizzling `+(int)calculate:(int)number;` method:
@code
SEL selector = @selector(calculate:);
[SentrySwizzle
swizzleClassMethod:selector
inClass:classToSwizzle
newImpFactory:^id(SentrySwizzleInfo *swizzleInfo) {
// This block will be used as the new implementation.
return ^int(__unsafe_unretained id self, int num){
// You MUST always cast implementation to the correct function pointer.
int (*originalIMP)(__unsafe_unretained id, SEL, int);
originalIMP = (__typeof(originalIMP))[swizzleInfo getOriginalImplementation];
// Calling original implementation.
int res = originalIMP(self,selector,num);
// Returning modified return value.
return res + 1;
};
}];
@endcode
Swizzling is fully thread-safe.
@param selector Selector of the method that should be swizzled.
@param classToSwizzle The class with the method that should be swizzled.
@param factoryBlock The factory block returning the block for the new implementation of the swizzled method.
*/
+ (void)swizzleClassMethod:(SEL)selector
inClass:(Class)classToSwizzle
newImpFactory:(SentrySwizzleImpFactoryBlock)factoryBlock;
@end
#pragma mark - Implementation details
// Do not write code that depends on anything below this line.
// Wrapping arguments to pass them as a single argument to another macro.
#define _SentrySWWrapArg(args...) args
#define _SentrySWDel2Arg(a1, a2, args...) a1, ##args
#define _SentrySWDel3Arg(a1, a2, a3, args...) a1, a2, ##args
// To prevent comma issues if there are no arguments we add one dummy argument
// and remove it later.
#define _SentrySWArguments(arguments...) DEL, ##arguments
#define _SentrySwizzleInstanceMethod(classToSwizzle, \
selector, \
SentrySWReturnType, \
SentrySWArguments, \
SentrySWReplacement, \
SentrySwizzleMode, \
KEY) \
[SentrySwizzle \
swizzleInstanceMethod:selector \
inClass:[classToSwizzle class] \
newImpFactory:^id(SentrySwizzleInfo *swizzleInfo) { \
SentrySWReturnType (*originalImplementation_)(_SentrySWDel3Arg(__unsafe_unretained id, \
SEL, \
SentrySWArguments)); \
SEL selector_ = selector; \
return ^SentrySWReturnType (_SentrySWDel2Arg(__unsafe_unretained id self, \
SentrySWArguments)) \
{ \
SentrySWReplacement \
}; \
} \
mode:SentrySwizzleMode \
key:KEY];
#define _SentrySwizzleClassMethod(classToSwizzle, \
selector, \
SentrySWReturnType, \
SentrySWArguments, \
SentrySWReplacement) \
[SentrySwizzle \
swizzleClassMethod:selector \
inClass:[classToSwizzle class] \
newImpFactory:^id(SentrySwizzleInfo *swizzleInfo) { \
SentrySWReturnType (*originalImplementation_)(_SentrySWDel3Arg(__unsafe_unretained id, \
SEL, \
SentrySWArguments)); \
SEL selector_ = selector; \
return ^SentrySWReturnType (_SentrySWDel2Arg(__unsafe_unretained id self, \
SentrySWArguments)) \
{ \
SentrySWReplacement \
}; \
}];
#define _SentrySWCallOriginal(arguments...) \
((__typeof(originalImplementation_))[swizzleInfo \
getOriginalImplementation])(self, \
selector_, \
##arguments)

View File

@ -1,61 +0,0 @@
//
// SentryThread.h
// Sentry
//
// Created by Daniel Griesser on 05/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#import <Sentry/SentrySerializable.h>
#else
#import "SentryDefines.h"
#import "SentrySerializable.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@class SentryStacktrace;
NS_SWIFT_NAME(Thread)
@interface SentryThread : NSObject <SentrySerializable>
SENTRY_NO_INIT
/**
* Number of the thread
*/
@property(nonatomic, copy) NSNumber *threadId;
/**
* Name (if available) of the thread
*/
@property(nonatomic, copy) NSString *_Nullable name;
/**
* SentryStacktrace of the SentryThread
*/
@property(nonatomic, strong) SentryStacktrace *_Nullable stacktrace;
/**
* Did this thread crash?
*/
@property(nonatomic, copy) NSNumber *_Nullable crashed;
/**
* Was it the current thread.
*/
@property(nonatomic, copy) NSNumber *_Nullable current;
/**
* Initializes a SentryThread with its id
* @param threadId NSNumber
* @return SentryThread
*/
- (instancetype)initWithThreadId:(NSNumber *)threadId;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,56 +0,0 @@
//
// SentryUser.h
// Sentry
//
// Created by Daniel Griesser on 05/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#import <Sentry/SentrySerializable.h>
#else
#import "SentryDefines.h"
#import "SentrySerializable.h"
#endif
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(User)
@interface SentryUser : NSObject <SentrySerializable>
/**
* Optional: Id of the user
*/
@property(nonatomic, copy) NSString *userId;
/**
* Optional: Email of the user
*/
@property(nonatomic, copy) NSString *_Nullable email;
/**
* Optional: Username
*/
@property(nonatomic, copy) NSString *_Nullable username;
/**
* Optional: Additional data
*/
@property(nonatomic, strong) NSDictionary<NSString *, id> *_Nullable extra;
/**
* Initializes a SentryUser with the id
* @param userId NSString
* @return SentryUser
*/
- (instancetype)initWithUserId:(NSString *)userId;
- (instancetype)init;
+ (instancetype)new NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,25 +0,0 @@
framework module Sentry {
umbrella header "Sentry.h"
export *
module * { export * }
explicit module Private {
header "SentryDsn.h"
header "SentryClient+Internal.h"
header "SentryError.h"
header "SentryAsynchronousOperation.h"
header "SentryRequestOperation.h"
header "SentryQueueableRequestManager.h"
header "SentryKSCrashInstallation.h"
header "SentryKSCrashReportSink.h"
header "SentryKSCrashReportConverter.h"
header "SentryLog.h"
header "SentryBreadcrumbTracker.h"
header "SentryCrashExceptionApplication.h"
header "NSData+Compression.h"
header "NSDate+Extras.h"
header "NSDictionary+Sanitize.h"
}
}

View File

@ -1,20 +0,0 @@
//
// NSData+Compression.h
// Sentry
//
// Created by Daniel Griesser on 08/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSData (Compression)
- (NSData *_Nullable)sentry_gzippedWithCompressionLevel:(NSInteger)compressionLevel
error:(NSError *_Nullable *_Nullable)error;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,21 +0,0 @@
//
// NSDate+Extras.h
// Sentry
//
// Created by Daniel Griesser on 19/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSDate (Extras)
+ (NSDate *)sentry_fromIso8601String:(NSString *)string;
- (NSString *)sentry_toIso8601String;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,15 +0,0 @@
//
// NSDictionary+Sanitize.h
// Sentry
//
// Created by Daniel Griesser on 16/06/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSDictionary (Sanitize)
- (NSDictionary *)sentry_sanitize;
@end

View File

@ -1,19 +0,0 @@
//
// SentryAsynchronousOperation.h
// Sentry
//
// Created by Daniel Griesser on 05/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SentryAsynchronousOperation : NSOperation
- (void)completeOperation;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,15 +0,0 @@
//
// SentryBreadcrumbTracker.h
// Sentry
//
// Created by Daniel Griesser on 31/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SentryBreadcrumbTracker : NSObject
- (void)start;
@end

View File

@ -1,25 +0,0 @@
//
// SentryClient+Internal.h
// Sentry
//
// Created by Daniel Griesser on 01/06/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryClient.h>
#import <Sentry/SentryDebugMeta.h>
#else
#import "SentryClient.h"
#import "SentryDebugMeta.h"
#endif
@interface SentryClient ()
@property(nonatomic, strong) NSArray<SentryThread *> *_Nullable _snapshotThreads;
@property(nonatomic, strong) NSArray<SentryDebugMeta *> *_Nullable _debugMeta;
@end

View File

@ -1,23 +0,0 @@
//
// SentryDsn.h
// Sentry
//
// Created by Daniel Griesser on 03/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SentryDsn : NSObject
@property(nonatomic, strong) NSURL *url;
- (_Nullable instancetype)initWithString:(NSString *)dsnString didFailWithError:(NSError *_Nullable *_Nullable)error;
- (NSString *)getHash;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,37 +0,0 @@
//
// SentryError.h
// Sentry
//
// Created by Daniel Griesser on 03/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#else
#import "SentryDefines.h"
#endif
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, SentryError) {
kSentryErrorUnknownError = -1,
kSentryErrorInvalidDsnError = 100,
kSentryErrorKSCrashNotInstalledError = 101,
kSentryErrorInvalidCrashReportError = 102,
kSentryErrorCompressionError = 103,
kSentryErrorJsonConversionError = 104,
kSentryErrorCouldNotFindDirectory = 105,
kSentryErrorRequestError = 106,
kSentryErrorEventNotSent = 107,
};
SENTRY_EXTERN NSError *_Nullable NSErrorFromSentryError(SentryError error, NSString *description);
SENTRY_EXTERN NSString *const SentryErrorDomain;
NS_ASSUME_NONNULL_END

View File

@ -1,52 +0,0 @@
//
// SentryFileManager.h
// Sentry
//
// Created by Daniel Griesser on 23/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#else
#import "SentryDefines.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@class SentryEvent, SentryBreadcrumb, SentryDsn;
@interface SentryFileManager : NSObject
SENTRY_NO_INIT
- (_Nullable instancetype)initWithDsn:(SentryDsn *)dsn didFailWithError:(NSError **)error;
- (NSString *)storeEvent:(SentryEvent *)event;
- (NSString *)storeEvent:(SentryEvent *)event maxCount:(NSUInteger)maxCount;
- (NSString *)storeBreadcrumb:(SentryBreadcrumb *)crumb;
- (NSString *)storeBreadcrumb:(SentryBreadcrumb *)crumb maxCount:(NSUInteger)maxCount;
+ (BOOL)createDirectoryAtPath:(NSString *)path withError:(NSError **)error;
- (void)deleteAllStoredEvents;
- (void)deleteAllStoredBreadcrumbs;
- (void)deleteAllFolders;
- (NSArray<NSDictionary<NSString *, id> *> *)getAllStoredEvents;
- (NSArray<NSDictionary<NSString *, id> *> *)getAllStoredBreadcrumbs;
- (BOOL)removeFileAtPath:(NSString *)path;
- (NSArray<NSString *> *)allFilesInFolder:(NSString *)path;
- (NSString *)storeDictionary:(NSDictionary *)dictionary toPath:(NSString *)path;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,28 +0,0 @@
//
// SentryKSCrashInstallation.h
// Sentry
//
// Created by Daniel Griesser on 10/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<KSCrash/KSCrash.h>)
#import <KSCrash/KSCrash.h>
#import <KSCrash/KSCrashInstallation.h>
#elif __has_include("KSCrash.h")
#import "KSCrash.h"
#import "KSCrashInstallation.h"
#endif
#if WITH_KSCRASH
@interface SentryKSCrashInstallation : KSCrashInstallation
#else
@interface SentryKSCrashInstallation : NSObject
#endif
- (void)sendAllReports;
@end

View File

@ -1,25 +0,0 @@
//
// SentryKSCrashReportConverter.h
// Sentry
//
// Created by Daniel Griesser on 10/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
@class SentryEvent;
NS_ASSUME_NONNULL_BEGIN
@interface SentryKSCrashReportConverter : NSObject
@property(nonatomic, strong) NSDictionary *userContext;
- (instancetype)initWithReport:(NSDictionary *)report;
- (SentryEvent *)convertReportToEvent;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,24 +0,0 @@
//
// SentryKSCrashReportSink.h
// Sentry
//
// Created by Daniel Griesser on 10/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<KSCrash/KSCrash.h>)
#import <KSCrash/KSCrash.h>
#elif __has_include("KSCrash.h")
#import "KSCrash.h"
#endif
#if WITH_KSCRASH
@interface SentryKSCrashReportSink : NSObject <KSCrashReportFilter>
#else
@interface SentryKSCrashReportSink : NSObject
#endif
@end

View File

@ -1,27 +0,0 @@
//
// SentryLog.h
// Sentry
//
// Created by Daniel Griesser on 02/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#else
#import "SentryDefines.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@interface SentryLog : NSObject
+ (void)logWithMessage:(NSString *)message andLevel:(SentryLogLevel)level;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,37 +0,0 @@
//
// SentryQueueableRequestManager.h
// Sentry
//
// Created by Daniel Griesser on 05/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryDefines.h>
#else
#import "SentryDefines.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@protocol SentryRequestManager
@property(nonatomic, readonly, getter = isReady) BOOL ready;
- (instancetype)initWithSession:(NSURLSession *)session;
- (void)addRequest:(NSURLRequest *)request completionHandler:(_Nullable SentryRequestOperationFinished)completionHandler;
- (void)cancelAllOperations;
@end
@interface SentryQueueableRequestManager : NSObject <SentryRequestManager>
@end
NS_ASSUME_NONNULL_END

View File

@ -1,30 +0,0 @@
//
// SentryRequestOperation.h
// Sentry
//
// Created by Daniel Griesser on 05/05/2017.
// Copyright © 2017 Sentry. All rights reserved.
//
#import <Foundation/Foundation.h>
#if __has_include(<Sentry/Sentry.h>)
#import <Sentry/SentryQueueableRequestManager.h>
#import <Sentry/SentryAsynchronousOperation.h>
#else
#import "SentryQueueableRequestManager.h"
#import "SentryAsynchronousOperation.h"
#endif
NS_ASSUME_NONNULL_BEGIN
@interface SentryRequestOperation : SentryAsynchronousOperation
- (instancetype)initWithSession:(NSURLSession *)session request:(NSURLRequest *)request
completionHandler:(_Nullable SentryRequestOperationFinished)completionHandler;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,211 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
## Runtime Library Exception to the Apache 2.0 License: ##
As an exception, if you use this Software to compile your source code and
portions of this Software are embedded into the binary product as a result,
you may redistribute such product without providing attribution as would
otherwise be required by Sections 4(a), 4(b) and 4(d) of the License.

View File

@ -1,5 +1,13 @@
import Foundation
import xcbuddykit
<<<<<<< HEAD
var registry = CommandRegistry()
=======
let errorHandler = ErrorHandler()
var registry = CommandRegistry(usage: "<command> <options>", overview: "Your Xcode buddy", errorHandler: CommandLineErrorHandler(errorHandler: errorHandler))
registry.register(command: InitCommand.self)
registry.register(command: UpdateCommand.self)
registry.register(command: DumpCommand.self)
>>>>>>> [error-handler] Replace Sentry with Bugsnag
registry.run()

View File

@ -13,9 +13,13 @@ public final class CommandRegistry {
// Registered commands.
var commands: [Command] = []
/// Error handler.
let errorHandler: CommandLineErrorHandling
/// Returns the process arguments.
private let processArguments: () -> [String]
<<<<<<< HEAD
/// Initializes the command registry
public init(processArguments: @escaping () -> [String] = CommandRegistry.processArguments) {
printer = Printer()
@ -26,6 +30,21 @@ public final class CommandRegistry {
register(command: GenerateCommand.self)
register(command: UpdateCommand.self)
register(command: DumpCommand.self)
=======
/// Initialies the registry.
///
/// - Parameters:
/// - usage: tool usage.
/// - errorHandler: error handler.
/// - overview: tool overview.
public init(usage: String,
overview: String,
errorHandler: CommandLineErrorHandling,
processArguments: @escaping () -> [String] = CommandRegistry.processArguments) {
parser = ArgumentParser(usage: usage, overview: overview)
self.processArguments = processArguments
self.errorHandler = errorHandler
>>>>>>> [error-handler] Replace Sentry with Bugsnag
}
/// Returns the process arguments
@ -44,9 +63,10 @@ public final class CommandRegistry {
/// Runs the command line interface.
public func run() {
do {
errorHandler.run {
let parsedArguments = try parse()
try process(arguments: parsedArguments)
<<<<<<< HEAD
} catch let error as ArgumentParserError {
printer.print(errorMessage: error.localizedDescription)
exit(1)
@ -56,6 +76,8 @@ public final class CommandRegistry {
} catch {
printer.print(errorMessage: error.localizedDescription)
exit(1)
=======
>>>>>>> [error-handler] Replace Sentry with Bugsnag
}
}

View File

@ -0,0 +1,14 @@
import Foundation
/// Buildify errors.
///
/// - abort: prints the message and exits 1.
/// - bug: like abort but reporting the bug to Sentry.
/// - abortSilent: like abort but without printing anything.
/// - bugSilent: like bug but without printing anything.
enum BuildifyError: Error {
case abort(Error)
case bug(Error)
case abortSilent(Error)
case bugSilent(Error)
}

View File

@ -0,0 +1,44 @@
import Foundation
/// Command line error handling.
public protocol CommandLineErrorHandling: AnyObject {
func run(action: () throws -> ())
}
/// Utility class that handles errors thrown from the commands.
/// It parses the errors and reports/prints them accordingly.
public class CommandLineErrorHandler: CommandLineErrorHandling {
/// Error handler.
let errorHandler: ErrorHandling
/// Printer.
let printer: Printing
/// Initializes the handler with the tech logger.
///
/// - Parameter errorHandler: error handler.
public convenience init(errorHandler: ErrorHandling) {
self.init(errorHandler: errorHandler, printer: Printer())
}
/// Initializes the handler with its attributes.
///
/// - Parameters:
/// - errorHandler: error handler.
/// - printer: printer.
init(errorHandler: ErrorHandling,
printer: Printing = Printer()) {
self.errorHandler = errorHandler
self.printer = printer
}
public func run(action: () throws -> ()) {
do {
try action()
} catch {
}
}
}

View File

@ -0,0 +1,27 @@
import Foundation
import Bugsnag
public protocol ErrorHandling: AnyObject {
}
fileprivate var started: Bool = false
public class ErrorHandler: ErrorHandling {
public init() {
Bugsnag.notifyError(NSError.init(domain: "domain", code: 0, userInfo: nil))
if !started {
if let apiKey = Bundle.main.object(forInfoDictionaryKey: "BUGSNAG_API_KEY") as? String {
Bugsnag.start(withApiKey: apiKey)
}
started = true
}
}
func notify(error: Error) {
if !started { return }
Bugsnag.notifyError(error)
}
}

1
Cartfile Normal file
View File

@ -0,0 +1 @@
github "bugsnag/bugsnag-cocoa"

1
Cartfile.resolved Normal file
View File

@ -0,0 +1 @@
github "bugsnag/bugsnag-cocoa" "v5.15.4"

View File

@ -102,6 +102,10 @@ def docs
execute("bundle exec jazzy")
end
def carthage
execute("carthage update; carthage build --platform macos")
end
def release
branch = `git rev-parse --abbrev-ref HEAD`.strip
unless branch.include?("version/")
@ -149,6 +153,11 @@ task :test do
test
end
desc 'Fetches Carthage dependencies'
task :carthage do
carthage
end
desc 'Releases a new version of the app'
task :release do
release