Merge branch 'release/v1.0-beta.7'

This commit is contained in:
Christoph Wendt 2016-02-03 15:27:18 -08:00
Родитель 83a333169f 6ff840c2a3
Коммит a8cfe39931
121 изменённых файлов: 402 добавлений и 7961 удалений

Просмотреть файл

@ -1,5 +1,5 @@
language: objective-c
osx_image: xcode6.4
osx_image: xcode7.2
env:
global:
@ -7,13 +7,10 @@ env:
- SDK="iphonesimulator"
matrix:
- SCHEME="ApplicationInsights" DESTINATION="OS=7.1,name=iPad 2" CONFIGURATION="Debug" RUN_TESTS="YES" POD_LINT="NO" XCODEBUILD_GCC_PREPROCESSOR_DEFINITIONS="CI=1"
- SCHEME="ApplicationInsights" DESTINATION="OS=7.1,name=iPhone 5" CONFIGURATION="Debug" RUN_TESTS="YES" POD_LINT="NO" XCODEBUILD_GCC_PREPROCESSOR_DEFINITIONS="CI=1"
- SCHEME="ApplicationInsights" DESTINATION="OS=8.2,name=iPhone 6" CONFIGURATION="Debug" RUN_TESTS="YES" POD_LINT="NO" XCODEBUILD_GCC_PREPROCESSOR_DEFINITIONS="CI=1"
- SCHEME="ApplicationInsights" DESTINATION="OS=8.3,name=iPhone 6 Plus" CONFIGURATION="Debug" RUN_TESTS="YES" POD_LINT="NO" XCODEBUILD_GCC_PREPROCESSOR_DEFINITIONS="CI=1"
- SCHEME="ApplicationInsights Framework" CONFIGURATION="Release" RUN_TESTS="NO" POD_LINT="NO" XCODEBUILD_GCC_PREPROCESSOR_DEFINITIONS="MSAI_FEATURE_TELEMETRY=0 MSAI_FEATURE_CRASH_REPORTER=0"
- SCHEME="ApplicationInsights Framework" CONFIGURATION="Release" RUN_TESTS="NO" POD_LINT="NO" XCODEBUILD_GCC_PREPROCESSOR_DEFINITIONS="MSAI_FEATURE_TELEMETRY=1 MSAI_FEATURE_CRASH_REPORTER=0"
- SCHEME="ApplicationInsights Framework" CONFIGURATION="Release" RUN_TESTS="NO" POD_LINT="NO" XCODEBUILD_GCC_PREPROCESSOR_DEFINITIONS="MSAI_FEATURE_TELEMETRY=0 MSAI_FEATURE_CRASH_REPORTER=1"
- SCHEME="ApplicationInsights" DESTINATION="OS=9.1,name=iPad Air 2" CONFIGURATION="Debug" RUN_TESTS="YES" POD_LINT="NO" XCODEBUILD_GCC_PREPROCESSOR_DEFINITIONS="CI=1"
- SCHEME="ApplicationInsights" DESTINATION="OS=9.2,name=iPhone 5" CONFIGURATION="Debug" RUN_TESTS="YES" POD_LINT="NO" XCODEBUILD_GCC_PREPROCESSOR_DEFINITIONS="CI=1"
- SCHEME="ApplicationInsights Framework" CONFIGURATION="Release" RUN_TESTS="NO" POD_LINT="YES"
before_install:

Просмотреть файл

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "ApplicationInsights"
s.version = "1.0-beta.6"
s.version = "1.0-beta.7"
s.summary = "Microsoft Application Insights SDK for iOS"
s.description = <<-DESC
Application Insights is a service that allows developers to keep their applications available, performant, and successful.
@ -15,9 +15,9 @@ Pod::Spec.new do |s|
s.platform = :ios, '6.0'
s.requires_arc = true
s.frameworks = 'UIKit', 'Foundation', 'SystemConfiguration', 'Security', 'CoreTelephony'
s.libraries = 'z', 'c++'
s.frameworks = 'CoreTelephony', 'UIKit', 'Foundation', 'SystemConfiguration', 'Security'
s.libraries = 'z'
s.ios.vendored_frameworks = 'ApplicationInsights/ApplicationInsights.framework'
s.preserve_path = 'ApplicationInsights/README.md'
s.vendored_frameworks = 'ApplicationInsights/ApplicationInsights/ApplicationInsights.framework'
end

Просмотреть файл

@ -1,3 +1,13 @@
## 1.0-beta.7 (3/2/2016)
**Crash Reporting and the API to send handled exceptions have been removed from the SDK. In addition, the Application Insights for iOS SDK is now deprecated.**
The reason for this is that [HockeyApp](http://hockeyapp.net/) is now our major offering for mobile and cross-plattform crash reporting, beta distribution and user feedback. We are focusing all our efforts on enhancing the HockeySDK and adding telemetry features to make HockeyApp the best platform to build awesome apps. We've launched [HockeyApp Preseason](http://hockeyapp.net/blog/2016/02/02/introducing-preseason.html) so you can try all the new bits yourself, including User Metrics.
* Remove crash reporting. To add this feature to your app, we recommend to use [HockeyApp](http://hockeyapp.net/features/) which provides you with superior crash reporting, feedback, beta distribution and much more.
* Enable Bitcode. This was previously not possible as Bitcode-enabled apps are recompiled at unknown times on Apple's servers and make it very hard to get fully symbolicated and useful crash reports.
* Fixes an issue where pageview durations where incorrectly sent as days instead of as a string in the 'd:hh:mm:ss.fffffff' format. The relevant methods now take an `NSTimeInterval` parameter with the duration in seconds.
## 1.0-beta.6 (7/8/2015)
* Add CHANGELOG.md

Просмотреть файл

@ -1,13 +1,7 @@
#import "ApplicationInsightsFeatureConfig.h"
#import "MSAINullability.h"
#import "MSAIApplicationInsights.h"
#if MSAI_FEATURE_CRASH_REPORTER
#import "MSAICrashManager.h"
#import "MSAICrashManagerDelegate.h"
#endif /* MSAI_FEATURE_CRASH_REPORTER */
#if MSAI_FEATURE_TELEMETRY
#import "MSAITelemetryManager.h"
#endif /* MSAI_FEATURE_TELEMETRY */
@ -16,43 +10,3 @@
#define MSAINetworkDidBecomeReachableNotification @"MSAINetworkDidBecomeReachable"
#define MSAI_SERVER_URL @"https://dc.services.visualstudio.com/v2/track"
#if MSAI_FEATURE_CRASH_REPORTER
NS_ASSUME_NONNULL_BEGIN
/**
* MSAI Crash Reporter error domain
*/
typedef NS_ENUM (NSInteger, MSAICrashErrorReason) {
/**
* Unknown error
*/
MSAICrashErrorUnknown,
/**
* API Server rejected app version
*/
MSAICrashAPIAppVersionRejected,
/**
* API Server returned empty response
*/
MSAICrashAPIReceivedEmptyResponse,
/**
* Connection error with status code
*/
MSAICrashAPIErrorWithStatusCode
};
FOUNDATION_EXPORT NSString *const __unused kMSAICrashErrorDomain;
/**
* MSAI global error domain
*/
typedef NS_ENUM(NSInteger, MSAIErrorReason) {
/**
* Unknown error
*/
MSAIErrorUnknown
};
extern NSString *const __unused kMSAIErrorDomain;
NS_ASSUME_NONNULL_END
#endif /* MSAI_FEATURE_CRASH_REPORTER */

Просмотреть файл

@ -1,17 +1,6 @@
#ifndef MSAI_FeatureConfig_h
#define MSAI_FeatureConfig_h
/**
* If true, include support for handling crash reports
*
* _Default_: Disabled
*/
#ifndef MSAI_FEATURE_CRASH_REPORTER
# define MSAI_FEATURE_CRASH_REPORTER 1
#endif /* MSAI_FEATURE_CRASH_REPORTER */
/**
* If true, include support for gathering telemetry
*

Просмотреть файл

@ -7,16 +7,6 @@ NS_ASSUME_NONNULL_BEGIN
FOUNDATION_EXPORT NSString *const kMSAIName;
FOUNDATION_EXPORT NSString *const kMSAIIdentifier;
FOUNDATION_EXPORT NSString *const kMSAICrashSettings;
FOUNDATION_EXPORT NSString *const kMSAICrashAnalyzer;
#if MSAI_FEATURE_TELEMETRY
FOUNDATION_EXPORT NSString *const __unused kMSAITelemetryCachesSessions;
FOUNDATION_EXPORT NSString *const __unused kMSAITelemetryTempSessionData;
FOUNDATION_EXPORT NSString *const __unused kMSAITelemetryLastAppVersion;
#endif /* MSAI_FEATURE_METRICS */
FOUNDATION_EXPORT NSString *const kMSAIIntegrationflowTimestamp;

Просмотреть файл

@ -3,9 +3,4 @@
NSString *const kMSAIName = @"ApplicationInsights";
NSString *const kMSAIIdentifier = @"com.microsoft.applicationinsights.ios";
NSString *const kMSAICrashSettings = @"MSAICrashManager.plist";
NSString *const kMSAICrashAnalyzer = @"MSAICrashManager.analyzer";
NSString *const kMSAICrashErrorDomain = @"MSAICrashReporterErrorDomain";
NSString *const kMSAIErrorDomain = @"MSAIErrorDomain";

Просмотреть файл

@ -83,26 +83,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, copy) NSString *serverURL;
#if MSAI_FEATURE_CRASH_REPORTER
/**
* Flag which determines whether the Crash Manager should be disabled. If this flag is
* enabled, then crash reporting is disabled and no crashes will be send. Please note
* that the Crash Manager instance will be initialized anyway, but crash report
* handling (signal and uncaught exception handlers) will **not** be registered.
*
* @warning This property needs to be set before calling `start`
*/
@property (nonatomic, getter = isCrashManagerDisabled) BOOL crashManagerDisabled;
/**
* Enable (NO) or disable (YES) the crash manager. This should be called before `start`.
*
* @param crashManagerDisabled Flag which determines whether the Crash Manager should be disabled
*/
+ (void)setCrashManagerDisabled:(BOOL)crashManagerDisabled;
#endif /* MSAI_FEATURE_CRASH_REPORTER */
#if MSAI_FEATURE_TELEMETRY
/**
* Flag that determines whether the Telemetry Manager should be disabled.
@ -207,7 +187,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* This starts a new session with the given session ID.
*
* @param sessionId The session ID which should be attached to all future telemetry and crash events.
* @param sessionId The session ID which should be attached to all future telemetry events.
*
* @warning Using this method automatically disables automatic session management!
* @see autoSessionManagementDisabled
@ -217,7 +197,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* This starts a new session with the given session ID.
*
* @param sessionId The session ID which should be attached to all future telemetry and crash events.
* @param sessionId The session ID which should be attached to all future telemetry events.
*
* @warning Using this method automatically disables automatic session management!
* @see autoSessionManagementDisabled

Просмотреть файл

@ -18,11 +18,6 @@
#include <stdint.h>
#import "MSAICategoryContainer.h"
#if MSAI_FEATURE_CRASH_REPORTER
#import "MSAICrashManager.h"
#import "MSAICrashManagerPrivate.h"
#endif /* MSAI_FEATURE_CRASH_REPORTER */
#if MSAI_FEATURE_TELEMETRY
#import "MSAITelemetryManager.h"
#import "MSAITelemetryManagerPrivate.h"
@ -57,9 +52,6 @@ NSString *const kMSAIInstrumentationKey = @"MSAIInstrumentationKey";
_serverURL = nil;
_managersInitialized = NO;
_appClient = nil;
#if MSAI_FEATURE_CRASH_REPORTER
_crashManagerDisabled = NO;
#endif /* MSAI_FEATURE_CRASH_REPORTER */
#if MSAI_FEATURE_TELEMETRY
_telemetryManagerDisabled = NO;
#endif /* MSAI_FEATURE_TELEMETRY */
@ -112,14 +104,6 @@ NSString *const kMSAIInstrumentationKey = @"MSAIInstrumentationKey";
[[MSAISender sharedSender] sendSavedData];
#if MSAI_FEATURE_CRASH_REPORTER
if (![self isCrashManagerDisabled]) {
MSAILog(@"INFO: Starting MSAICrashManager");
[MSAICrashManager sharedManager].isCrashManagerDisabled = self.isCrashManagerDisabled;
[[MSAICrashManager sharedManager] startManager];
}
#endif /* MSAI_FEATURE_CRASH_REPORTER */
#if MSAI_FEATURE_TELEMETRY
if (![self isTelemetryManagerDisabled]) {
@ -230,17 +214,6 @@ NSString *const kMSAIInstrumentationKey = @"MSAIInstrumentationKey";
[[self sharedInstance] setAutoSessionManagementDisabled:autoSessionManagementDisabled];
}
#if MSAI_FEATURE_CRASH_REPORTER
- (void)setCrashManagerDisabled:(BOOL)crashManagerDisabled {
[MSAICrashManager sharedManager].isCrashManagerDisabled = crashManagerDisabled;
_crashManagerDisabled = crashManagerDisabled;
}
+ (void)setCrashManagerDisabled:(BOOL)crashManagerDisabled{
[[self sharedInstance] setCrashManagerDisabled:crashManagerDisabled];
}
#endif /* MSAI_FEATURE_CRASH_REPORTER */
- (void)setServerURL:(NSString *)serverURL {
// trailing slash is needed

Просмотреть файл

@ -101,11 +101,6 @@ static dispatch_once_t once_token;
}
}
- (void)processDictionary:(MSAIOrderedDictionary *)dictionary withCompletionBlock: (nullable void (^)(BOOL success)) completionBlock{
[[MSAIPersistence sharedInstance] persistBundle:[self serializeObjectToJSONData:dictionary]
ofType:MSAIPersistenceTypeHighPriority withCompletionBlock:completionBlock];
}
#pragma mark - Serialization Helper
- (NSString *)serializeDictionaryToJSONString:(MSAIOrderedDictionary *)dictionary {

Просмотреть файл

@ -4,10 +4,8 @@
@class MSAIEnvelope;
@class MSAITelemetryContext;
@class MSAIAppClient;
@class MSAITelemetryContext;
@class MSAITelemetryData;
@class MSAISender;
@class MSAICrashData;
@class MSAIOrderedDictionary;
NS_ASSUME_NONNULL_BEGIN
@ -48,7 +46,7 @@ FOUNDATION_EXPORT NSInteger const defaultMaxBatchCount;
@property (nonatomic, assign) NSUInteger dataItemCount;
/**
* Enqueue telemetry data (events, metrics, exceptions, traces) before processing it.
* Enqueue telemetry data (events, metrics, traces) before processing it.
*
* @param dictionary The dictionary object, which should be processed.
*/
@ -85,14 +83,6 @@ void msai_appendStringToSafeJsonStream(NSString *string, char *__nonnull*__nonnu
*/
void msai_resetSafeJsonStream(char *__nonnull*__nonnull jsonStream);
/**
* Directly process telemetry data (crashs) without enqueuing it first.
*
* @param dictionary the dictionary object to process.
* @param completionBlock the block, which should be executed after the envelope has been persisted.
*/
- (void)processDictionary:(MSAIOrderedDictionary *)dictionary withCompletionBlock:(nullable void (^)(BOOL success))completionBlock;
///-----------------------------------------------------------------------------
/// @name Batching
///-----------------------------------------------------------------------------

Просмотреть файл

@ -20,6 +20,7 @@ NSString *const kMSAIApplicationWasLaunched = @"MSAIApplicationWasLaunched";
NSString *const MSAIUserChangedNotification = @"MSAIUserChangedNotification";
NSString *const kMSAIUserInfo = @"MSAIUserInfo";
NSString *const kMSAIPersistedUser = @"MSAIPersistedUser";
NSString *const MSAISessionStartedNotification = @"MSAISessionStartedNotification";
NSString *const MSAISessionEndedNotification = @"MSAISessionEndedNotification";
@ -51,10 +52,6 @@ NSString *const kMSAISessionInfo = @"MSAISessionInfo";
_autoSessionManagementDisabled = NO;
_appBackgroundTimeBeforeSessionExpires = defaultSessionExpirationTime;
NSMutableDictionary *restoredMetaData = [[[MSAIPersistence sharedInstance] metaData] mutableCopy];
_metaData = restoredMetaData ?: @{}.mutableCopy;
_metaData[@"sessions"] = restoredMetaData[@"sessions"] ?: @{}.mutableCopy;
_metaData[@"users"] = restoredMetaData[@"users"] ?: @{}.mutableCopy;
[self registerObservers];
}
return self;
@ -74,12 +71,12 @@ NSString *const kMSAISessionInfo = @"MSAISessionInfo";
#pragma mark Manual User ID Management
- (void)setUserWithConfigurationBlock:(void (^)(MSAIUser *user))userConfigurationBlock {
MSAIUser *__block currentUser = [self userForDate:[NSDate date]];
MSAIUser *currentUser = [self loadUser];
if(!currentUser) {
currentUser = [self newUser];
}
userConfigurationBlock(currentUser);
if(!currentUser) {
@ -90,58 +87,25 @@ NSString *const kMSAISessionInfo = @"MSAISessionInfo";
}
- (void)setCurrentUser:(nonnull MSAIUser *)user {
[self addUser:user forDate:[NSDate date]];
[self saveUser:user];
[self sendUserChangedNotificationWithUserInfo:@{kMSAIUserInfo : user}];
}
- (void)addUser:(MSAIUser *)user forDate:(NSDate *)date {
NSString *timestamp = [self unixTimestampFromDate:date ?: [NSDate date]];
#pragma mark User persistence
__weak typeof(self) weakSelf = self;
dispatch_sync(self.operationsQueue, ^{
typeof(self) strongSelf = weakSelf;
NSMutableDictionary *users = strongSelf.metaData[@"users"];
users[timestamp] = user;
[[MSAIPersistence sharedInstance] persistMetaData:strongSelf.metaData];
});
- (void)saveUser:(MSAIUser *)user {
NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:user];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:encodedObject forKey:kMSAIPersistedUser];
}
- (MSAIUser *)userForDate:(NSDate *)date {
NSString *timestamp = [self unixTimestampFromDate:date];
NSMutableDictionary *users = self.metaData[@"users"];
__block MSAIUser *user = nil;
__weak typeof(self) weakSelf = self;
dispatch_sync(self.operationsQueue, ^{
typeof(self) strongSelf = weakSelf;
NSString *userKey = [strongSelf keyForTimestamp:timestamp inDictionary:users];
user = users[userKey];
});
- (MSAIUser *)loadUser {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *encodedObject = [defaults objectForKey:kMSAIPersistedUser];
MSAIUser *user = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];
return user;
}
- (BOOL)removeUserId:(NSString *)userId {
BOOL __block success = NO;
__weak typeof(self) weakSelf = self;
dispatch_sync(self.operationsQueue, ^{
typeof(self) strongSelf = weakSelf;
NSMutableDictionary *users = self.metaData[@"users"];
[users enumerateKeysAndObjectsUsingBlock:^(NSString *blockTimestamp, MSAIUser *blockUser, BOOL *stop) {
if([blockUser.userId isEqualToString:userId]) {
[users removeObjectForKey:blockTimestamp];
success = YES;
*stop = YES;
}
}];
[[MSAIPersistence sharedInstance] persistMetaData:strongSelf.metaData];
});
return success;
}
#pragma mark - Sessions
#pragma mark Session Creation
@ -244,65 +208,15 @@ NSString *const kMSAISessionInfo = @"MSAISessionInfo";
- (void)renewSessionWithId:(NSString *)sessionId {
MSAISession *session = [self newSessionWithId:sessionId];
[self addSession:session withDate:[NSDate date]];
NSDictionary *userInfo = @{kMSAISessionInfo : session};
[self sendSessionStartedNotificationWithUserInfo:userInfo];
}
- (void)addSession:(MSAISession *)session withDate:(NSDate *)date {
NSString *timestamp = [self unixTimestampFromDate:date];
__weak typeof(self) weakSelf = self;
dispatch_sync(self.operationsQueue, ^{
typeof(self) strongSelf = weakSelf;
NSMutableDictionary *sessions = strongSelf.metaData[@"sessions"];
sessions[timestamp] = session;
[[MSAIPersistence sharedInstance] persistMetaData:strongSelf.metaData];
});
}
- (MSAISession *)sessionForDate:(NSDate *)date {
NSString *timestamp = [self unixTimestampFromDate:date];
NSMutableDictionary *sessions = self.metaData[@"sessions"];
__block MSAISession *session = nil;
__weak typeof(self) weakSelf = self;
dispatch_sync(self.operationsQueue, ^{
typeof(self) strongSelf = weakSelf;
NSString *sessionKey = [strongSelf keyForTimestamp:timestamp inDictionary:sessions];
session = [sessions valueForKey:sessionKey];
});
return session;
}
- (BOOL)removeSession:(MSAISession *)session {
BOOL __block success = NO;
__weak typeof(self) weakSelf = self;
dispatch_sync(self.operationsQueue, ^{
typeof(self) strongSelf = weakSelf;
NSMutableDictionary *sessions = self.metaData[@"sessions"];
[sessions enumerateKeysAndObjectsUsingBlock:^(NSString *blockTimestamp, MSAISession *blockSession, BOOL *stop) {
if([blockSession.sessionId isEqualToString:session.sessionId]) {
[sessions removeObjectForKey:blockTimestamp];
*stop = YES;
success = YES;
}
}];
[[MSAIPersistence sharedInstance] persistMetaData:strongSelf.metaData];
});
return success;
}
#pragma mark Session Lifecycle
- (void)startNewSession {
[self renewSessionWithId:msai_appAnonID()];
NSString *newSessionId = msai_UUID();
[self renewSessionWithId:newSessionId];
}
- (void)endSession {
@ -335,41 +249,6 @@ NSString *const kMSAISessionInfo = @"MSAISessionInfo";
});
}
#pragma mark - Cleanup Meta Data
- (void)cleanUpMetaData {
__weak typeof(self) weakSelf = self;
dispatch_sync(self.operationsQueue, ^{
typeof(self) strongSelf = weakSelf;
NSMutableDictionary *sessions = strongSelf.metaData[@"sessions"];
NSMutableDictionary *users = strongSelf.metaData[@"users"];
if(sessions.count > 1) {
// Get most recent session
NSArray *sortedKeys = [strongSelf sortedKeysOfDictionay:sessions];
NSString *recentSessionKey = sortedKeys.firstObject;
// Clear list and add most recent session
MSAISession *lastSession = sessions[recentSessionKey];
[sessions removeAllObjects];
sessions[recentSessionKey] = lastSession;
}
if(users.count > 1) {
// Get most recent session
NSArray *sortedKeys = [strongSelf sortedKeysOfDictionay:users];
NSString *recentUserKey = sortedKeys.firstObject;
// Clear list and add most recent session
MSAIUser *lastuser = users[recentUserKey];
[users removeAllObjects];
users[recentUserKey] = lastuser;
}
[[MSAIPersistence sharedInstance] persistMetaData:strongSelf.metaData];
});
}
#pragma mark - Helper
- (NSString *)unixTimestampFromDate:(NSDate *)date {

Просмотреть файл

@ -26,11 +26,6 @@ FOUNDATION_EXPORT NSString *const kMSAIApplicationWasLaunched;
*/
@property (nonatomic, strong) dispatch_queue_t operationsQueue;
/**
* A Dictionary which holds content of property list in memory.
*/
@property (nonatomic, strong) NSMutableDictionary *metaData;
/**
* This flag determines if the helper automatically renews sessions.
*/
@ -76,31 +71,18 @@ FOUNDATION_EXPORT NSString *const kMSAIApplicationWasLaunched;
- (void)setCurrentUser:(nonnull MSAIUser *)user;
/**
* Add a MSAIUser object to the automatic meta data store.
* Method that return a persited user or nil if not available.
*
* @param user Any MSAIUser object which should be stored for later reference.
* @param date The time and date when the user object started to be the current user.
* @return The persitet user instance
*/
- (void)addUser:(MSAIUser *)user forDate:(NSDate *)date;
- (MSAIUser *)loadUser;
/**
* Retrieve the latest user object for a given date.
* Method that stores a user to NSUserDefaults.
*
* @param date The date for which the user should be retrieved.
*
* @return The most current user for the given date parameter.
* @param user the user that should be stored
*/
- (MSAIUser *)userForDate:(NSDate *)date;
/**
* Remove a specific user ID from the persistent storage.
*
* @param userId The user ID to be removed.
*
* @return Returns YES if the ID was found and successfully removed.
*/
- (BOOL)removeUserId:(NSString *)userId;
- (void)saveUser:(MSAIUser *)user;
///-----------------------------------------------------------------------------
/// @name Creating A New Session
@ -156,34 +138,6 @@ FOUNDATION_EXPORT NSString *const kMSAIApplicationWasLaunched;
- (void)renewSessionWithId:(NSString *)sessionId;
/**
* Adds a new sessionId (value) for a given timestamp (key) to the session plist.
*
* @param sessionId the sessionId (value)
* @param timestamp the timestamp, which represents the creation of the session
*/
- (void)addSession:(MSAISession *)session withDate:(NSDate *)date;
/**
* Returns the best effort based on a given timestamp.
*
*
* @param date the creation date of a crash report
*
* @return the sessionId of the session, in which the crash occured
*/
- (MSAISession *)sessionForDate:(NSDate *)date;
/**
* Removes the entry for a given sessionId.
*
* @param sessionId The session ID of the plist entry which should be removed
*
* @return Returns YES if the ID was found and successfully removed.
*/
- (BOOL)removeSession:(MSAISession *)session;
///-----------------------------------------------------------------------------
/// @name Session Lifecycle
///-----------------------------------------------------------------------------
@ -222,17 +176,6 @@ FOUNDATION_EXPORT NSString *const kMSAIApplicationWasLaunched;
*/
- (void)sendSessionEndedNotification;
///-----------------------------------------------------------------------------
/// @name Clean Up
///-----------------------------------------------------------------------------
/**
* Remove everything except the most recent entries of each meta data type from the persistent store.
*/
- (void)cleanUpMetaData;
///-----------------------------------------------------------------------------
/// @name Helper
///-----------------------------------------------------------------------------

Просмотреть файл

@ -1,21 +0,0 @@
#import <Foundation/Foundation.h>
#import "MSAINullability.h"
typedef struct {
const void * __nullable exception;
const char * __nullable exception_type_name;
const char * __nullable exception_message;
uint32_t exception_frames_count;
const uintptr_t * __nonnull exception_frames;
} MSAICrashUncaughtCXXExceptionInfo;
typedef void (*MSAICrashUncaughtCXXExceptionHandler)(
const MSAICrashUncaughtCXXExceptionInfo * __nonnull info
);
@interface MSAICrashUncaughtCXXExceptionHandlerManager : NSObject
+ (void)addCXXExceptionHandler:(nonnull MSAICrashUncaughtCXXExceptionHandler)handler;
+ (void)removeCXXExceptionHandler:(nonnull MSAICrashUncaughtCXXExceptionHandler)handler;
@end

Просмотреть файл

@ -1,205 +0,0 @@
#import "MSAICrashCXXExceptionHandler.h"
#import <vector>
#import <cxxabi.h>
#import <exception>
#import <stdexcept>
#import <typeinfo>
#import <string>
#import <pthread.h>
#import <dlfcn.h>
#import <execinfo.h>
#import <libkern/OSAtomic.h>
typedef std::vector<MSAICrashUncaughtCXXExceptionHandler> MSAICrashUncaughtCXXExceptionHandlerList;
typedef struct
{
void *exception_object;
uintptr_t call_stack[128];
uint32_t num_frames;
} MSAICrashCXXExceptionTSInfo;
static bool _MSAICrashIsOurTerminateHandlerInstalled = false;
static std::terminate_handler _MSAICrashOriginalTerminateHandler = nullptr;
static MSAICrashUncaughtCXXExceptionHandlerList _MSAICrashUncaughtExceptionHandlerList;
static OSSpinLock _MSAICrashCXXExceptionHandlingLock = OS_SPINLOCK_INIT;
static pthread_key_t _MSAICrashCXXExceptionInfoTSDKey = 0;
@implementation MSAICrashUncaughtCXXExceptionHandlerManager
extern "C" void LIBCXXABI_NORETURN __cxa_throw(void *exception_object, std::type_info *tinfo, void (*dest)(void *))
{
// Purposely do not take a lock in this function. The aim is to be as fast as
// possible. While we could really use some of the info set up by the real
// __cxa_throw, if we call through we never get control back - the function is
// noreturn and jumps to landing pads. Most of the stuff in __cxxabiv1 also
// won't work yet. We therefore have to do these checks by hand.
// The technique for distinguishing Objective-C exceptions is based on the
// implementation of objc_exception_throw(). It's weird, but it's fast. The
// explicit symbol load and NULL checks should guard against the
// implementation changing in a future version. (Or not existing in an earlier
// version).
typedef void (*cxa_throw_func)(void *, std::type_info *, void (*)(void *)) LIBCXXABI_NORETURN;
static dispatch_once_t predicate = 0;
static cxa_throw_func __original__cxa_throw = nullptr;
static const void **__real_objc_ehtype_vtable = nullptr;
dispatch_once(&predicate, ^ {
__original__cxa_throw = reinterpret_cast<cxa_throw_func>(dlsym(RTLD_NEXT, "__cxa_throw"));
__real_objc_ehtype_vtable = reinterpret_cast<const void **>(dlsym(RTLD_DEFAULT, "objc_ehtype_vtable"));
});
// Actually check for Objective-C exceptions.
if (tinfo && __real_objc_ehtype_vtable && // Guard from an ABI change
*reinterpret_cast<void **>(tinfo) == __real_objc_ehtype_vtable + 2) {
goto callthrough;
}
// Any other exception that came here has to be C++, since Objective-C is the
// only (known) runtime that hijacks the C++ ABI this way. We need to save off
// a backtrace.
// Invariant: If the terminate handler is installed, the TSD key must also be
// initialized.
if (_MSAICrashIsOurTerminateHandlerInstalled) {
MSAICrashCXXExceptionTSInfo *info = static_cast<MSAICrashCXXExceptionTSInfo *>(pthread_getspecific(_MSAICrashCXXExceptionInfoTSDKey));
if (!info) {
info = reinterpret_cast<MSAICrashCXXExceptionTSInfo *>(calloc(1, sizeof(MSAICrashCXXExceptionTSInfo)));
pthread_setspecific(_MSAICrashCXXExceptionInfoTSDKey, info);
}
info->exception_object = exception_object;
// XXX: All significant time in this call is spent right here.
info->num_frames = backtrace(reinterpret_cast<void **>(&info->call_stack[0]), sizeof(info->call_stack) / sizeof(info->call_stack[0]));
}
callthrough:
if (__original__cxa_throw) {
__original__cxa_throw(exception_object, tinfo, dest);
} else {
abort();
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
__builtin_unreachable();
#pragma clang diagnostic pop
}
__attribute__((always_inline))
static inline void MSAICrashIterateExceptionHandlers_unlocked(const MSAICrashUncaughtCXXExceptionInfo &info)
{
for (const auto &handler : _MSAICrashUncaughtExceptionHandlerList) {
handler(&info);
}
}
static void MSAICrashUncaughtCXXTerminateHandler(void)
{
MSAICrashUncaughtCXXExceptionInfo info = {
.exception = nullptr,
.exception_type_name = nullptr,
.exception_message = nullptr,
.exception_frames_count = 0,
.exception_frames = nullptr,
};
auto p = std::current_exception();
OSSpinLockLock(&_MSAICrashCXXExceptionHandlingLock); {
if (p) { // explicit operator bool
info.exception = reinterpret_cast<const void *>(&p);
info.exception_type_name = __cxxabiv1::__cxa_current_exception_type()->name();
MSAICrashCXXExceptionTSInfo *recorded_info = reinterpret_cast<MSAICrashCXXExceptionTSInfo *>(pthread_getspecific(_MSAICrashCXXExceptionInfoTSDKey));
if (recorded_info) {
info.exception_frames_count = recorded_info->num_frames - 1;
info.exception_frames = &recorded_info->call_stack[1];
} else {
// There's no backtrace, grab this function's trace instead. Probably
// means the exception came from a dynamically loaded library.
void *frames[128] = { nullptr };
info.exception_frames_count = backtrace(&frames[0], sizeof(frames) / sizeof(frames[0])) - 1;
info.exception_frames = reinterpret_cast<uintptr_t *>(&frames[1]);
}
try {
std::rethrow_exception(p);
} catch (const std::exception &e) { // C++ exception.
info.exception_message = e.what();
MSAICrashIterateExceptionHandlers_unlocked(info);
} catch (const std::exception *e) { // C++ exception by pointer.
info.exception_message = e->what();
MSAICrashIterateExceptionHandlers_unlocked(info);
} catch (const std::string &e) { // C++ string as exception.
info.exception_message = e.c_str();
MSAICrashIterateExceptionHandlers_unlocked(info);
} catch (const std::string *e) { // C++ string pointer as exception.
info.exception_message = e->c_str();
MSAICrashIterateExceptionHandlers_unlocked(info);
} catch (const char *e) { // Plain string as exception.
info.exception_message = e;
MSAICrashIterateExceptionHandlers_unlocked(info);
} catch (id e) { // Objective-C exception. Pass it on to Foundation.
OSSpinLockUnlock(&_MSAICrashCXXExceptionHandlingLock);
if (_MSAICrashOriginalTerminateHandler != nullptr) {
_MSAICrashOriginalTerminateHandler();
}
return;
} catch (...) { // Any other kind of exception. No message.
MSAICrashIterateExceptionHandlers_unlocked(info);
}
}
} OSSpinLockUnlock(&_MSAICrashCXXExceptionHandlingLock); // In case terminate is called reentrantly by pasing it on
if (_MSAICrashOriginalTerminateHandler != nullptr) {
_MSAICrashOriginalTerminateHandler();
} else {
abort();
}
}
+ (void)addCXXExceptionHandler:(MSAICrashUncaughtCXXExceptionHandler)handler
{
static dispatch_once_t key_predicate = 0;
// This only EVER has to be done once, since we don't delete the TSD later
// (there's no reason to delete it).
dispatch_once(&key_predicate, ^ {
pthread_key_create(&_MSAICrashCXXExceptionInfoTSDKey, free);
});
OSSpinLockLock(&_MSAICrashCXXExceptionHandlingLock); {
if (!_MSAICrashIsOurTerminateHandlerInstalled) {
_MSAICrashOriginalTerminateHandler = std::set_terminate(MSAICrashUncaughtCXXTerminateHandler);
_MSAICrashIsOurTerminateHandlerInstalled = true;
}
_MSAICrashUncaughtExceptionHandlerList.push_back(handler);
} OSSpinLockUnlock(&_MSAICrashCXXExceptionHandlingLock);
}
+ (void)removeCXXExceptionHandler:(MSAICrashUncaughtCXXExceptionHandler)handler
{
OSSpinLockLock(&_MSAICrashCXXExceptionHandlingLock); {
auto i = std::find(_MSAICrashUncaughtExceptionHandlerList.begin(), _MSAICrashUncaughtExceptionHandlerList.end(), handler);
if (i != _MSAICrashUncaughtExceptionHandlerList.end()) {
_MSAICrashUncaughtExceptionHandlerList.erase(i);
}
if (_MSAICrashIsOurTerminateHandlerInstalled) {
if (_MSAICrashUncaughtExceptionHandlerList.empty()) {
std::terminate_handler previous_handler = std::set_terminate(_MSAICrashOriginalTerminateHandler);
if (previous_handler != MSAICrashUncaughtCXXTerminateHandler) {
std::set_terminate(previous_handler);
} else {
_MSAICrashIsOurTerminateHandlerInstalled = false;
_MSAICrashOriginalTerminateHandler = nullptr;
}
}
}
} OSSpinLockUnlock(&_MSAICrashCXXExceptionHandlingLock);
}
@end

Просмотреть файл

@ -1,17 +0,0 @@
#import "MSAIDomain.h"
@class MSAICrashDataHeaders;
@interface MSAICrashData : MSAIDomain <NSCoding>
@property (nonatomic, copy, readonly) NSString *envelopeTypeName;
@property (nonatomic, copy, readonly) NSString *dataTypeName;
@property (nonatomic, strong) MSAICrashDataHeaders *headers;
@property (nonatomic, strong) NSMutableArray *threads;
@property (nonatomic, strong) NSMutableArray *binaries;
- (instancetype)initWithCoder:(NSCoder *)coder;
- (void)encodeWithCoder:(NSCoder *)coder;
@end

Просмотреть файл

@ -1,73 +0,0 @@
#import "MSAICrashData.h"
#import "MSAICrashDataHeaders.h"
#import "MSAICrashDataBinary.h"
#import "MSAICrashDataThread.h"
#import "MSAIOrderedDictionary.h"
/// Data contract class for type CrashData.
@implementation MSAICrashData
@synthesize envelopeTypeName = _envelopeTypeName;
@synthesize dataTypeName = _dataTypeName;
@synthesize version = _version;
/// Initializes a new instance of the class.
- (instancetype)init {
if (self = [super init]) {
_envelopeTypeName = @"Microsoft.ApplicationInsights.Crash";
_dataTypeName = @"CrashData";
_version = @2;
_threads = [NSMutableArray new];
_binaries = [NSMutableArray new];
}
return self;
}
///
/// Adds all members of this class to a dictionary
/// @param dictionary to which the members of this class will be added.
///
- (MSAIOrderedDictionary *)serializeToDictionary {
MSAIOrderedDictionary *dict = [super serializeToDictionary];
MSAIOrderedDictionary *headersDict = [self.headers serializeToDictionary];
if ([NSJSONSerialization isValidJSONObject:headersDict]) {
[dict setObject:headersDict forKey:@"headers"];
} else {
NSLog(@"[ApplicationInsights] Some of the telemetry data was not NSJSONSerialization compatible and could not be serialized!");
}
if (self.threads != nil) {
NSMutableArray *threadsArray = [NSMutableArray array];
for (MSAICrashDataThread *threadsElement in self.threads) {
[threadsArray addObject:[threadsElement serializeToDictionary]];
}
[dict setObject:threadsArray forKey:@"threads"];
}
if (self.binaries != nil) {
NSMutableArray *binariesArray = [NSMutableArray array];
for (MSAICrashDataBinary *binariesElement in self.binaries) {
[binariesArray addObject:[binariesElement serializeToDictionary]];
}
[dict setObject:binariesArray forKey:@"binaries"];
}
return dict;
}
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if(self) {
_headers = [coder decodeObjectForKey:@"self.headers"];
_threads = [coder decodeObjectForKey:@"self.threads"];
_binaries = [coder decodeObjectForKey:@"self.binaries"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.headers forKey:@"self.headers"];
[coder encodeObject:self.threads forKey:@"self.threads"];
[coder encodeObject:self.binaries forKey:@"self.binaries"];
}
@end

Просмотреть файл

@ -1,13 +0,0 @@
#import "MSAIObject.h"
@interface MSAICrashDataBinary : MSAIObject <NSCoding>
@property (nonatomic, copy) NSString *startAddress;
@property (nonatomic, copy) NSString *endAddress;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSNumber *cpuType;
@property (nonatomic, copy) NSNumber *cpuSubType;
@property (nonatomic, copy) NSString *uuid;
@property (nonatomic, copy) NSString *path;
@end

Просмотреть файл

@ -1,66 +0,0 @@
#import "MSAICrashDataBinary.h"
#import "MSAIOrderedDictionary.h"
/// Data contract class for type CrashDataBinary.
@implementation MSAICrashDataBinary
///
/// Adds all members of this class to a dictionary
/// @param dictionary to which the members of this class will be added.
///
- (MSAIOrderedDictionary *)serializeToDictionary {
MSAIOrderedDictionary *dict = [super serializeToDictionary];
if (self.startAddress != nil) {
[dict setObject:self.startAddress forKey:@"startAddress"];
}
if (self.endAddress != nil) {
[dict setObject:self.endAddress forKey:@"endAddress"];
}
if (self.name != nil) {
[dict setObject:self.name forKey:@"name"];
}
if (self.cpuType != nil) {
[dict setObject:self.cpuType forKey:@"cpuType"];
}
if (self.cpuSubType != nil) {
[dict setObject:self.cpuSubType forKey:@"cpuSubType"];
}
if (self.uuid != nil) {
[dict setObject:self.uuid forKey:@"uuid"];
}
if (self.path != nil) {
[dict setObject:self.path forKey:@"path"];
}
return dict;
}
#pragma mark - NSCoding
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if(self) {
_startAddress = [coder decodeObjectForKey:@"self.startAddress"];
_endAddress = [coder decodeObjectForKey:@"self.endAddress"];
_name = [coder decodeObjectForKey:@"self.name"];
_cpuType = [coder decodeObjectForKey:@"self.cpuType"];
_cpuSubType = [coder decodeObjectForKey:@"self.cpuSubType"];
_uuid = [coder decodeObjectForKey:@"self.uuid"];
_path = [coder decodeObjectForKey:@"self.path"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.startAddress forKey:@"self.startAddress"];
[coder encodeObject:self.endAddress forKey:@"self.endAddress"];
[coder encodeObject:self.name forKey:@"self.name"];
[coder encodeObject:self.cpuType forKey:@"self.cpuType"];
[coder encodeObject:self.cpuSubType forKey:@"self.cpuSubType"];
[coder encodeObject:self.uuid forKey:@"self.uuid"];
[coder encodeObject:self.path forKey:@"self.path"];
}
@end

Просмотреть файл

@ -1,19 +0,0 @@
#import "MSAIObject.h"
@interface MSAICrashDataHeaders : MSAIObject <NSCoding>
@property (nonatomic, copy) NSString *crashDataHeadersId;
@property (nonatomic, copy) NSString *process;
@property (nonatomic, copy) NSNumber *processId;
@property (nonatomic, copy) NSString *parentProcess;
@property (nonatomic, copy) NSNumber *parentProcessId;
@property (nonatomic, copy) NSNumber *crashThread;
@property (nonatomic, copy) NSString *applicationPath;
@property (nonatomic, copy) NSString *applicationIdentifier;
@property (nonatomic, copy) NSString *applicationBuild;
@property (nonatomic, copy) NSString *exceptionType;
@property (nonatomic, copy) NSString *exceptionCode;
@property (nonatomic, copy) NSString *exceptionAddress;
@property (nonatomic, copy) NSString *exceptionReason;
@end

Просмотреть файл

@ -1,96 +0,0 @@
#import "MSAICrashDataHeaders.h"
#import "MSAIOrderedDictionary.h"
/// Data contract class for type CrashDataHeaders.
@implementation MSAICrashDataHeaders
///
/// Adds all members of this class to a dictionary
/// @param dictionary to which the members of this class will be added.
///
- (MSAIOrderedDictionary *)serializeToDictionary {
MSAIOrderedDictionary *dict = [super serializeToDictionary];
if (self.crashDataHeadersId != nil) {
[dict setObject:self.crashDataHeadersId forKey:@"id"];
}
if (self.process != nil) {
[dict setObject:self.process forKey:@"process"];
}
if (self.processId != nil) {
[dict setObject:self.processId forKey:@"processId"];
}
if (self.parentProcess != nil) {
[dict setObject:self.parentProcess forKey:@"parentProcess"];
}
if (self.parentProcessId != nil) {
[dict setObject:self.parentProcessId forKey:@"parentProcessId"];
}
if (self.crashThread != nil) {
[dict setObject:self.crashThread forKey:@"crashThread"];
}
if (self.applicationPath != nil) {
[dict setObject:self.applicationPath forKey:@"applicationPath"];
}
if (self.applicationIdentifier != nil) {
[dict setObject:self.applicationIdentifier forKey:@"applicationIdentifier"];
}
if (self.applicationBuild != nil) {
[dict setObject:self.applicationBuild forKey:@"applicationBuild"];
}
if (self.exceptionType != nil) {
[dict setObject:self.exceptionType forKey:@"exceptionType"];
}
if (self.exceptionCode != nil) {
[dict setObject:self.exceptionCode forKey:@"exceptionCode"];
}
if (self.exceptionAddress != nil) {
[dict setObject:self.exceptionAddress forKey:@"exceptionAddress"];
}
if (self.exceptionReason != nil) {
[dict setObject:self.exceptionReason forKey:@"exceptionReason"];
}
return dict;
}
#pragma mark - NSCoding
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if(self) {
_crashDataHeadersId = [coder decodeObjectForKey:@"self.crashDataHeadersId"];
_process = [coder decodeObjectForKey:@"self.process"];
_processId = [coder decodeObjectForKey:@"self.processId"];
_parentProcess = [coder decodeObjectForKey:@"self.parentProcess"];
_parentProcessId = [coder decodeObjectForKey:@"self.parentProcessId"];
_crashThread = [coder decodeObjectForKey:@"self.crashThread"];
_applicationPath = [coder decodeObjectForKey:@"self.applicationPath"];
_applicationIdentifier = [coder decodeObjectForKey:@"self.applicationIdentifier"];
_applicationBuild = [coder decodeObjectForKey:@"self.applicationBuild"];
_exceptionType = [coder decodeObjectForKey:@"self.exceptionType"];
_exceptionCode = [coder decodeObjectForKey:@"self.exceptionCode"];
_exceptionAddress = [coder decodeObjectForKey:@"self.exceptionAddress"];
_exceptionReason = [coder decodeObjectForKey:@"self.exceptionReason"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.crashDataHeadersId forKey:@"self.crashDataHeadersId"];
[coder encodeObject:self.process forKey:@"self.process"];
[coder encodeObject:self.processId forKey:@"self.processId"];
[coder encodeObject:self.parentProcess forKey:@"self.parentProcess"];
[coder encodeObject:self.parentProcessId forKey:@"self.parentProcessId"];
[coder encodeObject:self.crashThread forKey:@"self.crashThread"];
[coder encodeObject:self.applicationPath forKey:@"self.applicationPath"];
[coder encodeObject:self.applicationIdentifier forKey:@"self.applicationIdentifier"];
[coder encodeObject:self.applicationBuild forKey:@"self.applicationBuild"];
[coder encodeObject:self.exceptionType forKey:@"self.exceptionType"];
[coder encodeObject:self.exceptionCode forKey:@"self.exceptionCode"];
[coder encodeObject:self.exceptionAddress forKey:@"self.exceptionAddress"];
[coder encodeObject:self.exceptionReason forKey:@"self.exceptionReason"];
}
@end

Просмотреть файл

@ -1,36 +0,0 @@
#import <Foundation/Foundation.h>
#import "MSAINullability.h"
@class MSAIEnvelope;
@class MSAIPLCrashReport;
NS_ASSUME_NONNULL_BEGIN
/**
* ApplicationInsights Crash Reporter error domain
*/
typedef NS_ENUM (NSInteger, MSAIBinaryImageType) {
/**
* App binary
*/
MSAIBinaryImageTypeAppBinary,
/**
* App provided framework
*/
MSAIBinaryImageTypeAppFramework,
/**
* Image not related to the app
*/
MSAIBinaryImageTypeOther
};
@interface MSAICrashDataProvider : NSObject {
}
+ (MSAIEnvelope *)crashDataForCrashReport:(MSAIPLCrashReport *)report handledException:(nullable NSException *)exception;
+ (MSAIEnvelope *)crashDataForCrashReport:(MSAIPLCrashReport *)report;
+ (MSAIBinaryImageType)imageTypeForImagePath:(NSString *)imagePath processPath:(NSString *)processPath;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,671 +0,0 @@
/*
* Authors:
* Landon Fuller <landonf@plausiblelabs.com>
* Damian Morris <damian@moso.com.au>
* Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2008-2013 Plausible Labs Cooperative, Inc.
* Copyright (c) 2010 MOSO Corporation, Pty Ltd.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <CrashReporter/CrashReporter.h>
#import <mach-o/dyld.h>
#import <mach-o/getsect.h>
#import <mach-o/ldsyms.h>
#import <dlfcn.h>
#import <Availability.h>
#if defined(__OBJC2__)
#define SEL_NAME_SECT "__objc_methname"
#else
#define SEL_NAME_SECT "__cstring"
#endif
#import "MSAICrashDataProvider.h"
#import "MSAICrashData.h"
#import "MSAICrashDataHeaders.h"
#import "MSAICrashDataBinary.h"
#import "MSAICrashDataThread.h"
#import "MSAICrashDataThreadFrame.h"
#import "MSAIHelper.h"
#import "MSAIContextHelper.h"
#import "MSAIContextHelperPrivate.h"
#import "MSAIEnvelope.h"
#import "MSAIData.h"
#import "MSAIUser.h"
#import "MSAISession.h"
#import "MSAIEnvelopeManagerPrivate.h"
#import "MSAIEnvelopeManager.h"
#import "MSAIOrderedDictionary.h"
/*
* XXX: The ARM64 CPU type, and ARM_V7S and ARM_V8 Mach-O CPU subtypes are not
* defined in the Mac OS X 10.8 headers.
*/
#ifndef CPU_SUBTYPE_ARM_V7S
# define CPU_SUBTYPE_ARM_V7S 11
#endif
#ifndef CPU_TYPE_ARM64
#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
#endif
#ifndef CPU_SUBTYPE_ARM_V8
# define CPU_SUBTYPE_ARM_V8 13
#endif
/**
* Sort PLCrashReportBinaryImageInfo instances by their starting address.
*/
static NSInteger msai_binaryImageSort(id binary1, id binary2, void *context) {
uint64_t addr1 = [binary1 imageBaseAddress];
uint64_t addr2 = [binary2 imageBaseAddress];
if (addr1 < addr2)
return NSOrderedAscending;
else if (addr1 > addr2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
/**
* Validates that the given @a string terminates prior to @a limit.
*/
static const char *safer_string_read (const char *string, const char *limit) {
const char *p = string;
do {
if (p >= limit || p+1 >= limit) {
return NULL;
}
p++;
} while (*p != '\0');
return string;
}
/*
* The relativeAddress should be `<ecx/rsi/r1/x1 ...> - <image base>`, extracted from the crash report's thread
* and binary image list.
*
* For the (architecture-specific) registers to attempt, see:
* http://sealiesoftware.com/blog/archive/2008/09/22/objc_explain_So_you_crashed_in_objc_msgSend.html
*/
static const char *findSEL (const char *imageName, NSString *imageUUID, uint64_t relativeAddress) {
unsigned int images_count = _dyld_image_count();
for (unsigned int i = 0; i < images_count; ++i) {
intptr_t slide = _dyld_get_image_vmaddr_slide(i);
const struct mach_header *header = _dyld_get_image_header(i);
const struct mach_header_64 *header64 = (const struct mach_header_64 *) header;
const char *name = _dyld_get_image_name(i);
/* Image disappeared? */
if (name == NULL || header == NULL)
continue;
/* Check if this is the correct image. If we were being even more careful, we'd check the LC_UUID */
if (strcmp(name, imageName) != 0)
continue;
/* Determine whether this is a 64-bit or 32-bit Mach-O file */
BOOL m64 = NO;
if (header->magic == MH_MAGIC_64)
m64 = YES;
NSString *uuidString = nil;
const uint8_t *command;
uint32_t ncmds;
if (m64) {
command = (const uint8_t *)(header64 + 1);
ncmds = header64->ncmds;
} else {
command = (const uint8_t *)(header + 1);
ncmds = header->ncmds;
}
for (uint32_t idx = 0; idx < ncmds; ++idx) {
const struct load_command *load_command = (const struct load_command *)command;
if (load_command->cmd == LC_UUID) {
const struct uuid_command *uuid_command = (const struct uuid_command *)command;
const uint8_t *uuid = uuid_command->uuid;
uuidString = [[NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
uuid[0], uuid[1], uuid[2], uuid[3],
uuid[4], uuid[5], uuid[6], uuid[7],
uuid[8], uuid[9], uuid[10], uuid[11],
uuid[12], uuid[13], uuid[14], uuid[15]]
lowercaseString];
break;
} else {
command += load_command->cmdsize;
}
}
// Check if this is the correct image by comparing the UUIDs
if (!uuidString || ![uuidString isEqualToString:imageUUID])
continue;
/* Fetch the __objc_methname section */
const char *methname_sect;
uint64_t methname_sect_size;
if (m64) {
methname_sect = getsectdatafromheader_64(header64, SEG_TEXT, SEL_NAME_SECT, &methname_sect_size);
} else {
uint32_t meth_size_32;
methname_sect = getsectdatafromheader(header, SEG_TEXT, SEL_NAME_SECT, &meth_size_32);
methname_sect_size = meth_size_32;
}
/* Apply the slide, as per getsectdatafromheader(3) */
methname_sect += slide;
if (methname_sect == NULL) {
return NULL;
}
/* Calculate the target address within this image, and verify that it is within __objc_methname */
const char *target = ((const char *)header) + relativeAddress;
const char *limit = methname_sect + methname_sect_size;
if (target < methname_sect || target >= limit) {
return NULL;
}
/* Read the actual method name */
return safer_string_read(target, limit);
}
return NULL;
}
/**
* Formats PLCrashReport data as human-readable text.
*/
@implementation MSAICrashDataProvider
+ (MSAIEnvelope *)crashDataForCrashReport:(MSAIPLCrashReport *)report handledException:(NSException *)exception{
MSAIEnvelope *envelope = [[MSAIEnvelopeManager sharedManager] envelope];
/* System info */
{
/* Map to apple style OS nane */
NSString *osName;
switch (report.systemInfo.operatingSystem) {
case PLCrashReportOperatingSystemiPhoneOS:
osName = @"iPhone OS";
break;
case PLCrashReportOperatingSystemMacOSX:
case PLCrashReportOperatingSystemiPhoneSimulator:
osName = @"OS X";
break;
default:
osName = [NSString stringWithFormat: @"Unknown (%d)", report.systemInfo.operatingSystem];
break;
}
NSString *osBuild = @"???";
if (report.systemInfo.operatingSystemBuild != nil){
osBuild = report.systemInfo.operatingSystemBuild;
}
envelope.osVer = [NSString stringWithFormat:@"%@(%@)", report.systemInfo.operatingSystemVersion, osBuild];
envelope.os = osName;
// We add one second to the crash time to work around an issue where the timestamp has only second granularity.
envelope.time = msai_utcDateString([report.systemInfo.timestamp dateByAddingTimeInterval:1]);
envelope.appId = report.applicationInfo.applicationIdentifier;
NSString *marketingVersion = report.applicationInfo.applicationMarketingVersion;
NSString *appVersion = report.applicationInfo.applicationVersion;
envelope.appVer = marketingVersion ? [NSString stringWithFormat:@"%@ (%@)", marketingVersion, appVersion] : appVersion;
NSDate *crashTimestamp = report.systemInfo.timestamp;
MSAISession *session = [[MSAIContextHelper sharedInstance] sessionForDate:crashTimestamp];
MSAIUser *user = [[MSAIContextHelper sharedInstance] userForDate:crashTimestamp];
if (envelope.tags) {
if (session) {
[envelope.tags addEntriesFromDictionary:[session serializeToDictionary]];
}
if (user) {
[envelope.tags addEntriesFromDictionary:[user serializeToDictionary]];
}
}
}
MSAICrashData *crashData = [MSAICrashData new];
MSAICrashDataHeaders *crashHeaders = [MSAICrashDataHeaders new];
NSString *unknownString = @"???";
boolean_t lp64 = true; // quiesce GCC uninitialized value warning
/* Map to Apple-style code type, and mark whether architecture is LP64 (64-bit) */
NSNumber *codeType = nil;
{
/* Attempt to derive the code type from the binary images */
for (MSAIPLCrashReportBinaryImageInfo *image in report.images) {
/* Skip images with no specified type */
if (image.codeType == nil)
continue;
/* Skip unknown encodings */
if (image.codeType.typeEncoding != PLCrashReportProcessorTypeEncodingMach)
continue;
switch (image.codeType.type) {
case CPU_TYPE_ARM:
codeType = @(image.codeType.type);
lp64 = false;
break;
case CPU_TYPE_ARM64:
codeType = @(image.codeType.type);
lp64 = true;
break;
case CPU_TYPE_X86:
codeType = @(image.codeType.type);
lp64 = false;
break;
case CPU_TYPE_X86_64:
codeType = @(image.codeType.type);
lp64 = true;
break;
case CPU_TYPE_POWERPC:
codeType = @(image.codeType.type);
lp64 = false;
break;
default:
// Do nothing, handled below.
break;
}
/* Stop immediately if code type was discovered */
if (codeType != nil)
break;
}
/* If we were unable to determine the code type, fall back on the legacy architecture value. */
if (codeType == nil) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
switch (report.systemInfo.architecture) {
#pragma clang diagnostic pop
case PLCrashReportArchitectureARMv6:
case PLCrashReportArchitectureARMv7:
codeType = @(CPU_TYPE_ARM);
lp64 = false;
break;
case PLCrashReportArchitectureX86_32:
codeType = @(CPU_TYPE_X86);
lp64 = false;
break;
case PLCrashReportArchitectureX86_64:
codeType = @(CPU_TYPE_X86_64);
lp64 = true;
break;
case PLCrashReportArchitecturePPC:
codeType = @(CPU_TYPE_POWERPC);
lp64 = false;
break;
default:
lp64 = true;
break;
}
}
}
crashHeaders.crashDataHeadersId = msai_UUID();
/* Application and process info */
{
NSString *processName = unknownString;
NSString *processPath = unknownString;
NSString *parentProcessName = unknownString;
NSNumber *processId = nil;
NSNumber *parentProcessId = nil;
/* Process information was not available in earlier crash report versions */
if (report.hasProcessInfo) {
/* Process Name */
if (report.processInfo.processName != nil)
processName = report.processInfo.processName;
/* PID */
processId = @(report.processInfo.processID);
/* Process Path */
if (report.processInfo.processPath != nil) {
processPath = report.processInfo.processPath;
/* Remove username from the path */
#if TARGET_IPHONE_SIMULATOR
if ([processPath length] > 0)
processPath = [processPath stringByAbbreviatingWithTildeInPath];
if ([processPath length] > 0 && [[processPath substringToIndex:1] isEqualToString:@"~"])
processPath = [NSString stringWithFormat:@"/Users/USER%@", [processPath substringFromIndex:1]];
#endif
}
/* Parent Process Name */
if (report.processInfo.parentProcessName != nil)
parentProcessName = report.processInfo.parentProcessName;
/* Parent Process ID */
parentProcessId = @(report.processInfo.parentProcessID);
}
crashHeaders.process = processName;
crashHeaders.processId = processId;
crashHeaders.parentProcess = parentProcessName;
crashHeaders.parentProcessId = parentProcessId;
crashHeaders.applicationIdentifier = report.applicationInfo.applicationIdentifier;
crashHeaders.applicationBuild = report.applicationInfo.applicationVersion;
crashHeaders.applicationPath = processPath;
NSString *incidentIdentifier = @"???";
if (report.uuidRef != NULL) {
incidentIdentifier = (NSString *) CFBridgingRelease(CFUUIDCreateString(NULL, report.uuidRef));
}
crashHeaders.crashDataHeadersId = incidentIdentifier;
}
/* Exception code */
crashHeaders.exceptionAddress = [NSString stringWithFormat:@"0x%" PRIx64, report.signalInfo.address];
crashHeaders.exceptionType = (exception) ? exception.name : report.signalInfo.name;
crashHeaders.exceptionReason = (exception) ? exception.reason : nil;
crashHeaders.exceptionCode = report.signalInfo.code;
for (MSAIPLCrashReportThreadInfo *thread in report.threads) {
if (thread.crashed) {
crashHeaders.crashThread = @(thread.threadNumber);
break;
}
}
MSAIPLCrashReportThreadInfo *crashed_thread = nil;
for (MSAIPLCrashReportThreadInfo *thread in report.threads) {
if (thread.crashed) {
crashed_thread = thread;
break;
}
}
/* Uncaught Exception */
if (report.hasExceptionInfo) {
crashHeaders.exceptionReason = [NSString stringWithFormat:@"%@: %@", report.exceptionInfo.exceptionName, report.exceptionInfo.exceptionReason];
} else if (crashed_thread != nil) {
// try to find the selector in case this was a crash in obj_msgSend
// we search this wether the crash happend in obj_msgSend or not since we don't have the symbol!
NSString *foundSelector = nil;
// search the registers value for the current arch
#if TARGET_IPHONE_SIMULATOR
if (lp64) {
foundSelector = [[self class] selectorForRegisterWithName:@"rsi" ofThread:crashed_thread report:report];
if (foundSelector == NULL)
foundSelector = [[self class] selectorForRegisterWithName:@"rdx" ofThread:crashed_thread report:report];
} else {
foundSelector = [[self class] selectorForRegisterWithName:@"ecx" ofThread:crashed_thread report:report];
}
#else
if (lp64) {
foundSelector = [[self class] selectorForRegisterWithName:@"x1" ofThread:crashed_thread report:report];
} else {
foundSelector = [[self class] selectorForRegisterWithName:@"r1" ofThread:crashed_thread report:report];
if (foundSelector == NULL)
foundSelector = [[self class] selectorForRegisterWithName:@"r2" ofThread:crashed_thread report:report];
}
#endif
if (foundSelector) {
crashHeaders.exceptionReason = [NSString stringWithFormat:@"Selector name found in current argument registers: %@\n", foundSelector];
}
}
crashData.headers = crashHeaders;
NSMutableArray *addresses = [NSMutableArray new];
/* If an exception stack trace is available, output an Apple-compatible backtrace. */
if (report.exceptionInfo != nil && report.exceptionInfo.stackFrames != nil && [report.exceptionInfo.stackFrames count] > 0) {
MSAIPLCrashReportExceptionInfo *exception = report.exceptionInfo;
MSAICrashDataThread *threadData = [MSAICrashDataThread new];
threadData.crashDataThreadId = @(-1);
/* Write out the frames. In raw reports, Apple writes this out as a simple list of PCs. In the minimally
* post-processed report, Apple writes this out as full frame entries. We use the latter format. */
int lastIndex = (int)[exception.stackFrames count] - 1;
for (NSInteger frame_idx = 0; frame_idx <= lastIndex; frame_idx++) {
MSAIPLCrashReportStackFrameInfo *frameInfo = exception.stackFrames[frame_idx];
MSAICrashDataThreadFrame *frame = [MSAICrashDataThreadFrame new];
frame.address = [NSString stringWithFormat:@"0x%0*" PRIx64, lp64 ? 16 : 8, frameInfo.instructionPointer];
[addresses addObject:[NSNumber numberWithUnsignedLongLong:frameInfo.instructionPointer]];
[threadData.frames addObject:frame];
}
[crashData.threads addObject:threadData];
}
/* Threads */
for (MSAIPLCrashReportThreadInfo *thread in report.threads) {
MSAICrashDataThread *threadData = [MSAICrashDataThread new];
threadData.crashDataThreadId = @(thread.threadNumber);
int lastIndex = (int)[thread.stackFrames count] - 1;
for (NSInteger frame_idx = 0; frame_idx <= lastIndex; frame_idx++) {
MSAIPLCrashReportStackFrameInfo *frameInfo = thread.stackFrames[frame_idx];
MSAICrashDataThreadFrame *frame = [MSAICrashDataThreadFrame new];
frame.address = [NSString stringWithFormat:@"0x%0*" PRIx64, lp64 ? 16 : 8, frameInfo.instructionPointer];
[addresses addObject:[NSNumber numberWithUnsignedLongLong:frameInfo.instructionPointer]];
[threadData.frames addObject:frame];
}
/* Registers */
if(thread.crashed){
for (MSAIPLCrashReportRegisterInfo *reg in crashed_thread.registers) {
NSString *regName = reg.registerName;
// Currently we only need "lr"
if([regName isEqualToString:@"lr"]){
NSString *formattedRegName = [NSString stringWithFormat:@"%s", [regName UTF8String]];
NSString *formattedRegValue = @"";
/* Use 32-bit or 64-bit fixed width format for the register values */
if (lp64){
formattedRegValue = [NSString stringWithFormat:@"0x%016" PRIx64, reg.registerValue];
}else{
formattedRegValue = [NSString stringWithFormat:@"0x%08" PRIx64, reg.registerValue];
}
if(threadData.frames.count > 0){
[[(MSAICrashDataThreadFrame *)threadData.frames[0] registers] setValue:formattedRegValue forKey:formattedRegName];
[addresses addObject:[NSNumber numberWithUnsignedLongLong:reg.registerValue]];
}
break;
}
}
}
[crashData.threads addObject:threadData];
}
/* Images. The iPhone crash report format sorts these in ascending order, by the base address */
NSMutableArray *binaries = [NSMutableArray new];
for (MSAIPLCrashReportBinaryImageInfo *imageInfo in [report.images sortedArrayUsingFunction: msai_binaryImageSort context: nil]) {
MSAICrashDataBinary *binary = [MSAICrashDataBinary new];
NSString *fmt = (lp64) ? @"0x%016" PRIx64 : @"0x%08" PRIx64;
uint64_t startAddress = imageInfo.imageBaseAddress;
binary.startAddress = [NSString stringWithFormat:fmt, startAddress];
uint64_t endAddress = imageInfo.imageBaseAddress + (MAX((uint64_t)1, imageInfo.imageSize) - 1);
binary.endAddress = [NSString stringWithFormat:fmt, endAddress];
BOOL binaryIsInAddresses = [self isBinaryWithStart:startAddress end:endAddress inAddresses:addresses];
MSAIBinaryImageType imageType = [self imageTypeForImagePath:imageInfo.imageName processPath:report.processInfo.processPath];
if (binaryIsInAddresses || (imageType != MSAIBinaryImageTypeOther)) {
/* Remove username from the image path */
NSString *imageName = @"";
if (imageInfo.imageName && [imageInfo.imageName length] > 0) {
#if TARGET_IPHONE_SIMULATOR
imageName = [imageInfo.imageName stringByAbbreviatingWithTildeInPath];
#else
imageName = imageInfo.imageName;
#endif
}
#if TARGET_IPHONE_SIMULATOR
if ([imageName length] > 0 && [[imageName substringToIndex:1] isEqualToString:@"~"]) {
imageName = [NSString stringWithFormat:@"/Users/USER%@", [imageName substringFromIndex:1]];
}
#endif
binary.path = imageName;
binary.name = [imageInfo.imageName lastPathComponent];
/* Fetch the UUID if it exists */
binary.uuid = (imageInfo.hasImageUUID) ? imageInfo.imageUUID : unknownString;
/* Determine the architecture string */
binary.cpuType = codeType;
binary.cpuSubType = @(imageInfo.codeType.subtype);
[binaries addObject:binary];
}
}
crashData.binaries = binaries;
MSAIData *data = [MSAIData new];
data.baseData = crashData;
data.baseType = crashData.dataTypeName;
envelope.data = data;
envelope.name = crashData.envelopeTypeName;
return envelope;
}
+ (BOOL)isBinaryWithStart:(uint64_t)start end:(uint64_t)end inAddresses:(NSArray *)addresses{
for(NSNumber *address in addresses){
if([address unsignedLongLongValue] >= start && [address unsignedLongLongValue] <= end){
return YES;
}
}
return NO;
}
/* Determine if in binary image is the app executable or app specific framework */
+ (MSAIBinaryImageType)imageTypeForImagePath:(NSString *)imagePath processPath:(NSString *)processPath {
MSAIBinaryImageType imageType = MSAIBinaryImageTypeOther;
NSString *standardizedImagePath = [[imagePath stringByStandardizingPath] lowercaseString];
imagePath = [imagePath lowercaseString];
processPath = [processPath lowercaseString];
NSRange appRange = [standardizedImagePath rangeOfString: @".app/"];
// Exclude iOS swift dylibs. These are provided as part of the app binary by Xcode for now, but we never get a dSYM for those.
NSRange swiftLibRange = [standardizedImagePath rangeOfString:@"frameworks/libswift"];
BOOL dylibSuffix = [standardizedImagePath hasSuffix:@".dylib"];
if (appRange.location != NSNotFound && !(swiftLibRange.location != NSNotFound && dylibSuffix)) {
NSString *appBundleContentsPath = [standardizedImagePath substringToIndex:appRange.location + 5];
if ([standardizedImagePath isEqual: processPath] ||
// Fix issue with iOS 8 `stringByStandardizingPath` removing leading `/private` path (when not running in the debugger or simulator only)
[imagePath hasPrefix:processPath]) {
imageType = MSAIBinaryImageTypeAppBinary;
} else if ([standardizedImagePath hasPrefix:appBundleContentsPath] ||
// Fix issue with iOS 8 `stringByStandardizingPath` removing leading `/private` path (when not running in the debugger or simulator only)
[imagePath hasPrefix:appBundleContentsPath]) {
imageType = MSAIBinaryImageTypeAppFramework;
}
}
return imageType;
}
/**
* Formats the provided @a report as human-readable text in the given @a textFormat, and return
* the formatted result as a string.
*
* @param report The report to format.
* @param textFormat The text format to use.
*
* @return Returns the formatted result on success, or nil if an error occurs.
*/
+ (MSAIEnvelope *)crashDataForCrashReport:(MSAIPLCrashReport *)report {
return [[self class]crashDataForCrashReport:report handledException:nil];
}
/**
* Return the selector string of a given register name
*
* @param regName The name of the register to use for getting the address
* @param thread The crashed thread
* @param images NSArray of binary images
*
* @return The selector as a C string or NULL if no selector was found
*/
+ (NSString *)selectorForRegisterWithName:(NSString *)regName ofThread:(MSAIPLCrashReportThreadInfo *)thread report:(MSAIPLCrashReport *)report {
// get the address for the register
uint64_t regAddress = 0;
for (MSAIPLCrashReportRegisterInfo *reg in thread.registers) {
if ([reg.registerName isEqualToString:regName]) {
regAddress = reg.registerValue;
break;
}
}
if (regAddress == 0)
return nil;
MSAIPLCrashReportBinaryImageInfo *imageForRegAddress = [report imageForAddress:regAddress];
if (imageForRegAddress) {
// get the SEL
const char *foundSelector = findSEL([imageForRegAddress.imageName UTF8String], imageForRegAddress.imageUUID, regAddress - (uint64_t)imageForRegAddress.imageBaseAddress);
if (foundSelector != NULL) {
return [NSString stringWithUTF8String:foundSelector];
}
}
return nil;
}
@end

Просмотреть файл

@ -1,8 +0,0 @@
#import "MSAIObject.h"
@interface MSAICrashDataThread : MSAIObject <NSCoding>
@property (nonatomic, copy) NSNumber *crashDataThreadId;
@property (nonatomic, strong) NSMutableArray *frames;
@end

Просмотреть файл

@ -1,54 +0,0 @@
#import "MSAICrashDataThread.h"
#import "MSAIOrderedDictionary.h"
#import "MSAICrashDataThreadFrame.h"
/// Data contract class for type CrashDataThread.
@implementation MSAICrashDataThread
/// Initializes a new instance of the class.
- (instancetype)init {
if (self = [super init]) {
_frames = [NSMutableArray new];
}
return self;
}
///
/// Adds all members of this class to a dictionary
/// @param dictionary to which the members of this class will be added.
///
- (MSAIOrderedDictionary *)serializeToDictionary {
MSAIOrderedDictionary *dict = [super serializeToDictionary];
if (self.crashDataThreadId != nil) {
[dict setObject:self.crashDataThreadId forKey:@"id"];
}
if (self.frames != nil) {
NSMutableArray *framesArray = [NSMutableArray array];
for (MSAICrashDataThreadFrame *framesElement in self.frames) {
[framesArray addObject:[framesElement serializeToDictionary]];
}
[dict setObject:framesArray forKey:@"frames"];
}
return dict;
}
#pragma mark - NSCoding
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if(self) {
_crashDataThreadId = [coder decodeObjectForKey:@"self.crashDataThreadId"];
_frames = [coder decodeObjectForKey:@"self.frames"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.crashDataThreadId forKey:@"self.crashDataThreadId"];
[coder encodeObject:self.frames forKey:@"self.frames"];
}
@end

Просмотреть файл

@ -1,9 +0,0 @@
#import "MSAIObject.h"
@interface MSAICrashDataThreadFrame : MSAIObject <NSCoding>
@property (nonatomic, copy) NSString *address;
@property (nonatomic, copy) NSString *symbol;
@property (nonatomic, strong) NSMutableDictionary *registers;
@end

Просмотреть файл

@ -1,55 +0,0 @@
#import "MSAICrashDataThreadFrame.h"
#import "MSAIOrderedDictionary.h"
/// Data contract class for type CrashDataThreadFrame.
@implementation MSAICrashDataThreadFrame
/// Initializes a new instance of the class.
- (instancetype)init {
if (self = [super init]) {
_registers = [MSAIOrderedDictionary new];
}
return self;
}
///
/// Adds all members of this class to a dictionary
/// @param dictionary to which the members of this class will be added.
///
- (MSAIOrderedDictionary *)serializeToDictionary {
MSAIOrderedDictionary *dict = [super serializeToDictionary];
if (self.address != nil) {
[dict setObject:self.address forKey:@"address"];
}
// symbol is not needed
// if (self.symbol != nil) {
// [dict setObject:self.symbol forKey:@"symbol"];
// }
if (self.registers != nil && self.registers.count > 0) {
[dict setObject:self.registers forKey:@"registers"];
}
return dict;
}
#pragma mark - NSCoding
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if(self) {
_address = [coder decodeObjectForKey:@"self.address"];
_symbol = [coder decodeObjectForKey:@"self.symbol"];
_registers = [coder decodeObjectForKey:@"self.registers"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.address forKey:@"self.address"];
[coder encodeObject:self.symbol forKey:@"self.symbol"];
[coder encodeObject:self.registers forKey:@"self.registers"];
}
@end

Просмотреть файл

@ -1,85 +0,0 @@
#import <Foundation/Foundation.h>
#import "MSAINullability.h"
NS_ASSUME_NONNULL_BEGIN
/**
* Provides details about the crash that occured in the previous app session
*/
@interface MSAICrashDetails : NSObject
/**
* UUID for the crash report
*/
@property (nonatomic, readonly, copy) NSString *incidentIdentifier;
/**
* UUID for the app installation on the device
*/
@property (nonatomic, readonly, copy) NSString *reporterKey;
/**
* Signal that caused the crash
*/
@property (nonatomic, readonly, copy) NSString *signal;
/**
* Exception name that triggered the crash, nil if the crash was not caused by an exception
*/
@property (nonatomic, readonly, copy) NSString *exceptionName;
/**
* Exception reason, nil if the crash was not caused by an exception
*/
@property (nonatomic, readonly, copy) NSString *exceptionReason;
/**
* Date and time the app started, nil if unknown
*/
@property (nonatomic, readonly, strong) NSDate *appStartTime;
/**
* Date and time the crash occured, nil if unknown
*/
@property (nonatomic, readonly, strong) NSDate *crashTime;
/**
* Operation System version string the app was running on when it crashed.
*/
@property (nonatomic, readonly, copy) NSString *osVersion;
/**
* Operation System build string the app was running on when it crashed
*
* This may be unavailable.
*/
@property (nonatomic, readonly, copy) NSString *osBuild;
/**
* CFBundleVersion value of the app that crashed
*/
@property (nonatomic, readonly, copy) NSString *appBuild;
/**
Indicates if the app was killed while being in foreground from the iOS
If `[MSAICrashManager appNotTerminatingCleanlyDetectionEnabled]` is enabled, use this on startup
to check if the app starts the first time after it was killed by iOS in the previous session.
This can happen if it consumed too much memory or the watchdog killed the app because it
took too long to startup or blocks the main thread for too long, or other reasons. See Apple
documentation: https://developer.apple.com/library/ios/qa/qa1693/_index.html
See `[MSAICrashManager appNotTerminatingCleanlyDetectionEnabled]` for more details about which kind of kills can be detected.
@warning This property only has a correct value, once `[MSAIApplicationInsights start]` was
invoked! In addition, it is automatically disabled while a debugger session is active!
@see `[MSAICrashManager appNotTerminatingCleanlyDetectionEnabled]`
@see `[MSAICrashManager didReceiveMemoryWarningInLastSession]`
@return YES if the details represent an app kill instead of a crash
*/
- (BOOL)isAppKill;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,43 +0,0 @@
#import "MSAICrashDetails.h"
#import "MSAICrashDetailsPrivate.h"
NSString *const kMSAICrashKillSignal = @"SIGKILL";
@implementation MSAICrashDetails
- (instancetype)initWithIncidentIdentifier:(NSString *)incidentIdentifier
reporterKey:(NSString *)reporterKey
signal:(NSString *)signal
exceptionName:(NSString *)exceptionName
exceptionReason:(NSString *)exceptionReason
appStartTime:(NSDate *)appStartTime
crashTime:(NSDate *)crashTime
osVersion:(NSString *)osVersion
osBuild:(NSString *)osBuild
appBuild:(NSString *)appBuild
{
if ((self = [super init])) {
_incidentIdentifier = incidentIdentifier;
_reporterKey = reporterKey;
_signal = signal;
_exceptionName = exceptionName;
_exceptionReason = exceptionReason;
_appStartTime = appStartTime;
_crashTime = crashTime;
_osVersion = osVersion;
_osBuild = osBuild;
_appBuild = appBuild;
}
return self;
}
- (BOOL)isAppKill {
BOOL result = NO;
if (_signal && [[_signal uppercaseString] isEqualToString:kMSAICrashKillSignal])
result = YES;
return result;
}
@end

Просмотреть файл

@ -1,23 +0,0 @@
#import "ApplicationInsights.h"
#import "MSAICrashDetails.h"
NS_ASSUME_NONNULL_BEGIN
extern NSString *const __unused kMSAICrashKillSignal;
@interface MSAICrashDetails () {
}
- (instancetype)initWithIncidentIdentifier:(NSString *)incidentIdentifier
reporterKey:(NSString *)reporterKey
signal:(NSString *)signal
exceptionName:(NSString *)exceptionName
exceptionReason:(NSString *)exceptionReason
appStartTime:(NSDate *)appStartTime
crashTime:(NSDate *)crashTime
osVersion:(NSString *)osVersion
osBuild:(NSString *)osBuild
appBuild:(NSString *)appBuild;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,302 +0,0 @@
#import <Foundation/Foundation.h>
#import "MSAINullability.h"
#import "MSAICrashDetails.h"
NS_ASSUME_NONNULL_BEGIN
/**
* Prototype of a callback function used to execute additional user code. Called upon completion of crash
* handling, after the crash report has been written to disk.
*
* @param context The API client's supplied context value.
*
* @see `MSAICrashManagerCallbacks`
* @see `[MSAICrashManager setCrashCallbacks:]`
*/
typedef void (*MSAICrashManagerPostCrashSignalCallback)(void *context);
/**
* This structure contains callbacks supported by `MSAICrashManager` to allow the host application to perform
* additional tasks prior to program termination after a crash has occured.
*
* @see `MSAICrashManagerPostCrashSignalCallback`
* @see `[MSAICrashManager setCrashCallbacks:]`
*/
typedef struct MSAICrashManagerCallbacks {
/** An arbitrary user-supplied context value. This value may be NULL. */
void *context;
/**
* The callback used to report caught signal information.
*/
MSAICrashManagerPostCrashSignalCallback handleSignal;
} MSAICrashManagerCallbacks;
@protocol MSAICrashManagerDelegate;
/**
The crash reporting module.
This is the Application Insights module for handling crash reports, including when distributed via the App Store.
As a foundation it is using the open source, reliable and async-safe crash reporting framework
[PLCrashReporter](https://code.google.com/p/plcrashreporter/).
This module works as a wrapper around the underlying crash reporting framework and provides functionality to
detect new crashes.
It also provides options via `MSAICrashManagerDelegate` protocol and a way to detect startup crashes so you
can adjust your startup process to get these crash reports too and delay your app initialization.
Crashes are send the next time the app starts. This module is not sending the reports right when the crash happens
deliberately, because if is not safe to implement such a mechanism while being async-safe (any Objective-C code
is _NOT_ async-safe!) and not causing more danger like a deadlock of the device, than helping. We found that users
do start the app again because most don't know what happened, and you will get by far most of the reports.
Sending the reports on startup is done asynchronously (non-blocking). This is the only safe way to ensure
that the app won't be possibly killed by the iOS watchdog process, because startup could take too long
and the app could not react to any user input when network conditions are bad or connectivity might be
very slow.
It is possible to check upon startup if the app crashed before using `didCrashInLastSession` and also how much
time passed between the app launch and the crash using `timeintervalCrashInLastSessionOccured`. This allows you
to add additional code to your app delaying the app start until the crash has been successfully send if the crash
occured within a critical startup timeframe, e.g. after 10 seconds. The `MSAICrashManagerDelegate` protocol provides
various delegates to inform the app about it's current status so you can continue the remaining app startup setup
after sending has been completed. The documentation contains a guide
[How to handle Crashes on startup](HowTo-Handle-Crashes-On-Startup) with an example on how to do that.
More background information on this topic can be found in the following blog post by Landon Fuller, the
developer of [PLCrashReporter](https://www.plcrashreporter.org), about writing reliable and
safe crash reporting: [Reliable Crash Reporting](http://goo.gl/WvTBR)
@warning If you start the app with the Xcode debugger attached, detecting crashes will _NOT_ be enabled!
*/
@interface MSAICrashManager : NSObject
///-----------------------------------------------------------------------------
/// @name Initialization
///-----------------------------------------------------------------------------
+ (instancetype)sharedManager;
/**
* Indicates if the MSAICrashManager is initialised correctly.*
*/
@property (nonatomic, assign) BOOL isSetupCorrectly;
///-----------------------------------------------------------------------------
/// @name Configuration
///-----------------------------------------------------------------------------
/**
* Indicates if the CrashManager has been disabled.
* The CrashManager is enabled by default.
* Set this after initialization (you can check the `isSetupCorrectly´property to find out) to disable the CrashManager.
* Usually, this isn't done directly on MSAICrashManger but the interface provided by `MSAIApplicationInsights´
* @default: NO
* @see MSAIApplicationInsights
*/
@property (nonatomic, assign, setter=setCrashManagerDisabled:) BOOL isCrashManagerDisabled;
//TODO move the properties to the private header to make sure developers don't use the MSAICrashmanager but MSAIApplicationInsights
/**
* Trap fatal signals via a Mach exception server.
*
* By default the SDK is using the safe and proven in-process BSD Signals for catching crashes.
* This option provides an option to enable catching fatal signals via a Mach exception server
* instead.
*
* We strongly advice _NOT_ to enable Mach exception handler in release versions of your apps!
*
* Default: _NO_
*
* @warning The Mach exception handler executes in-process, and will interfere with debuggers when
* they attempt to suspend all active threads (which will include the Mach exception handler).
* Mach-based handling should _NOT_ be used when a debugger is attached. The SDK will not
* enabled catching exceptions if the app is started with the debugger running. If you attach
* the debugger during runtime, this may cause issues the Mach exception handler is enabled!
* @see debuggerIsAttached
*/
@property (nonatomic, assign) BOOL machExceptionHandlerEnabled;
/**
* Enable on device symbolication for system symbols
*
* By default, the SDK does not symbolicate on the device, since this can
* take a few seconds at each crash. Also note that symbolication on the
* device might not be able to retrieve all symbols.
*
* Enable if you want to analyze crashes on unreleased OS versions.
*
* Default: _NO_
*/
@property (nonatomic, assign) BOOL onDeviceSymbolicationEnabled;
/**
* EXPERIMENTAL: Enable heuristics to detect the app not terminating cleanly
*
* This allows it to get a crash report if the app got killed while being in the foreground
* because of now of the following reasons:
* - The main thread was blocked for too long
* - The app took too long to start up
* - The app tried to allocate too much memory. If iOS did send a memory warning before killing the app because of this reason, `didReceiveMemoryWarningInLastSession` returns `YES`.
* - Permitted background duration if main thread is running in an endless loop
* - App failed to resume in time if main thread is running in an endless loop
* - If `enableMachExceptionHandler` is not activated, crashed due to stackoverflow will also be reported
*
* The following kills can _NOT_ be detected:
* - Terminating the app takes too long
* - Permitted background duration too long for all other cases
* - App failed to resume in time for all other cases
* - possibly more cases
*
* Crash reports triggered by this mechanisms do _NOT_ contain any stack traces since the time of the kill
* cannot be intercepted and hence no stack trace of the time of the kill event can't be gathered.
*
* The heuristic is implemented as follows:
* If the app never gets a `UIApplicationDidEnterBackgroundNotification` or `UIApplicationWillTerminateNotification`
* notification, PLCrashReporter doesn't detect a crash itself, and the app starts up again, it is assumed that
* the app got either killed by iOS while being in foreground or a crash occured that couldn't be detected.
*
* Default: _NO_
*
* @warning This is a heuristic and it _MAY_ report false positives! It has been tested with iOS 6.1 and iOS 7.
* Depending on Apple changing notification events, new iOS version may cause more false positives!
*
* @see lastSessionCrashDetails
* @see didReceiveMemoryWarningInLastSession
* @see `MSAICrashManagerDelegate considerAppNotTerminatedCleanlyReportForCrashManager:`
* @see [Apple Technical Note TN2151](https://developer.apple.com/library/ios/technotes/tn2151/_index.html)
* @see [Apple Technical Q&A QA1693](https://developer.apple.com/library/ios/qa/qa1693/_index.html)
*/
@property (nonatomic, assign) BOOL appNotTerminatingCleanlyDetectionEnabled;
/**
* Set the callbacks that will be executed prior to program termination after a crash has occurred
*
* PLCrashReporter provides support for executing an application specified function in the context
* of the crash reporter's signal handler, after the crash report has been written to disk.
*
* Writing code intended for execution inside of a signal handler is exceptionally difficult, and is _NOT_ recommended!
*
* _Program Flow and Signal Handlers_
*
* When the signal handler is called the normal flow of the program is interrupted, and your program is an unknown state. Locks may be held, the heap may be corrupt (or in the process of being updated), and your signal handler may invoke a function that was being executed at the time of the signal. This may result in deadlocks, data corruption, and program termination.
*
* _Async-Safe Functions_
*
* A subset of functions are defined to be async-safe by the OS, and are safely callable from within a signal handler. If you do implement a custom post-crash handler, it must be async-safe. A table of POSIX-defined async-safe functions and additional information is available from the [CERT programming guide - SIG30-C](https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers).
*
* Most notably, the Objective-C runtime itself is not async-safe, and Objective-C may not be used within a signal handler.
*
* Documentation taken from PLCrashReporter: https://www.plcrashreporter.org/documentation/api/v1.2-rc2/async_safety.html
*
* @see MSAICrashManagerPostCrashSignalCallback
* @see MSAICrashManagerCallbacks
*
* @param callbacks A pointer to an initialized PLCrashReporterCallback structure, see https://www.plcrashreporter.org/documentation/api/v1.2-rc2/struct_p_l_crash_reporter_callbacks.html
*/
- (void)setCrashCallbacks:(MSAICrashManagerCallbacks *)callbacks;
///-----------------------------------------------------------------------------
/// @name Crash Meta Information
///-----------------------------------------------------------------------------
/**
Indicates if the app crash in the previous session
Use this on startup, to check if the app starts the first time after it crashed
previously. You can use this also to disable specific events, like asking
the user to rate your app.
@warning This property only has a correct value, once `[MSAIApplicationInsights start]` was
invoked!
@see lastSessionCrashDetails
*/
@property (nonatomic, readonly) BOOL didCrashInLastSession;
/**
* Provides details about the crash that occured in the last app session
*/
@property (nonatomic, strong, readonly) MSAICrashDetails *lastSessionCrashDetails;
/**
Provides the time between startup and crash in seconds
Use this in together with `didCrashInLastSession` to detect if the app crashed very
early after startup. This can be used to delay app initialization until the crash
report has been sent to the server or if you want to do any other actions like
cleaning up some cache data etc.
Note that sending a crash reports starts as early as 1.5 seconds after the application
did finish launching!
The `MSAICrashManagerDelegate` protocol provides some delegates to inform if sending
a crash report was finished successfully, ended in error or was cancelled by the user.
*Default*: _-1_
@see didCrashInLastSession
@see MSAICrashManagerDelegate
*/
@property (nonatomic, readonly) NSTimeInterval timeintervalCrashInLastSessionOccured;
/**
Indicates if the app did receive a low memory warning in the last session
It may happen that low memory warning where send but couldn't be logged, since iOS
killed the app before updating the flag in the filesystem did complete.
This property may be true in case of low memory kills, but it doesn't have to be! Apps
can also be killed without the app ever receiving a low memory warning.
Also the app could have received a low memory warning, but the reason for being killed was
actually different.
@warning This property only has a correct value, once `[MSAIApplicationInsights start]` was
invoked!
@see appNotTerminatingCleanlyDetectionEnabled
@see lastSessionCrashDetails
*/
@property (nonatomic, readonly) BOOL didReceiveMemoryWarningInLastSession;
///-----------------------------------------------------------------------------
/// @name Debugging Helpers
///-----------------------------------------------------------------------------
/**
* Detect if a debugger is attached to the app process
*
* This is only invoked once on app startup and can not detect if the debugger is being
* attached during runtime!
*
* @return BOOL if the debugger is attached on app startup
*/
@property (nonatomic, readonly, getter=getIsDebuggerAttached) BOOL debuggerIsAttached;
/**
* Lets the app crash for easy testing of the SDK
*
* The best way to use this is to trigger the crash with a button action.
*
* Make sure not to let the app crash in `applicationDidFinishLaunching` or any other
* startup method! Since otherwise the app would crash before the SDK could process it.
*
* Note that our SDK provides support for handling crashes that happen early on startup.
* Check the documentation for more information on how to use this.
*
* If the SDK detects an App Store environment, it will _NOT_ cause the app to crash!
*/
- (void)generateTestCrash;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,645 +0,0 @@
#import "ApplicationInsights.h"
#if MSAI_FEATURE_CRASH_REPORTER
#import "ApplicationInsightsPrivate.h"
#import "MSAIHelper.h"
#import "MSAICrashManagerPrivate.h"
#import "MSAICrashDataProvider.h"
#import "MSAICrashDetailsPrivate.h"
#import "MSAICrashData.h"
#import "MSAICrashDataHeaders.h"
#import "MSAICrashCXXExceptionHandler.h"
#import "MSAIChannel.h"
#import "MSAIChannelPrivate.h"
#import "MSAIPersistencePrivate.h"
#import "MSAIContextHelper.h"
#import "MSAIContextHelperPrivate.h"
#import "MSAIEnvelope.h"
#import "MSAIEnvelopeManager.h"
#import "MSAIEnvelopeManagerPrivate.h"
#import "MSAIData.h"
#import <mach-o/loader.h>
#import <mach-o/dyld.h>
#include <sys/sysctl.h>
// stores the set of crashreports that have been approved but aren't sent yet
#define kMSAICrashApprovedReports @"MSAICrashApprovedReports" //TODO remove this in next Sprint
// internal keys
NSString *const kMSAICrashManagerIsDisabled = @"MSAICrashManagerIsDisabled";
NSString *const kMSAIAppWentIntoBackgroundSafely = @"MSAIAppWentIntoBackgroundSafely";
NSString *const kMSAIAppDidReceiveLowMemoryNotification = @"MSAIAppDidReceiveLowMemoryNotification";
static char const *saveEventsFilePath;
static MSAICrashManagerCallbacks msaiCrashCallbacks = {
.context = NULL,
.handleSignal = NULL
};
// Proxy implementation for PLCrashReporter to keep our interface stable while this can change
static void plcr_post_crash_callback(siginfo_t *info, ucontext_t *uap, void *context) {
msai_save_events_callback(info, uap, context);
if(msaiCrashCallbacks.handleSignal != NULL) {
msaiCrashCallbacks.handleSignal(context);
}
}
// Proxy that is set as a callback when the developer defined a custom callback.
// The developer's callback will be called in plcr_post_crash_callback in addition to our default function.
static PLCrashReporterCallbacks plCrashCallbacks = {
.version = 0,
.context = NULL,
.handleSignal = plcr_post_crash_callback
};
// Our default callback that will always be executed, possibly in addition to a custom callback set by the developer.
static PLCrashReporterCallbacks defaultCallback = {
.version = 0,
.context = NULL,
.handleSignal = msai_save_events_callback
};
// Temporary class until PLCR catches up
// We trick PLCR with an Objective-C exception.
//
// This code provides us access to the C++ exception message, but we won't get a correct stack trace.
// The cause for this is that the iOS runtime catches every C++ exception internally and rethrows it.
// Since the exception object doesn't have the backtrace attached, we have no chance of accessing it.
//
// As a workaround we could hook into __cxx_throw and attaching the backtrace every time this is called.
// This has a few sides effects which is why we are not doing this right now:
// - CoreAdudio (and possibly other frameworks) use C++ exceptions heavily for control flow.
// Calling `backtrace()` is not cheap, so this could affect performance
// - It is not clear if such a hook is ABI compatible with all C++ runtimes
// - It is not clear if there could be any other side effects
//
// We'll evaluate this further to see if there is a safe solution.
//
@interface MSAICrashCXXExceptionWrapperException : NSException
- (instancetype)initWithCXXExceptionInfo:(const MSAICrashUncaughtCXXExceptionInfo *)info;
@end
@implementation MSAICrashCXXExceptionWrapperException {
const MSAICrashUncaughtCXXExceptionInfo *_info;
}
- (instancetype)initWithCXXExceptionInfo:(const MSAICrashUncaughtCXXExceptionInfo *)info {
extern char* __cxa_demangle(const char* mangled_name, char* output_buffer, size_t* length, int* status);
char *demangled_name = __cxa_demangle ? __cxa_demangle(info->exception_type_name ?: "", NULL, NULL, NULL) : NULL;
if ((self = [super
initWithName:[NSString stringWithUTF8String:demangled_name ?: info->exception_type_name ?: ""]
reason:[NSString stringWithUTF8String:info->exception_message ?: ""]
userInfo:nil])) {
_info = info;
}
return self;
}
- (NSArray *)callStackReturnAddresses {
NSMutableArray *cxxFrames = [NSMutableArray arrayWithCapacity:_info->exception_frames_count];
for (uint32_t i = 0; i < _info->exception_frames_count; ++i) {
[cxxFrames addObject:[NSNumber numberWithUnsignedLongLong:_info->exception_frames[i]]];
}
return cxxFrames;
}
@end
// C++ Exception Handler
static void uncaught_cxx_exception_handler(const MSAICrashUncaughtCXXExceptionInfo *info) {
// This relies on a LOT of sneaky internal knowledge of how PLCR works and should not be considered a long-term solution.
NSGetUncaughtExceptionHandler()([[MSAICrashCXXExceptionWrapperException alloc] initWithCXXExceptionInfo:info]);
abort();
}
@implementation MSAICrashManager {
id _appDidBecomeActiveObserver;
id _appWillTerminateObserver;
id _appDidEnterBackgroundObserver;
id _appWillEnterForegroundObserver;
id _appDidReceiveLowMemoryWarningObserver;
}
#pragma mark - Start
+ (instancetype)sharedManager {
static MSAICrashManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [self new];
});
return sharedManager;
}
/**
* Main startup sequence initializing PLCrashReporter if it wasn't disabled
*/
- (void)startManager {
if (self.isCrashManagerDisabled) {return;}
if (![MSAICrashManager sharedManager].isSetupCorrectly) {
[self checkCrashManagerDisabled];
[self registerObservers];
static dispatch_once_t plcrPredicate;
dispatch_once(&plcrPredicate, ^{
_timeintervalCrashInLastSessionOccured = -1;
[[MSAIPersistence sharedInstance] deleteCrashReporterLockFile];
[self configDefaultCallback];
[self configPLCrashReporter];
// Check if we previously crashed
if([self.plCrashReporter hasPendingCrashReport]) {
_didCrashInLastSession = YES;
[self readCrashReportAndStartProcessing];
}
// The actual signal and mach handlers are only registered when invoking `enableCrashReporterAndReturnError`
// So it is safe enough to only disable the following part when a debugger is attached no matter which
// signal handler type is set
// We only check for this if we are not in the App Store environment
if(!msai_isAppStoreEnvironment()) {
if(self.debuggerIsAttached) {
NSLog(@"[ApplicationInsights] WARNING: Detecting crashes is NOT enabled due to running the app with a debugger attached.");
}
}
[self setupExceptionHandler];
});
[self checkForLowMemoryWarning];
[self checkStateOfLastSession];
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive) {
[self appEnteredForeground];
}
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:kMSAIAppDidReceiveLowMemoryNotification];
[[NSUserDefaults standardUserDefaults] synchronize];
[MSAICrashManager sharedManager].isSetupCorrectly = YES;
}
}
- (void)dealloc {
[self unregisterObservers];
}
#pragma mark - Start Helpers
- (void)checkStateOfLastSession {
if(!self.didCrashInLastSession && self.appNotTerminatingCleanlyDetectionEnabled) {
BOOL didAppSwitchToBackgroundSafely = YES;
if([[NSUserDefaults standardUserDefaults] valueForKey:kMSAIAppWentIntoBackgroundSafely])
didAppSwitchToBackgroundSafely = [[NSUserDefaults standardUserDefaults] boolForKey:kMSAIAppWentIntoBackgroundSafely];
if(!didAppSwitchToBackgroundSafely) {
BOOL considerReport = YES;
if(self.delegate &&
[self.delegate respondsToSelector:@selector(considerAppNotTerminatedCleanlyReportForCrashManager)]) {
considerReport = [self.delegate considerAppNotTerminatedCleanlyReportForCrashManager];
}
if(considerReport) {
[self createCrashReportForAppKill];
_didCrashInLastSession = YES;
}
}
}
}
- (void)checkForLowMemoryWarning {
if([[NSUserDefaults standardUserDefaults] valueForKey:kMSAIAppDidReceiveLowMemoryNotification]) {
_didReceiveMemoryWarningInLastSession = [[NSUserDefaults standardUserDefaults] boolForKey:kMSAIAppDidReceiveLowMemoryNotification];
}
}
- (void)setupExceptionHandler {
if(!self.debuggerIsAttached) {
// Multiple exception handlers can be set, but we can only query the top level error handler (uncaught exception handler).
//
// To check if PLCrashReporter's error handler is successfully added, we compare the top
// level one that is set before and the one after PLCrashReporter sets up its own.
//
// With delayed processing we can then check if another error handler was set up afterwards
// and can show a debug warning log message, that the dev has to make sure the "newer" error handler
// doesn't exit the process itself, because then all subsequent handlers would never be invoked.
//
// Note: ANY error handler setup BEFORE ApplicationInsights initialization will not be processed!
// get the current top level error handler
NSUncaughtExceptionHandler *initialHandler = NSGetUncaughtExceptionHandler();
// PLCrashReporter may only be initialized once. So make sure the developer
// can't break this
NSError *error = NULL;
// set any user defined callbacks, hopefully the users knows what they do
if(self.crashCallBacks) {
[self.plCrashReporter setCrashCallbacks:self.crashCallBacks];
} else {
[self.plCrashReporter setCrashCallbacks:&defaultCallback];
}
// Enable the Crash Reporter
if(![self.plCrashReporter enableCrashReporterAndReturnError:&error]) {
NSLog(@"[ApplicationInsights] WARNING: Could not enable crash reporter: %@", [error localizedDescription]);
}
// get the new current top level error handler, which should now be the one from PLCrashReporter
NSUncaughtExceptionHandler *currentHandler = NSGetUncaughtExceptionHandler();
// do we have a new top level error handler? then we were successful
if(currentHandler && currentHandler != initialHandler) {
self.exceptionHandler = currentHandler;
MSAILog(@"INFO: Exception handler successfully initialized.");
} else {
// this should never happen, theoretically only if NSSetUncaugtExceptionHandler() has some internal issues
NSLog(@"[ApplicationInsights] ERROR: Exception handler could not be set. Make sure there is no other exception handler set up!");
}
// Add the C++ uncaught exception handler, which is currently not handled by PLCrashReporter internally
[MSAICrashUncaughtCXXExceptionHandlerManager addCXXExceptionHandler:uncaught_cxx_exception_handler];
}
}
- (void)configPLCrashReporter {
PLCrashReporterSignalHandlerType signalHandlerType = PLCrashReporterSignalHandlerTypeBSD;
if(self.machExceptionHandlerEnabled) {
signalHandlerType = PLCrashReporterSignalHandlerTypeMach;
}
PLCrashReporterSymbolicationStrategy symbolicationStrategy = PLCrashReporterSymbolicationStrategyNone;
if(self.onDeviceSymbolicationEnabled) {
symbolicationStrategy = PLCrashReporterSymbolicationStrategyAll;
}
MSAIPLCrashReporterConfig *config = [[MSAIPLCrashReporterConfig alloc] initWithSignalHandlerType:signalHandlerType
symbolicationStrategy:symbolicationStrategy];
self.plCrashReporter = [[MSAIPLCrashReporter alloc] initWithConfiguration:config];
}
- (void)checkCrashManagerDisabled {
NSString *testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kMSAICrashManagerIsDisabled];
if(testValue) {
self.isCrashManagerDisabled = [[NSUserDefaults standardUserDefaults] boolForKey:kMSAICrashManagerIsDisabled];
} else {
[[NSUserDefaults standardUserDefaults] setBool:self.isCrashManagerDisabled forKey:kMSAICrashManagerIsDisabled];
}
}
#pragma mark - Configuration
// Enable/Disable the CrashManager and store the setting in standardUserDefaults
- (void)setCrashManagerDisabled:(BOOL)disableCrashManager {
_isCrashManagerDisabled = disableCrashManager;
[[NSUserDefaults standardUserDefaults] setBool:disableCrashManager forKey:kMSAICrashManagerIsDisabled];
}
/**
* Set the callback for PLCrashReporter
*
* @param callbacks MSAICrashManagerCallbacks instance
*/
- (void)setCrashCallbacks:(MSAICrashManagerCallbacks *)callbacks {
if(!callbacks) return;
// set our proxy callback struct
msaiCrashCallbacks.context = callbacks->context;
msaiCrashCallbacks.handleSignal = callbacks->handleSignal;
// set the PLCrashReporterCallbacks struct
plCrashCallbacks.context = callbacks->context;
self.crashCallBacks = &plCrashCallbacks;
}
- (void)configDefaultCallback {
saveEventsFilePath = strdup([[[MSAIPersistence sharedInstance] newFileURLForPersitenceType:MSAIPersistenceTypeRegular] UTF8String]);
}
void msai_save_events_callback(siginfo_t *info, ucontext_t *uap, void *context) {
// Try to get a file descriptor with our pre-filled path
int fd = open(saveEventsFilePath, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
return;
}
size_t len = strlen(MSAISafeJsonEventsString);
if (len > 0) {
// Simply write the whole string to disk and close the JSON array
write(fd, MSAISafeJsonEventsString, len);
if ((len >= 1) && strncmp(MSAISafeJsonEventsString, "[", 1) == 0) {
write(fd, "]", 1);
}
}
close(fd);
}
#pragma mark - Debugging Helpers
- (BOOL)getIsDebuggerAttached {
return msai_isDebuggerAttached();
}
- (void)generateTestCrash {
if(!msai_isAppStoreEnvironment()) {
if(self.debuggerIsAttached) {
NSLog(@"[ApplicationInsights] WARNING: The debugger is attached. The following crash cannot be detected by the SDK!");
}
__builtin_trap();
}
}
#pragma mark - Lifecycle Notifications
- (void)registerObservers {
__weak typeof(self) weakSelf = self;
if(nil == _appDidBecomeActiveObserver) {
_appDidBecomeActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification
object:nil
queue:NSOperationQueue.mainQueue
usingBlock:^(NSNotification *note) {
typeof(self) strongSelf = weakSelf;
[strongSelf readCrashReportAndStartProcessing];
}];
}
if(nil == _appWillTerminateObserver) {
_appWillTerminateObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillTerminateNotification
object:nil
queue:NSOperationQueue.mainQueue
usingBlock:^(NSNotification *note) {
typeof(self) strongSelf = weakSelf;
[strongSelf leavingAppSafely];
}];
}
if(nil == _appDidEnterBackgroundObserver) {
_appDidEnterBackgroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification
object:nil
queue:NSOperationQueue.mainQueue
usingBlock:^(NSNotification *note) {
typeof(self) strongSelf = weakSelf;
[strongSelf leavingAppSafely];
}];
}
if(nil == _appWillEnterForegroundObserver) {
_appWillEnterForegroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification
object:nil
queue:NSOperationQueue.mainQueue
usingBlock:^(NSNotification *note) {
typeof(self) strongSelf = weakSelf;
[strongSelf appEnteredForeground];
}];
}
if(nil == _appDidReceiveLowMemoryWarningObserver) {
_appDidReceiveLowMemoryWarningObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidReceiveMemoryWarningNotification
object:nil
queue:NSOperationQueue.mainQueue
usingBlock:^(NSNotification *note) {
typeof(self) strongSelf = weakSelf;
// we only need to log this once
if(!strongSelf.didLogLowMemoryWarning) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kMSAIAppDidReceiveLowMemoryNotification];
[[NSUserDefaults standardUserDefaults] synchronize];
strongSelf.didLogLowMemoryWarning = YES;
}
}];
}
}
- (void)unregisterObservers {
[self unregisterObserver:_appDidBecomeActiveObserver];
[self unregisterObserver:_appWillTerminateObserver];
[self unregisterObserver:_appDidEnterBackgroundObserver];
[self unregisterObserver:_appWillEnterForegroundObserver];
[self unregisterObserver:_appDidReceiveLowMemoryWarningObserver];
}
- (void)unregisterObserver:(id)observer {
if(observer) {
[[NSNotificationCenter defaultCenter] removeObserver:observer];
observer = nil;
}
}
//Safe info about safe termination of the app to NSUserDefaults
- (void)leavingAppSafely {
if(self.appNotTerminatingCleanlyDetectionEnabled)
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kMSAIAppWentIntoBackgroundSafely];
}
/**
* Stores info about didEnterBackground in NSUserDefaults.
*/
- (void)appEnteredForeground {
// we disable kill detection while the debugger is running, since we'd get only false positives if the app is terminated by the user using the debugger
if(self.debuggerIsAttached) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kMSAIAppWentIntoBackgroundSafely];
} else if(self.appNotTerminatingCleanlyDetectionEnabled) {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:kMSAIAppWentIntoBackgroundSafely];
}
}
#pragma mark - PLCrashReporter
/**
* Process new crash reports provided by PLCrashReporter
*
* Parse the new crash report and gather additional meta data from the app which will be stored along the crash report
*/
- (void)readCrashReportAndStartProcessing {
NSError *error = NULL;
if(!self.plCrashReporter) {
return;
}
NSData *crashData;
// check if the next call ran successfully the last time
// check again if we have a pending crash report to be sure we actually have something to load
if(![[MSAIPersistence sharedInstance] crashReportLockFilePresent] && [self.plCrashReporter hasPendingCrashReport]) {
// mark the start of the routine
[[MSAIPersistence sharedInstance] createCrashReporterLockFile];
// Try loading the crash report
crashData = [[NSData alloc] initWithData:[self.plCrashReporter loadPendingCrashReportDataAndReturnError:&error]];
if(crashData == nil) {
MSAILog(@"ERROR: Could not load crash report: %@", error);
} else {
// get the startup timestamp from the crash report, and the file timestamp to calculate the timeinterval when the crash happened after startup
MSAIPLCrashReport *report = [[MSAIPLCrashReport alloc] initWithData:crashData error:&error];
if(report == nil) {
MSAILog(@"WARNING: Could not parse crash report");
}
else {
NSDate *appStartTime = nil;
NSDate *appCrashTime = nil;
if([report.processInfo respondsToSelector:@selector(processStartTime)]) {
if(report.systemInfo.timestamp && report.processInfo.processStartTime) {
appStartTime = report.processInfo.processStartTime;
appCrashTime = report.systemInfo.timestamp;
_timeintervalCrashInLastSessionOccured = [report.systemInfo.timestamp timeIntervalSinceDate:report.processInfo.processStartTime];
}
}
NSString *incidentIdentifier = @"???";
if(report.uuidRef != NULL) {
incidentIdentifier = (NSString *) CFBridgingRelease(CFUUIDCreateString(NULL, report.uuidRef));
}
NSString *reporterKey = msai_appAnonID() ?: @"";
_lastSessionCrashDetails = [[MSAICrashDetails alloc] initWithIncidentIdentifier:incidentIdentifier
reporterKey:reporterKey
signal:report.signalInfo.name
exceptionName:report.exceptionInfo.exceptionName
exceptionReason:report.exceptionInfo.exceptionReason
appStartTime:appStartTime
crashTime:appCrashTime
osVersion:report.systemInfo.operatingSystemVersion
osBuild:report.systemInfo.operatingSystemBuild
appBuild:report.applicationInfo.applicationVersion
];
}
}
}
if(!msai_isRunningInAppExtension() &&
[[UIApplication sharedApplication] applicationState] != UIApplicationStateActive) {
[[MSAIPersistence sharedInstance] deleteCrashReporterLockFile];//TODO only do this when persisting was successful?
return;
}
// check again if another exception handler was added with a short delay
[self performSelector:@selector(checkForOtherExceptionHandlersAfterSetup) withObject:nil afterDelay:0.5f];
[self createCrashReportWithCrashData:crashData];
// Purge the report
// mark the end of the routine
[[MSAIPersistence sharedInstance] deleteCrashReporterLockFile];//TODO only do this when persisting was successful?
[self.plCrashReporter purgePendingCrashReport]; //TODO only do this when persisting was successful?
[[MSAIContextHelper sharedInstance] cleanUpMetaData];
}
- (void)checkForOtherExceptionHandlersAfterSetup {
// was our own exception handler successfully added?
if (self.exceptionHandler) {
// get the current top level error handler
NSUncaughtExceptionHandler *currentHandler = NSGetUncaughtExceptionHandler();
// If the top level error handler differs from our own, then at least another one was added.
// This could cause exception crashes not to be reported to HockeyApp. See log message for details.
if (self.exceptionHandler != currentHandler) {
NSLog(@"[ApplicationInsights] ERROR: Exception handler could not be set. Make sure there is no other exception handler set up!");
}
}
}
#pragma mark - Crash Report Processing
/**
* Creates a crash template because the app was killed while being in foreground
*/
- (void)createCrashReportForAppKill {
MSAICrashDataHeaders *crashHeaders = [MSAICrashDataHeaders new];
crashHeaders.crashDataHeadersId = msai_UUID();
crashHeaders.exceptionType = kMSAICrashKillSignal;
crashHeaders.exceptionCode = @"00000020 at 0x8badf00d";
crashHeaders.exceptionReason = @"The application did not terminate cleanly but no crash occured. The app received at least one Low Memory Warning.";
MSAICrashData *crashData = [MSAICrashData new];
crashData.headers = crashHeaders;
MSAIData *data = [MSAIData new];
data.baseData = crashData;
data.baseType = crashData.dataTypeName;
MSAIEnvelope *crashTemplate = [[MSAIEnvelopeManager sharedManager] envelope];
crashTemplate.data = data;
crashTemplate.name = crashData.envelopeTypeName;
[[MSAIPersistence sharedInstance] persistCrashTemplate:crashTemplate];
}
/***
* Gathers all collected data and constructs Crash into an Envelope for processing
*/
- (void)createCrashReportWithCrashData:(NSData*)crashData {
if(!crashData) {
return;
}
NSError *error = NULL;
if([crashData length] > 0) {
MSAIPLCrashReport *report = nil;
MSAIEnvelope *crashEnvelope = nil;
report = [[MSAIPLCrashReport alloc] initWithData:crashData error:&error];
if(report) {
crashEnvelope = [MSAICrashDataProvider crashDataForCrashReport:report];
if([report.applicationInfo.applicationVersion compare:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]] == NSOrderedSame) {
//TODO Check if this has to be added again
// _crashIdenticalCurrentVersion = YES;
}
}
if([report.applicationInfo.applicationVersion compare:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]] == NSOrderedSame) {
//TODO Check if this has to be added again
// _crashIdenticalCurrentVersion = YES;
}
if(report == nil && crashEnvelope == nil) {
MSAILog(@"WARNING: Could not parse crash report");
// we cannot do anything with this report, so don't continue
// the next crash will be automatically processed on the next app start/becoming active event
return;
}
MSAILog(@"INFO: Persisting crash reports started.");
[[MSAIChannel sharedChannel] processDictionary:[crashEnvelope serializeToDictionary] withCompletionBlock:nil];
}
}
#pragma mark - Logging Helpers
- (void)reportError:(NSError *)error {
MSAILog(@"ERROR: %@", [error localizedDescription]);
}
@end
#endif /* MSAI_FEATURE_CRASH_REPORTER */

Просмотреть файл

@ -1,59 +0,0 @@
#import <Foundation/Foundation.h>
#import "MSAINullability.h"
@class MSAICrashManager;
NS_ASSUME_NONNULL_BEGIN
/**
The `MSAICrashManagerDelegate` formal protocol defines methods further configuring
the behaviour of `MSAICrashManager`.
*/
@protocol MSAICrashManagerDelegate <NSObject>
@optional
///-----------------------------------------------------------------------------
/// @name Networking
///-----------------------------------------------------------------------------
//Reason for this: http://support.hockeyapp.net/kb/client-integration-ios-mac-os-x/how-to-handle-crashes-during-startup-on-ios
/** Invoked right before sending crash reports will start
*/
- (void)crashManagerWillSendCrashReport; //TODO this should be part of the MSAISenderDelegate
/** Invoked after sending crash reports failed
@param error The error returned from the NSURLConnection call or `kMSAICrashErrorDomain`
with reason of type `MSAICrashErrorReason`.
*/
- (void)crashManagerDidFailWithError:(NSError *)error;
/** Invoked after sending crash reports succeeded
*/
- (void)crashManagerDidFinishSendingCrashReport;
///-----------------------------------------------------------------------------
/// @name Experimental
///-----------------------------------------------------------------------------
/** Define if a report should be considered as a crash report
Due to the risk, that these reports may be false positives, this delegates allows the
developer to influence which reports detected by the heuristic should actually be reported.
The developer can use the following property to get more information about the crash scenario:
- `[MSAICrashManager didReceiveMemoryWarningInLastSession]`: Did the app receive a low memory warning
This allows only reports to be considered where at least one low memory warning notification was
received by the app to reduce to possibility of having false positives.
@return `YES` if the heuristic based detected report should be reported, otherwise `NO`
@see `[MSAICrashManager didReceiveMemoryWarningInLastSession]`
*/
- (BOOL)considerAppNotTerminatedCleanlyReportForCrashManager;
//not implemented as property as users want to implement logic
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,117 +0,0 @@
#import "ApplicationInsights.h"
#if MSAI_FEATURE_CRASH_REPORTER
#import <CrashReporter/CrashReporter.h>
@class MSAIAppClient;
@class MSAIEnvelope;
NS_ASSUME_NONNULL_BEGIN
@interface MSAICrashManager ()
///-----------------------------------------------------------------------------
/// @name Properties
///-----------------------------------------------------------------------------
/**
Sets the optional `MSAICrashManagerDelegate` delegate.
The delegate is automatically set by using `[MSAIManager setDelegate:]`. You
should not need to set this delegate individually.
@see `[MSAIManager setDelegate:]`
*/
@property (nonatomic, weak) id delegate; //TODO Will be removed eventually
/*
Optional callbacks that will be called when PLCrashReporter finds a crash. Hopefully users know what they do if they use
this.
*/
@property (nonatomic, assign) PLCrashReporterCallbacks *crashCallBacks;
/*
The crashReporter instance.
*/
@property (nonatomic, strong) MSAIPLCrashReporter *plCrashReporter;
/*
Value that indicates a low memory warning has been sent to the app. For memory warnings related to the last session,
@see didReceiveMemoryWarningInLastSession.
*/
@property (nonatomic, assign) BOOL didLogLowMemoryWarning;
/**
* The exceptionhandler that is used for crash reporting.
*/
@property (nonatomic, assign) NSUncaughtExceptionHandler *exceptionHandler;
/**
* This method is used to setup the CrashManager-Module of the Application Insights SDK.
* This method is called by MSAIManager during it's initialization, so calling this by hand
* shouldn't be necessary in most cases. It won't do anything if MSAICrashManager has been disabled.*
*/
- (void)startManager;
/**
* Checks if the crashreporting module of ApplicationInsights has been disabled
*/
- (void)checkCrashManagerDisabled;
/**
* The method that's responsible to read crash data created by from MSAIPLCrashReporter and collects additional info
* about the last crash (@see lastSessionCrashDetails)
*/
- (void)readCrashReportAndStartProcessing;
/**
* Creates a "fake" crash report for an app kill (a case where we can't provide a regular crash report because it's not
* technically possible.
*/
- (void)createCrashReportForAppKill;
/**
* Format and create the ApplicationInsights crash report data and forward it to `MSAIChannel´for persistence and sending
*/
- (void)createCrashReportWithCrashData:(NSData*)crashData;
/**
* Write info about safely leaving the app to NSUserDefaults.
*/
- (void)leavingAppSafely;
/**
* Write info about the app entering the foreground safely into NSUserDefaults.
*/
- (void)appEnteredForeground;
/**
* by default, just logs the message
*
* can be overridden by subclasses to do their own error handling,
* e.g. to show UI
*
* @param error NSError
*/
- (void)reportError:(NSError *)error;
/**
* Because we can't access any Objective-C code from our default signal handler callback, we need to have all necessary data and pointers already in place once it runs.
* This method sets permanent references to [MSAIChannel sharedChannel] and file path to which our data is written in case of a crash.
*/
- (void)configDefaultCallback;
/**
* This function is used as our default callback in PLCrashReporter's signal handler.
* It tries to write to disk the string kept by MSAIChannel as a backup.
*
*/
void msai_save_events_callback(siginfo_t *info, ucontext_t *uap, void *context);
@end
NS_ASSUME_NONNULL_END
#endif /* MSAI_FEATURE_CRASH_REPORTER */

Просмотреть файл

@ -1,5 +1,5 @@
#import <Foundation/Foundation.h>
#import "MSAINullability.h"
#import "ApplicationInsights.h"
NS_ASSUME_NONNULL_BEGIN
@interface MSAIEnvelopeManager : NSObject

Просмотреть файл

@ -6,7 +6,6 @@
#import "MSAITelemetryContext.h"
#import "MSAITelemetryContextPrivate.h"
#import "MSAIHelper.h"
#import "MSAICrashDataProvider.h"
#import "MSAIHelper.h"
static NSInteger const schemaVersion = 2;
@ -70,12 +69,4 @@ static NSInteger const schemaVersion = 2;
return envelope;
}
- (MSAIEnvelope *)envelopeForCrashReport:(MSAIPLCrashReport *)report {
return [self envelopeForCrashReport:report exception:nil];
}
- (MSAIEnvelope *)envelopeForCrashReport:(MSAIPLCrashReport *)report exception:(NSException *)exception {
return [MSAICrashDataProvider crashDataForCrashReport:report handledException:exception];
}
@end

Просмотреть файл

@ -1,10 +1,9 @@
#import <Foundation/Foundation.h>
#import "MSAIEnvelopeManager.h"
@class MSAIEnvelope;
@class MSAITelemetryData;
@class MSAITelemetryContext;
@class MSAIPLCrashReport;
#import <Foundation/Foundation.h>
#import "MSAIEnvelopeManager.h"
#import "ApplicationInsights.h"
NS_ASSUME_NONNULL_BEGIN
@interface MSAIEnvelopeManager()
@ -52,25 +51,5 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (MSAIEnvelope *)envelopeForTelemetryData:(MSAITelemetryData *)telemetryData;
/**
* Creates an envelope object based on the information of a given crash report.
*
* @param report the crash report which contains context and exception information.
*
* @return an envelope object that contains a crash report
*/
- (MSAIEnvelope *)envelopeForCrashReport:(MSAIPLCrashReport *)report;
/**
* Creates an envelope object based on the information of a given crash report. This method is
* used to send handled exception rather than crashs.
*
* @param report the report, which contains context as well as exception information
* @param exception a handled exception object
*
* @return an envelope object that contains a handled exception
*/
- (MSAIEnvelope *)envelopeForCrashReport:(MSAIPLCrashReport *)report exception:(nullable NSException *)exception;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,19 +0,0 @@
#import "MSAIDomain.h"
#import "MSAIEnums.h"
@interface MSAIExceptionData : MSAIDomain <NSCoding>
@property (nonatomic, copy, readonly) NSString *envelopeTypeName;
@property (nonatomic, copy, readonly) NSString *dataTypeName;
@property (nonatomic, copy) NSString *handledAt;
@property (nonatomic, copy) NSString *problemId;
@property (nonatomic, copy) NSNumber *crashThreadId;
@property (nonatomic, strong) NSMutableArray *exceptions;
@property (nonatomic, assign) MSAISeverityLevel severityLevel;
@property (nonatomic, strong) MSAIOrderedDictionary *measurements;
- (instancetype)initWithCoder:(NSCoder *)coder;
- (void)encodeWithCoder:(NSCoder *)coder;
@end

Просмотреть файл

@ -1,87 +0,0 @@
#import "MSAIExceptionData.h"
#import "MSAIOrderedDictionary.h"
#import "MSAIEnums.h"
#import "MSAIExceptionDetails.h"
/// Data contract class for type ExceptionData.
@implementation MSAIExceptionData
@synthesize envelopeTypeName = _envelopeTypeName;
@synthesize dataTypeName = _dataTypeName;
@synthesize version = _version;
@synthesize properties = _properties;
/// Initializes a new instance of the class.
- (instancetype)init {
if (self = [super init]) {
_envelopeTypeName = @"Microsoft.ApplicationInsights.Exception";
_dataTypeName = @"ExceptionData";
_version = @2;
_exceptions = [NSMutableArray new];
_properties = [MSAIOrderedDictionary new];
_measurements = [MSAIOrderedDictionary new];
}
return self;
}
///
/// Adds all members of this class to a dictionary
/// @param dictionary to which the members of this class will be added.
///
- (MSAIOrderedDictionary *)serializeToDictionary {
MSAIOrderedDictionary *dict = [super serializeToDictionary];
if (self.handledAt != nil) {
[dict setObject:self.handledAt forKey:@"handledAt"];
}
if (self.problemId != nil) {
[dict setObject:self.problemId forKey:@"problemId"];
}
if (self.crashThreadId != nil) {
[dict setObject:self.crashThreadId forKey:@"crashThreadId"];
}
if (self.exceptions != nil) {
NSMutableArray *exceptionsArray = [NSMutableArray array];
for (MSAIExceptionDetails *exceptionsElement in self.exceptions) {
[exceptionsArray addObject:[exceptionsElement serializeToDictionary]];
}
[dict setObject:exceptionsArray forKey:@"exceptions"];
}
[dict setObject:@((int) self.severityLevel) forKey:@"severityLevel"];
if(self.problemId != nil) {
[dict setObject:self.problemId forKey:@"problemId"];
}
if(self.crashThreadId != nil) {
[dict setObject:self.crashThreadId forKey:@"crashThreadId"];
}
[dict setObject:self.properties forKey:@"properties"];
[dict setObject:self.measurements forKey:@"measurements"];
return dict;
}
#pragma mark - NSCoding
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if(self) {
_handledAt = [coder decodeObjectForKey:@"self.handledAt"];
_exceptions = [coder decodeObjectForKey:@"self.exceptions"];
_severityLevel = (MSAISeverityLevel) [coder decodeIntForKey:@"self.severityLevel"];
_problemId = [coder decodeObjectForKey:@"self.problemId"];
_crashThreadId = [coder decodeObjectForKey:@"self.crashThreadId"];
_measurements = [coder decodeObjectForKey:@"self.measurements"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.handledAt forKey:@"self.handledAt"];
[coder encodeObject:self.exceptions forKey:@"self.exceptions"];
[coder encodeInt:self.severityLevel forKey:@"self.severityLevel"];
[coder encodeObject:self.problemId forKey:@"self.problemId"];
[coder encodeObject:self.crashThreadId forKey:@"self.crashThreadId"];
[coder encodeObject:self.measurements forKey:@"self.measurements"];
}
@end

Просмотреть файл

@ -1,13 +0,0 @@
#import "MSAIObject.h"
@interface MSAIExceptionDetails : MSAIObject <NSCoding>
@property (nonatomic, copy) NSNumber *exceptionDetailsId;
@property (nonatomic, copy) NSNumber *outerId;
@property (nonatomic, copy) NSString *typeName;
@property (nonatomic, copy) NSString *message;
@property (nonatomic, assign) BOOL hasFullStack;
@property (nonatomic, copy) NSString *stack;
@property (nonatomic, strong) NSMutableArray *parsedStack;
@end

Просмотреть файл

@ -1,78 +0,0 @@
#import "MSAIExceptionDetails.h"
#import "MSAIStackFrame.h"
#import "MSAIOrderedDictionary.h"
/// Data contract class for type ExceptionDetails.
@implementation MSAIExceptionDetails
/// Initializes a new instance of the class.
- (instancetype)init {
if (self = [super init]) {
_hasFullStack = true;
_parsedStack = [NSMutableArray new];
}
return self;
}
///
/// Adds all members of this class to a dictionary
/// @param dictionary to which the members of this class will be added.
///
- (MSAIOrderedDictionary *)serializeToDictionary {
MSAIOrderedDictionary *dict = [super serializeToDictionary];
if (self.exceptionDetailsId != nil) {
[dict setObject:self.exceptionDetailsId forKey:@"id"];
}
if (self.outerId != nil) {
[dict setObject:self.outerId forKey:@"outerId"];
}
if (self.typeName != nil) {
[dict setObject:self.typeName forKey:@"typeName"];
}
if (self.message != nil) {
[dict setObject:self.message forKey:@"message"];
}
NSString *strhasFullStack = [NSString stringWithFormat:@"%s", (self.hasFullStack) ? "true" : "false"];
[dict setObject:strhasFullStack forKey:@"hasFullStack"];
if (self.stack != nil) {
[dict setObject:self.stack forKey:@"stack"];
}
if (self.parsedStack != nil) {
NSMutableArray *parsedStackArray = [NSMutableArray array];
for (MSAIStackFrame *parsedStackElement in self.parsedStack) {
[parsedStackArray addObject:[parsedStackElement serializeToDictionary]];
}
[dict setObject:parsedStackArray forKey:@"parsedStack"];
}
return dict;
}
#pragma mark - NSCoding
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super init];
if(self) {
_exceptionDetailsId = [coder decodeObjectForKey:@"self.exceptionDetailsId"];
_outerId = [coder decodeObjectForKey:@"self.outerId"];
_typeName = [coder decodeObjectForKey:@"self.typeName"];
_message = [coder decodeObjectForKey:@"self.message"];
_hasFullStack = [coder decodeBoolForKey:@"self.hasFullStack"];
_stack = [coder decodeObjectForKey:@"self.stack"];
_parsedStack = [coder decodeObjectForKey:@"self.parsedStack"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.exceptionDetailsId forKey:@"self.exceptionDetailsId"];
[coder encodeObject:self.outerId forKey:@"self.outerId"];
[coder encodeObject:self.typeName forKey:@"self.typeName"];
[coder encodeObject:self.message forKey:@"self.message"];
[coder encodeBool:self.hasFullStack forKey:@"self.hasFullStack"];
[coder encodeObject:self.stack forKey:@"self.stack"];
[coder encodeObject:self.parsedStack forKey:@"self.parsedStack"];
}
@end

Просмотреть файл

@ -8,8 +8,6 @@ NSString *msai_URLEncodedString(NSString *inputString);
NSString *msai_URLDecodedString(NSString *inputString);
NSString *msai_base64String(NSData *data);
NSString *msai_settingsDir(void);
NSString *msai_keychainMSAIServiceName(void);
NSString *msai_utcDateString(NSDate *date);

Просмотреть файл

@ -96,29 +96,6 @@ NSString *msai_base64String(NSData *data) {
#endif
}
NSString *msai_settingsDir(void) {
static NSString *settingsDir = nil;
static dispatch_once_t predSettingsDir;
dispatch_once(&predSettingsDir, ^{
NSFileManager *fileManager = [[NSFileManager alloc] init];
// temporary directory for crashes grabbed from PLCrashReporter
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
settingsDir = [paths[0] stringByAppendingPathComponent:kMSAIIdentifier];
if (![fileManager fileExistsAtPath:settingsDir]) {
NSDictionary *attributes = @{NSFilePosixPermissions : @0755};
NSError *theError = NULL;
[fileManager createDirectoryAtPath:settingsDir withIntermediateDirectories: YES attributes: attributes error: &theError];
}
});
return settingsDir;
}
NSString *msai_keychainMSAIServiceName(void) {
static NSString *serviceName = nil;
static dispatch_once_t predServiceName;
@ -355,6 +332,9 @@ BOOL msai_isAppStoreEnvironment(void){
* @return `YES` if the debugger is attached to the current process, `NO` otherwise
*/
BOOL msai_isDebuggerAttached(void) {
#if CI
return YES;
#endif
static BOOL debuggerIsAttached = NO;
static dispatch_once_t debuggerPredicate;
@ -370,11 +350,11 @@ BOOL msai_isDebuggerAttached(void) {
if(sysctl(name, 4, &info, &info_size, NULL, 0) == -1) {
NSLog(@"[ApplicationInsights] ERROR: Checking for a running debugger via sysctl() failed: %s", strerror(errno));
debuggerIsAttached = false;
debuggerIsAttached = NO;
}
if(!debuggerIsAttached && (info.kp_proc.p_flag & P_TRACED) != 0)
debuggerIsAttached = true;
debuggerIsAttached = YES;
});
return debuggerIsAttached;

Просмотреть файл

@ -4,6 +4,7 @@
/// Data contract class for type MessageData.
@implementation MSAIMessageData
@synthesize envelopeTypeName = _envelopeTypeName;
@synthesize dataTypeName = _dataTypeName;
@synthesize version = _version;

Просмотреть файл

@ -10,8 +10,6 @@ NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, MSAIPersistenceType) {
MSAIPersistenceTypeHighPriority = 0,
MSAIPersistenceTypeRegular = 1,
MSAIPersistenceTypeCrashTemplate = 2,
MSAIPersistenceTypeMetaData = 3
};
/**

Просмотреть файл

@ -1,14 +1,11 @@
#import "MSAIPersistence.h"
#import "MSAIPersistencePrivate.h"
#import "MSAIEnvelope.h"
#import "MSAICrashData.h"
#import "ApplicationInsightsPrivate.h"
#import "MSAIHelper.h"
NSString *const kHighPrioString = @"highPrio";
NSString *const kRegularPrioString = @"regularPrio";
NSString *const kCrashTemplateString = @"crashTemplate";
NSString *const kSessionIdsString = @"metaData";
NSString *const kFileBaseString = @"app-insights-bundle-";
NSString *const MSAIPersistenceSuccessNotification = @"MSAIPersistenceSuccessNotification";
@ -46,14 +43,12 @@ NSUInteger const defaultFileCount = 50;
return self;
}
//TODO remove the completion block and implement notification-handling in MSAICrashManager
- (void)persistBundle:(NSData *)bundle ofType:(MSAIPersistenceType)type withCompletionBlock:(nullable void (^)(BOOL success))completionBlock {
[self persistBundle:bundle ofType:type enableNotifications:YES withCompletionBlock:completionBlock];
}
/**
* Creates a serial background queue that saves the Bundle using NSKeyedArchiver and NSData's writeToFile:atomically
* In case if type MSAIPersistenceTypeCrashTemplate, we don't send out a kMSAIPersistenceSuccessNotification.
*
*/
- (void)persistBundle:(NSData *)bundle ofType:(MSAIPersistenceType)type enableNotifications:(BOOL)sendNotifications withCompletionBlock:(void (^)(BOOL success))completionBlock {
@ -67,7 +62,7 @@ NSUInteger const defaultFileCount = 50;
BOOL success = [bundle writeToFile:fileURL atomically:YES];
if(success) {
MSAILog(@"Wrote %@", fileURL);
if(sendNotifications && type != MSAIPersistenceTypeCrashTemplate) {
if(sendNotifications) {
[strongSelf sendBundleSavedNotification];
}
}
@ -87,14 +82,6 @@ NSUInteger const defaultFileCount = 50;
}
}
- (void)persistMetaData:(NSDictionary *)metaData {
NSString *fileURL = [self newFileURLForPersitenceType:MSAIPersistenceTypeMetaData];
dispatch_async(self.persistenceQueue, ^{
[NSKeyedArchiver archiveRootObject:metaData toFile:fileURL];
});
}
- (BOOL)isFreeSpaceAvailable{
return !_maxFileCountReached;
}
@ -117,29 +104,6 @@ NSUInteger const defaultFileCount = 50;
return path;
}
/**
* Method used to persist the "fake" crash reports. Crash templates are handled but are similar to the other bundle
* types under the hood.
*/
- (void)persistCrashTemplate:(MSAIEnvelope *)crashTemplate {
NSData *bundle = [NSKeyedArchiver archivedDataWithRootObject:@[crashTemplate]];
[self persistBundle:bundle ofType:MSAIPersistenceTypeCrashTemplate withCompletionBlock:nil];
}
/*
* @Returns a bundle that includes a crash template.
*/
- (NSArray *)crashTemplateBundle {
NSString *path = [self nextURLWithPriority:MSAIPersistenceTypeCrashTemplate];
if(path && path.length > 0) {
NSArray *bundle = [self bundleAtPath:path];
if(bundle) {
return bundle;
}
}
return nil;
}
/**
* Deserializes a bundle from disk using NSKeyedUnarchiver and deletes it from disk
* @return a bundle of data or nil
@ -152,15 +116,6 @@ NSUInteger const defaultFileCount = 50;
return bundle;
}
- (NSDictionary *)metaData {
NSDictionary *metaData = nil;
NSString *path = [self newFileURLForPersitenceType:MSAIPersistenceTypeMetaData];
if(path) {
metaData = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
}
return metaData;
}
- (NSData *)dataAtPath:(NSString *)path {
NSData *data = nil;
@ -224,16 +179,6 @@ NSUInteger const defaultFileCount = 50;
filePath = [[fileDir stringByAppendingPathComponent:kHighPrioString] stringByAppendingPathComponent:fileName];
break;
};
case MSAIPersistenceTypeCrashTemplate: {
[self createFolderAtPathIfNeeded:[fileDir stringByAppendingPathComponent:kCrashTemplateString]];
filePath = [[fileDir stringByAppendingPathComponent:kCrashTemplateString] stringByAppendingPathComponent:kCrashTemplateString];
break;
};
case MSAIPersistenceTypeMetaData: {
[self createFolderAtPathIfNeeded:[fileDir stringByAppendingPathComponent:kSessionIdsString]];
filePath = [[fileDir stringByAppendingPathComponent:kSessionIdsString] stringByAppendingPathComponent:kSessionIdsString];
break;
};
default: {
[self createFolderAtPathIfNeeded:[fileDir stringByAppendingPathComponent:kRegularPrioString]];
filePath = [[fileDir stringByAppendingPathComponent:kRegularPrioString] stringByAppendingPathComponent:fileName];
@ -325,18 +270,10 @@ NSUInteger const defaultFileCount = 50;
subfolderPath = kHighPrioString;
break;
};
case MSAIPersistenceTypeCrashTemplate: {
subfolderPath = kCrashTemplateString;
break;
};
case MSAIPersistenceTypeRegular: {
subfolderPath = kRegularPrioString;
break;
}
case MSAIPersistenceTypeMetaData: {
subfolderPath = kSessionIdsString;
break;
}
}
NSString *path = [persistenceFolder stringByAppendingPathComponent:subfolderPath];
@ -355,24 +292,4 @@ NSUInteger const defaultFileCount = 50;
});
}
- (BOOL)crashReportLockFilePresent {
NSString *analyzerInProgressFile = [msai_settingsDir() stringByAppendingPathComponent:kMSAICrashAnalyzer];
return [[NSFileManager defaultManager] fileExistsAtPath:analyzerInProgressFile];
}
- (void)createCrashReporterLockFile {
NSString *analyzerInProgressFile = [msai_settingsDir() stringByAppendingPathComponent:kMSAICrashAnalyzer];
[[NSFileManager defaultManager] createFileAtPath:analyzerInProgressFile contents:nil attributes:nil];
}
- (void)deleteCrashReporterLockFile {
NSString *analyzerInProgressFile = [msai_settingsDir() stringByAppendingPathComponent:kMSAICrashAnalyzer];
NSError *error = NULL;
if([[NSFileManager defaultManager] fileExistsAtPath:analyzerInProgressFile]) {
[[NSFileManager defaultManager] removeItemAtPath:analyzerInProgressFile error:&error];
}
}
@end

Просмотреть файл

@ -35,8 +35,8 @@ FOUNDATION_EXPORT NSString *const MSAIPersistenceSuccessNotification;
/**
* Saves the bundle and sends out a MSAIPersistenceSuccessNotification in case of success
* for all types except MSAIPersistenceTypeCrashTemplate
* @param bundle a bundle of tracked events (telemetry, crashes, ...) that will be serialized and saved.
* for all types
* @param bundle a bundle of tracked events that will be serialized and saved.
* @param type The type of the bundle we want to save.
* @param completionBlock An optional block that will be executed after we have tried to save the bundle.
*
@ -48,19 +48,12 @@ FOUNDATION_EXPORT NSString *const MSAIPersistenceSuccessNotification;
* Saves the bundle to disk.
*
* @param bundle the bundle, which should be saved to disk
* @param type the persistence type of the bundle (high prio/regular prio/crash template)
* @param type the persistence type of the bundle (high prio/regular prio)
* @param sendNotifications a flag which determines if a notification should be sent if saving was successful
* @param completionBlock a block which is executed after the bundle has been stored
*/
- (void)persistBundle:(NSData *)bundle ofType:(MSAIPersistenceType)type enableNotifications:(BOOL)sendNotifications withCompletionBlock:(void (^)(BOOL success))completionBlock;
/**
* Saves the given dictionary to the session Ids file.
*
* @param metaData a dictionary consisting of unix timestamps and session ids
*/
- (void)persistMetaData:(NSDictionary *)metaData;
/**
* Deletes the file for the given path.
*
@ -126,13 +119,6 @@ FOUNDATION_EXPORT NSString *const MSAIPersistenceSuccessNotification;
*/
- (NSData *)dataAtPath:(NSString *)path;
/**
* Returns the content of the session Ids file.
*
* @return return a dictionary containing all session Ids
*/
- (NSDictionary *)metaData;
///-----------------------------------------------------------------------------
/// @name Getting a path
///-----------------------------------------------------------------------------
@ -146,27 +132,5 @@ FOUNDATION_EXPORT NSString *const MSAIPersistenceSuccessNotification;
*/
- (NSString *)folderPathForPersistenceType:(MSAIPersistenceType)type;
///-----------------------------------------------------------------------------
/// @name Handling of a "fake" CrashReport
///-----------------------------------------------------------------------------
/**
* Persist a crash template.
*
* @param bundle The bundle of application insights data
*/
- (void)persistCrashTemplate:(MSAIEnvelope *)crashTemplate;
/**
* Get the persisted crash template.
*
* @return a crash template, wrapped as a bundle
*/
- (NSArray *)crashTemplateBundle;
- (BOOL)crashReportLockFilePresent;
- (void)createCrashReporterLockFile;
- (void)deleteCrashReporterLockFile;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -1,11 +0,0 @@
#import "MSAIObject.h"
@interface MSAIStackFrame : MSAIObject <NSCoding>
@property (nonatomic, copy) NSNumber *level;
@property (nonatomic, copy) NSString *method;
@property (nonatomic, copy) NSString *assembly;
@property (nonatomic, copy) NSString *fileName;
@property (nonatomic, copy) NSNumber *line;
@end

Просмотреть файл

@ -1,56 +0,0 @@
#import "MSAIStackFrame.h"
#import "MSAIOrderedDictionary.h"
/// Data contract class for type StackFrame.
@implementation MSAIStackFrame
///
/// Adds all members of this class to a dictionary
/// @param dictionary to which the members of this class will be added.
///
- (MSAIOrderedDictionary *)serializeToDictionary {
MSAIOrderedDictionary *dict = [super serializeToDictionary];
if (self.level != nil) {
[dict setObject:self.level forKey:@"level"];
}
if (self.method != nil) {
[dict setObject:self.method forKey:@"method"];
}
if (self.assembly != nil) {
[dict setObject:self.assembly forKey:@"assembly"];
}
if (self.fileName != nil) {
[dict setObject:self.fileName forKey:@"fileName"];
}
if (self.line != nil) {
[dict setObject:self.line forKey:@"line"];
}
return dict;
}
#pragma mark - NSCoding
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if(self) {
_level = [coder decodeObjectForKey:@"self.level"];
_method = [coder decodeObjectForKey:@"self.method"];
_assembly = [coder decodeObjectForKey:@"self.assembly"];
_fileName = [coder decodeObjectForKey:@"self.fileName"];
_line = [coder decodeObjectForKey:@"self.line"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.level forKey:@"self.level"];
[coder encodeObject:self.method forKey:@"self.method"];
[coder encodeObject:self.assembly forKey:@"self.assembly"];
[coder encodeObject:self.fileName forKey:@"self.fileName"];
[coder encodeObject:self.line forKey:@"self.line"];
}
@end

Просмотреть файл

@ -40,16 +40,13 @@ NSString *const kMSAISessionAcquisitionTime = @"MSAISessionAcquisitionTime";
applicationContext.version = appContext.appVersion;
MSAISession *sessionContext = [[MSAIContextHelper sharedInstance] newSession];
[[MSAIContextHelper sharedInstance] addSession:sessionContext withDate:[NSDate date]];
NSDictionary *userInfo = @{kMSAISessionInfo : sessionContext};
[[MSAIContextHelper sharedInstance] sendSessionStartedNotificationWithUserInfo:userInfo];
MSAIOperation *operationContext = [MSAIOperation new];
MSAIUser *userContext = [[MSAIContextHelper sharedInstance] userForDate:[NSDate date]];
MSAIUser *userContext = [[MSAIContextHelper sharedInstance] loadUser];
if (!userContext) {
userContext = [[MSAIContextHelper sharedInstance] newUser];
[[MSAIContextHelper sharedInstance] addUser:userContext forDate:[NSDate date]];
}
MSAILocation *locationContext = [MSAILocation new];

Просмотреть файл

@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* MSAITelemetryManager is the component of the Application Insights SDK for iOS that is responsible for all things
* that are related to metrics and tracking.
* It provides methods to track custom events, traces, metrics, pageviews and exceptions. You can access them via
* It provides methods to track custom events, traces, metrics, and pageviews. You can access them via
* class methods as well as via the sharedManager instance.
*/
@interface MSAITelemetryManager : NSObject
@ -116,7 +116,7 @@ NS_ASSUME_NONNULL_BEGIN
* @param pageName Name of the page/view which is being tracked.
* @param duration Time the page has been viewed in milliseconds. This method is ideally called when a page view ends where the time has to be calculated by the developer.
*/
+ (void)trackPageView:(NSString *)pageName duration:(long)duration;
+ (void)trackPageView:(NSString *)pageName duration:(NSTimeInterval)duration;
/**
* Track pageView by name of the page.
@ -125,14 +125,7 @@ NS_ASSUME_NONNULL_BEGIN
* @param duration time the page has been viewed. This method is ideally called when a page view ends. The time has to be calculated by the developer.
* @param properties key-value pairs which can contain additional information about the page view
*/
+ (void)trackPageView:(NSString *)pageName duration:(long)duration properties:(nullable NSDictionary *)properties;
/**
* Track handled exception.
*
* @param exception the handled exception, which should be send to the server.
*/
+ (void)trackException:(NSException *)exception;
+ (void)trackPageView:(NSString *)pageName duration:(NSTimeInterval)duration properties:(nullable NSDictionary *)properties;
/**
* Track the event by event name.
@ -201,25 +194,18 @@ NS_ASSUME_NONNULL_BEGIN
* Track pageView by name of the page.
*
* @param pageName Name of the page/view which is being tracked.
* @param duration Time the page has been viewed in milliseconds. This method is ideally called when a page view ends where the time has to be calculated by the developer.
* @param duration Time the page has been viewed in seconds. This method is ideally called when a page view ends where the time has to be calculated by the developer.
*/
- (void)trackPageView:(NSString *)pageName duration:(long)duration;
- (void)trackPageView:(NSString *)pageName duration:(NSTimeInterval)duration;
/**
* Track pageView by name of the page.
*
* @param pageName Name of the page/view which is being tracked.
* @param duration time the page has been viewed. This method is ideally called when a page view ends. The time has to be calculated by the developer.
* @param duration time the page has been viewed in seconds. This method is ideally called when a page view ends. The time has to be calculated by the developer.
* @param properties key-value pairs which can contain additional information about the page view
*/
- (void)trackPageView:(NSString *)pageName duration:(long)duration properties:(nullable NSDictionary *)properties;
/**
* Track handled exception.
*
* @param exception the handled exception, which should be send to the server.
*/
- (void)trackException:(NSException *)exception;
- (void)trackPageView:(NSString *)pageName duration:(NSTimeInterval)duration properties:(nullable NSDictionary *)properties;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -18,10 +18,6 @@
#import "MSAIPageViewData.h"
#import "MSAIDataPoint.h"
#import "MSAIEnums.h"
#import "MSAICrashDataProvider.h"
#import "MSAICrashData.h"
#import <pthread.h>
#import <CrashReporter/CrashReporter.h>
#import "MSAIEnvelope.h"
#import "MSAIEnvelopeManager.h"
#import "MSAIEnvelopeManagerPrivate.h"
@ -232,27 +228,6 @@ static char *const MSAICommonPropertiesQueue = "com.microsoft.ApplicationInsight
});
}
+ (void)trackException:(NSException *)exception {
[[self sharedManager] trackException:exception];
}
- (void)trackException:(NSException *)exception {
pthread_t thread = pthread_self();
dispatch_async(_telemetryEventQueue, ^{
PLCrashReporterSignalHandlerType signalHandlerType = PLCrashReporterSignalHandlerTypeBSD;
PLCrashReporterSymbolicationStrategy symbolicationStrategy = PLCrashReporterSymbolicationStrategyAll;
MSAIPLCrashReporterConfig *config = [[MSAIPLCrashReporterConfig alloc] initWithSignalHandlerType:signalHandlerType
symbolicationStrategy:symbolicationStrategy];
MSAIPLCrashReporter *cm = [[MSAIPLCrashReporter alloc] initWithConfiguration:config];
NSData *data = [cm generateLiveReportWithThread:pthread_mach_thread_np(thread)];
MSAIPLCrashReport *report = [[MSAIPLCrashReport alloc] initWithData:data error:nil];
MSAIEnvelope *envelope = [[MSAIEnvelopeManager sharedManager] envelopeForCrashReport:report exception:exception];
MSAIOrderedDictionary *dict = [envelope serializeToDictionary];
[[MSAIChannel sharedChannel] processDictionary:dict withCompletionBlock:nil];
});
}
+ (void)trackPageView:(NSString *)pageName {
[self trackPageView:pageName duration:0];
}
@ -261,19 +236,21 @@ static char *const MSAICommonPropertiesQueue = "com.microsoft.ApplicationInsight
[self trackPageView:pageName duration:0];
}
+ (void)trackPageView:(NSString *)pageName duration:(long)duration {
+ (void)trackPageView:(NSString *)pageName duration:(NSTimeInterval)duration {
[self trackPageView:pageName duration:duration properties:nil];
}
- (void)trackPageView:(NSString *)pageName duration:(long)duration {
- (void)trackPageView:(NSString *)pageName duration:(NSTimeInterval)duration {
[self trackPageView:pageName duration:duration properties:nil];
}
+ (void)trackPageView:(NSString *)pageName duration:(long)duration properties:(NSDictionary *)properties {
+ (void)trackPageView:(NSString *)pageName duration:(NSTimeInterval)duration properties:(NSDictionary *)properties {
[[self sharedManager] trackPageView:pageName duration:duration properties:properties];
}
- (void)trackPageView:(NSString *)pageName duration:(long)duration properties:(NSDictionary *)properties {
- (void)trackPageView:(NSString *)pageName duration:(NSTimeInterval)duration properties:(NSDictionary *)properties {
NSString *durationString = [self durationStringFromDuration:duration];
__weak typeof(self) weakSelf = self;
dispatch_async(_telemetryEventQueue, ^{
if(!_managerInitialised) return;
@ -281,12 +258,27 @@ static char *const MSAICommonPropertiesQueue = "com.microsoft.ApplicationInsight
typeof(self) strongSelf = weakSelf;
MSAIPageViewData *pageViewData = [MSAIPageViewData new];
pageViewData.name = pageName;
pageViewData.duration = [NSString stringWithFormat:@"%ld", duration];
pageViewData.duration = durationString;
pageViewData.properties = properties;
[strongSelf trackDataItem:pageViewData];
});
}
#pragma mark PageView Helper
- (NSString *)durationStringFromDuration:(NSTimeInterval)duration {
int milliseconds = (int)(fmod(duration, 1) * pow(10, 7));
int durationInt = (int)duration;
int seconds = durationInt % 60;
int minutes = (durationInt / 60) % 60;
int hours = (durationInt / 3600) % 24;
int days = (durationInt / 3600) / 24;
NSString *durationString = [NSString stringWithFormat:@"%01d:%02d:%02d:%02d.%07d", days, hours, minutes, seconds, milliseconds];
return durationString;
}
#pragma mark Track DataItem
- (void)trackDataItem:(MSAITelemetryData *)dataItem {

Просмотреть файл

@ -49,6 +49,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, strong) dispatch_queue_t commonPropertiesQueue;
/**
* Helper method that converts am NSTimeInterval value to a string of the format "d:hh:mm:ss.fffffff"
*/
- (NSString *)durationStringFromDuration:(NSTimeInterval)duration;
/**
* Converts the tracked to an envelope object and forwards it to the channel.
*

230
README.md
Просмотреть файл

@ -1,59 +1,61 @@
[![Build Status](https://travis-ci.org/Microsoft/ApplicationInsights-iOS.svg?branch=master)](https://travis-ci.org/Microsoft/ApplicationInsights-iOS)
# Application Insights for iOS (1.0-beta.6)
# Application Insights for iOS (1.0-beta.7)
This is the repository of the iOS SDK for Application Insights. [Application Insights](http://azure.microsoft.com/services/application-insights/) is a service that monitors the performance and usage of your published app. The SDK enables you to send telemetry of various kinds (events, traces, exceptions, etc.) to the Application Insights service where your data can be visualized in the Azure Portal.
This is the repository of the iOS SDK for Application Insights. [Application Insights](http://azure.microsoft.com/services/application-insights/) is a service that monitors the performance and usage of your published app. The SDK enables you to send telemetry of various kinds (events, traces, sessions etc.) to the Application Insights service where your data can be visualized in the Azure Portal.
You can use the [Application Insights for Mac](http://go.microsoft.com/fwlink/?linkid=533209&clcid=0x409) tool to integrate the Application Insights iOS SDK into your existing apps. It also supports with **uploading app symbols**, which are required to symbolicate the crash reports to display them properly in the Azure Portal.
You can use the [Application Insights for Mac](http://go.microsoft.com/fwlink/?linkid=533209&clcid=0x409) tool to integrate the Application Insights iOS SDK into your existing apps.
The SDK runs on devices with iOS 6.0 or higher. You'll need a subscription to [Microsoft Azure](https://azure.com). (It's free until you want to send quite a lot of telemetry.)
The SDK runs on devices with iOS 6.0 or higher.
[Application Insights overview](https://azure.microsoft.com/documentation/articles/app-insights-overview/)
##Breaking Changes!
Version 1.0-beta.7 of the Application Insights for iOS SDK comes with two major changes:
Crash Reporting and the API to send handled exceptions have been removed from the SDK. In addition, the Application Insights for iOS SDK is now deprecated.
The reason for this is that [HockeyApp](http://hockeyapp.net/) is now our major offering for mobile and cross-plattform crash reporting, beta distribution and user feedback. We are focusing all our efforts on enhancing the HockeySDK and adding telemetry features to make HockeyApp the best platform to build awesome apps. We've launched [HockeyApp Preseason](http://hockeyapp.net/blog/2016/02/02/introducing-preseason.html) so you can try all the new bits yourself, including User Metrics.
We apologize for any inconvenience and please feel free to [contact us](http://support.hockeyapp.net/) at any time.
## Content
1. [Release Notes](#releasenotes)
2. [Breaking Changes](#breakingchanges)
3. [Requirements](#requirements)
4. [Setup](#setup)
5. [Advanced Setup](#advancedsetup)
6. [Developer Mode](#developermode)
7. [Basic Usage](#basicusage)
8. [Advanced Usage](#advancedusage)
9. [Automatic collection of life-cycle events](#autolifecycle)
10. [Crash Reporting](#crashreporting)
11. [Set Custom Server Endpoint](#additionalconfig)
12. [Documentation](#documentation)
13. [Contributing](#contributing)
14. [Contact](#contact)
2. [Requirements](#requirements)
3. [Setup](#setup)
4. [Advanced Setup](#advancedsetup)
5. [Developer Mode](#developermode)
6. [Basic Usage](#basicusage)
7. [Advanced Usage](#advancedusage)
8. [Automatic collection of life-cycle events](#autolifecycle)
9. [Set Custom Server Endpoint](#additionalconfig)
10. [Documentation](#documentation)
11. [Contributing](#contributing)
12. [Contact](#contact)
<a name="releasenotes"></a>
## 1. Release Notes
* Important improvements to crash reports.
* We now filter some pageviews from standard view controllers in order to reduce noise and make pageviews more useful.
* Smaller refactorings and improvements.
* Remove crash reporting. To add this feature to your app, we recommend to use [HockeyApp](http://hockeyapp.net/features/) which provides you with superior crash reporting, feedback, beta distribution and much more.
* Enable Bitcode. This was previously not possible as Bitcode-enabled apps are recompiled at unknown times on Apple's servers and make it very hard to get fully symbolicated and useful crash reports.
* Fixes an issue where pageview durations where incorrectly sent as days instead of as a string in the 'd:hh:mm:ss.fffffff' format. The relevant methods now take an `NSTimeInterval` parameter with the duration in seconds.
See [here](https://github.com/Microsoft/ApplicationInsights-iOS/releases) for the release notes of previous versions.
<a name="breakingchanges"></a>
## 2. Breaking Changes
There haven't been any breaking changes since 1.0-beta.2. In case the API of the SDK changes, we will deprecate methods, etc. before removing them.
* **[1.0-beta.2]** ```MSAIAppInsights``` was the the central entry-point to use the Application Insights SDK. It has been renamed to ```MSAIApplicationInsights```.
* **[1.0-beta.2]** Setting the custom server URL now requires the complete URL to the server
<a id="requirements"></a>
## 3. Requirements
## 2. Requirements
The SDK runs on devices with iOS 6.0 or higher.
<a name="setup"></a>
## 4. Setup
## 3. Setup
We recommend integration of our binary into your Xcode project to setup Application Insights for your iOS app. For other ways to setup the SDK, see [Advanced Setup](#advancedsetup).
You can use the [Application Insights for Mac](http://go.microsoft.com/fwlink/?linkid=533209&clcid=0x409) tool to integrate the SDK, which provides you with a step-by-step wizard for this process. If you want to integrate the SDK manually, you can do that by following this steps:
### 4.1 Get the Instrumation Key of an Application Insights resource
### 3.1 Obtain an Instrumentation Key
To view your telemetry, you'll need an [Application Insights](https://azure.microsoft.com/documentation/articles/app-insights-overview/) resource in the [Microsoft Azure Portal](https://portal.azure.com). You can either:
@ -63,88 +65,88 @@ To view your telemetry, you'll need an [Application Insights](https://azure.micr
Open your resource and open the Essentials drop-down. Shortly, you'll need to copy the Instrumentation Key.
<a id="downloadsdk"></a>
### 4.2 Download the SDK
### 3.2 Download the SDK
1. Download the latest [Application Insights for iOS](https://github.com/Microsoft/ApplicationInsights-iOS/releases) framework which is provided as a zip-File.
2. Unzip the file and you will see a folder called `ApplicationInsights` .
### 4.3 Copy the SDK into your projects directory in Finder
### 3.3 Copy the SDK into your projects directory in Finder
From our experience, 3rd-party libraries usually reside inside a subdirectory (let's call our subdirectory `Vendor`), so if you don't have your project organized with a subdirectory for libraries, now would be a great start for it. To continue our example, create a folder called "Vendor" inside your project directory and move the unzipped `ApplicationInsights`-folder into it.
<a id="setupxcode"></a>
### 4.4 Set up the SDK in Xcode
### 3.4 Set up the SDK in Xcode
1. We recommend to use Xcode's group-feature to create a group for 3rd-party-libraries similar to the structure of our files on disk. For example, similar to the file structure in 4.3 above, our projects have a group called `Vendor`.
1. We recommend to use Xcode's group-feature to create a group for 3rd-party-libraries sixmilar to the structure of our files on disk. For example, similar to the file structure in 4.3 above, our projects have a group called `Vendor`.
2. Make sure the `Project Navigator` is visible (⌘+1)
3. Drag & drop `ApplicationInsights.framework` from your window in the `Finder` into your project in Xcode and move it to the desired location in the `Project Navigator` (e.g. into the group called `Vendor`)
4. A popup will appear. Select `Create groups for any added folders` and set the checkmark for your target. Then click `Finish`.
5. Open the `Info.plist` of your app target and add a new field of type *String*. Name it `MSAIInstrumentationKey` and set your Application Insights instrumentation key from 4.1 as its value.
<a id="modifycode"/>
### 4.5 Modify Code
### 3.5 Modify Code
**Objective-C**
1. Open your `AppDelegate.m` file.
2. Add the following line at the top of the file below your own `import` statements:
```objectivec
@import ApplicationInsights;
```
```objectivec
@import ApplicationInsights;
```
3. Search for the method `application:didFinishLaunchingWithOptions:`
4. Add the following lines to setup and start the Application Insights SDK:
```objectivec
[[MSAIApplicationInsights sharedInstance] setup];
// Do some additional configuration if needed here
//... more of your other setup code here ...
[[MSAIApplicationInsights sharedInstance] start];
```
```objectivec
[[MSAIApplicationInsights sharedInstance] setup];
// Do some additional configuration if needed here
//... more of your other setup code here ...
[[MSAIApplicationInsights sharedInstance] start];
```
You can also use the following shortcuts:
You can also use the following shortcuts:
```objectivec
[MSAIApplicationInsights setup];
[MSAIApplicationInsights start];
```
```objectivec
[MSAIApplicationInsights setup];
[MSAIApplicationInsights start];
```
**Swift**
1. Open your `AppDelegate.swift` file.
2. Add the following line at the top of the file below your own import statements:
```swift
import ApplicationInsights
```
```swift
import ApplicationInsights
```
3. Search for the method
```swift
application(application: UIApplication, didFinishLaunchingWithOptions launchOptions:[NSObject: AnyObject]?) -> Bool`
```
```swift
application(application: UIApplication, didFinishLaunchingWithOptions launchOptions:[NSObject: AnyObject]?) -> Bool`
```
4. Add the following lines to setup and start the Application Insights SDK:
```swift
MSAIApplicationInsights.sharedInstance().setup();
MSAIApplicationInsights.sharedInstance().start();
```
```swift
MSAIApplicationInsights.sharedInstance().setup();
MSAIApplicationInsights.sharedInstance().start();
```
You can also use the following shortcuts:
You can also use the following shortcuts:
```swift
MSAIApplicationInsights.setup()
MSAIApplicationInsights.start()
```
```swift
MSAIApplicationInsights.setup()
MSAIApplicationInsights.start()
```
**Congratulation, now you're all set to use Application Insights! See [Basic Usage](#basicusage) on how to use Application Insights.**
<a id="advancedsetup"></a>
## 5. Advanced Setup
## 4. Advanced Setup
### 5.1 Set Instrumentation Key in Code
### 4.1 Set Instrumentation Key in Code
It is also possible to set the instrumentation key of your app in code. This will override the one you might have set in your `Info.plist`. To set it in code, MSAIApplicationInsights provides an overloaded constructor:
@ -157,7 +159,7 @@ It is also possible to set the instrumentation key of your app in code. This wil
```
<a id="linkmanually"/>
### 5.2 Linking System Frameworks manually
### 4.2 Linking System Frameworks manually
If you are working with an older project which doesn't support clang modules yet or you for some reason turned off the `Enable Modules (C and Objective-C` and `Link Frameworks Automatically` options in Xcode, you have to manually link some system frameworks:
@ -171,12 +173,11 @@ If you are working with an older project which doesn't support clang modules yet
- `Security`
- `SystemConfiguration`
- `UIKit`
- `libc++`
- `libz`
Note that this also means that you can't use the `@import` syntax mentioned in the [Modify Code](#modify) section but have to stick to the old `#import <ApplicationInsights/ApplicationInsights.h>`.
### 5.3 Setup with CocoaPods
### 4.3 Setup with CocoaPods
[CocoaPods](https://cocoapods.org/) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like ApplicationInsights in your projects. To learn how to setup CocoaPods for your project, visit the [official CocoaPods website](https://cocoapods.org/).
@ -191,7 +192,7 @@ platform :ios, '8.0'
pod "ApplicationInsights", '1.0-beta.4'
```
### 5.4 iOS 8 Extensions
### 4.4 iOS 8 Extensions
The following points need to be considered to use the Application Insights SDK with iOS 8 Extensions:
@ -215,7 +216,7 @@ The following points need to be considered to use the Application Insights SDK w
}
```
### 5.4 WatchKit Extensions
### 4.5 WatchKit Extensions
WatchKit extensions don't use regular `UIViewControllers` but rather `WKInterfaceController` subclasses. These have a different lifecycle than you might be used to.
To make sure that the Application Insights SDK is only instantiated once in the WatchKit extension's lifecycle we recommend using a helper class similar to this:
@ -275,13 +276,13 @@ Then, in each of your WKInterfaceControllers where you want to use the Applicati
```
<a name="developermode"></a>
## 6. Developer Mode
## 5. Developer Mode
###6.1 Batching of data
###5.1 Batching of data
The **developer mode** is enabled automatically in case the debugger is attached or if the app is running in the simulator. This will decrease the number of telemetry items sent in a batch (5 items) as well as the interval items when telemetry will be sent (3 seconds).
###6.2 Logging
###5.2 Logging
We're all big fans of a clean debugging output without 3rd-party-SDKs messages piling up in the debugging view, right?!
That's why Application Insights keeps log messages to a minimum (like critical errors) unless the developer specifically enables debug logging before starting the SDK:
@ -297,15 +298,15 @@ That's why Application Insights keeps log messages to a minimum (like critical e
This setting is ignored if the app is running in an app store environment, so the user's console won't be littered with our log messages.
<a id="basicusage"></a>
## 7. Basic Usage
## 6. Basic Usage
**[NOTE]** The SDK is optimized to defer everything possible to a later time while making sure e.g. crashes on startup can also be caught and each module executes other code with a delay of some seconds. This ensures that `applicationDidFinishLaunching:` will process as fast as possible and the SDK will not block the startup sequence resulting in a possible kill by the watchdog process.
**[NOTE]** The SDK is optimized to defer everything possible to a later time while making sure each module executes other code with a delay of some seconds. This ensures that `applicationDidFinishLaunching:` will process as fast as possible and the SDK will not block the startup sequence resulting in a possible kill by the watchdog process.
After you have set up the SDK as [described above](#setup), the ```MSAITelemetryManager```-instance is the central interface to track events, traces, metrics, page views or handled exceptions.
For an overview of how to use the API and view the results in the Application Insights resource, see [API Overview](https://azure.microsoft.com/documentation/articles/app-insights-api-custom-events-metrics/). The examples are in Java, but the principles are the same.
### 7.1 Objective-C
### 6.1 Objective-C
```objectivec
// Send an event with custom properties and measurements data
@ -327,44 +328,44 @@ For an overview of how to use the API and view the results in the Application In
// Send custom metrics
[MSAITelemetryManager trackMetricWithName:@"Test metric" value:42.2];
// Track handled exceptions
NSArray *zeroItemArray = [NSArray new];
@try {
NSString *fooString = zeroItemArray[3];
} @catch(NSException *exception) {
[MSAITelemetryManager trackException:exception];
}
```
### 7.2 Swift
### 6.2 Swift
```swift
// Send an event with custom properties and measuremnts data
MSAITelemetryManager.trackEventWithName("Hello World event!",
properties:["Test property 1":"Some value",
"Test property 2":"Some other value"],
measurements:["Test measurement 1":4.8,
"Test measurement 2":15.16,
"Test measurement 3":23.42])
properties:["Test property 1":"Some value",
"Test property 2":"Some other value"],
measurements:["Test measurement 1":4.8,
"Test measurement 2":15.16,
"Test measurement 3":23.42])
// Send a message
MSAITelemetryManager.trackTraceWithMessage("Test message")
// Manually send pageviews
MSAITelemetryManager.trackPageView("MyViewController",
duration:300,
properties:["Test measurement 1":4.8])
duration:300,
properties:["Test measurement 1":4.8])
// Send a message
MSAITelemetryManager.trackMetricWithName("Test metric", value:42.2)
```
### View your data in the portal
In the [Azure portal](https://portal.azure.com), open the application resource that you created to get your instrumentation key. You'll see charts showing counts of page views and sessions. To see more:
* Click any chart to see more detail. You can [create your own metric pages, set alerts, and filter and segment your data](https://azure.microsoft.com/documentation/articles/app-insights-metrics-explorer/).
* Click [Search](https://azure.microsoft.com/documentation/articles/app-insights-diagnostic-search/) to see individual trackEvent, trackTrace, trackException and trackPageView messages.
<a name="advancedusage"></a>
## 8. Advanced Usage
## 7. Advanced Usage
The SDK also allows for some more advanced usages.
### 8.1 Common Properties
### 7.1 Common Properties
It is also possible to set so-called "common properties" that will then be automatically attached to all telemetry data items.
@ -380,15 +381,18 @@ It is also possible to set so-called "common properties" that will then be autom
MSAITelemetryManager.setCommonProperties(["custom info":"some value"])
```
#### Filter your views by properties
Use the properties to [segment and filter metric charts](https://azure.microsoft.com/documentation/articles/app-insights-metrics-explorer/#segment-your-data) and [filter searches](https://azure.microsoft.com/documentation/articles/app-insights-diagnostic-search/#filter-on-property-values).
<a name="autolifecycle"></a>
## 9. Automatic collection of lifecycle events
## 8. Automatic collection of lifecycle events
Automatic collection of lifecycle events is **enabled by default**. This means that Application Insights automatically tracks the appearance of a view controller and manages sessions for you.
### 9.1. Page views
### 8.1. Page views
The automatic tracking of viewcontroller appearance can be disabled between setup and start of the SDK.
```objectivec
[MSAIApplicationInsights setup]; //setup the SDK
@ -397,7 +401,7 @@ The automatic tracking of viewcontroller appearance can be disabled between setu
[MSAIApplicationInsights start]; //start using the SDK
```
### 9.2. Sessions
### 8.2. Sessions
By default, the Application Insights for iOS SDK starts a new session when the containing app is restarted (this means a 'cold start', i.e. when the app has not already been in memory prior to being launched) or when it has been in the background for more than 20 seconds.
@ -416,9 +420,9 @@ This then requires you to manage sessions manually:
[MSAIApplicationInsights renewSessionWithId:@"4815162342"];
```
### 9.3. Users
### 8.3. Users
Normally, a random anonymous ID is automatically generated for every user of your app by the SDK. Alternatively you can set your own user ID or other user attributes, which will then be attached to all telemetry events and crashes:
Normally, a random anonymous ID is automatically generated for every user of your app by the SDK. Alternatively you can set your own user ID or other user attributes, which will then be attached to all telemetry events:
```objectivec
[[MSAIApplicationInsights sharedInstance] setUserWithConfigurationBlock:^(MSAIUser *user) {
user.userId = @"your_user_id";
@ -426,24 +430,8 @@ Normally, a random anonymous ID is automatically generated for every user of you
}];
```
<a name="crashreporting"></a>
## 10. Crash Reporting
The Application Insights SDK enables crash reporting **per default**. Crashes will be immediately sent to the server the next time the app is launched.
To provide you with the best crash reporting, we are using [PLCrashReporter]("https://github.com/plausiblelabs/plcrashreporter") in [Version 1.2 / Commit 273a7e7cd4b77485a584ac82e77b7c857558e2f9]("https://github.com/plausiblelabs/plcrashreporter/commit/273a7e7cd4b77485a584ac82e77b7c857558e2f9").
This feature can be disabled as follows:
```objectivec
[MSAIApplicationInsights setup]; //setup the SDK
[[MSAIApplicationInsights sharedInstance] setCrashManagerDisabled:YES]; //disable crash reporting
[MSAIApplicationInsights start]; //start using the SDK
```
<a name="additionalconfig"></a>
## 11. Set Custom Server Endpoint
## 9. Set Custom Server Endpoint
You can also configure a different server endpoint for the SDK if needed using a full URL
@ -456,13 +444,13 @@ You can also configure a different server endpoint for the SDK if needed using a
```
<a id="documentation"></a>
## 12. Documentation
## 10. Documentation
Our documentation can be found on [CocoaDocs](http://cocoadocs.org/docsets/ApplicationInsights/1.0-beta.4/).
<a id="contributing"></a>
## 13. Contributing
## 11. Contributing
We're looking forward to your contributions via pull requests.
@ -474,6 +462,6 @@ We're looking forward to your contributions via pull requests.
* [Cocoapods](https://cocoapods.org/)
<a id="contact"></a>
## 14. Contact
## 12. Contact
If you have further questions or are running into trouble that cannot be resolved by any of the steps here, feel free to open a GitHub issue here or contact us at [AppInsights-iOS@microsoft.com](mailto:AppInsights-ios@microsoft.com)
If you have further questions or are running into trouble that cannot be resolved by any of the steps here, feel free to open a GitHub issue here or contact us at [support@hockeyapp.net](mailto:support@hockeyapp.net)

Просмотреть файл

@ -9,7 +9,7 @@
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.microsoft.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

Просмотреть файл

@ -34,22 +34,10 @@
/* Begin PBXBuildFile section */
1B3B73081A94BC8E008DCADA /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B3B73071A94BC8E008DCADA /* CoreTelephony.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
1B3C38761A82213000700081 /* MSAICrashData.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B3C386C1A82213000700081 /* MSAICrashData.h */; };
1B3C38771A82213000700081 /* MSAICrashData.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B3C386D1A82213000700081 /* MSAICrashData.m */; };
1B3C38781A82213000700081 /* MSAICrashDataBinary.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B3C386E1A82213000700081 /* MSAICrashDataBinary.h */; };
1B3C38791A82213000700081 /* MSAICrashDataBinary.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B3C386F1A82213000700081 /* MSAICrashDataBinary.m */; };
1B3C387A1A82213000700081 /* MSAICrashDataHeaders.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B3C38701A82213000700081 /* MSAICrashDataHeaders.h */; };
1B3C387B1A82213000700081 /* MSAICrashDataHeaders.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B3C38711A82213000700081 /* MSAICrashDataHeaders.m */; };
1B3C387C1A82213000700081 /* MSAICrashDataThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B3C38721A82213000700081 /* MSAICrashDataThread.h */; };
1B3C387D1A82213000700081 /* MSAICrashDataThread.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B3C38731A82213000700081 /* MSAICrashDataThread.m */; };
1B3C387E1A82213000700081 /* MSAICrashDataThreadFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B3C38741A82213000700081 /* MSAICrashDataThreadFrame.h */; };
1B3C387F1A82213000700081 /* MSAICrashDataThreadFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B3C38751A82213000700081 /* MSAICrashDataThreadFrame.m */; };
1B3FB89E1A93756100D06311 /* MSAIReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B3FB89C1A93756100D06311 /* MSAIReachability.h */; };
1B3FB89F1A93756100D06311 /* MSAIReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B3FB89D1A93756100D06311 /* MSAIReachability.m */; };
1B47E02E1A84D3DF000B4C3D /* MSAIEnvelopeManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B47E02C1A84D3DF000B4C3D /* MSAIEnvelopeManager.h */; };
1B47E02F1A84D3DF000B4C3D /* MSAIEnvelopeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B47E02D1A84D3DF000B4C3D /* MSAIEnvelopeManager.m */; };
1B53FEBF1A6425240082F2E9 /* CrashReporter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B53FEBE1A6425240082F2E9 /* CrashReporter.framework */; };
1B53FEC01A6425240082F2E9 /* CrashReporter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B53FEBE1A6425240082F2E9 /* CrashReporter.framework */; };
1B62F4D81A692A3200EB5AD0 /* MSAIContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B62F4D61A692A3200EB5AD0 /* MSAIContext.h */; };
1B62F4D91A692A3200EB5AD0 /* MSAIContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B62F4D71A692A3200EB5AD0 /* MSAIContext.m */; };
1B85606F1A7A6A9D00A54FB7 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B85606E1A7A6A9D00A54FB7 /* UIKit.framework */; };
@ -65,8 +53,6 @@
1BE53D771AB889420048ABBC /* MSAIContextHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BE53D751AB889420048ABBC /* MSAIContextHelper.m */; };
1E0FEE28173BDB260061331F /* MSAIKeychainUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E0FEE26173BDB260061331F /* MSAIKeychainUtils.h */; };
1E0FEE29173BDB260061331F /* MSAIKeychainUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E0FEE27173BDB260061331F /* MSAIKeychainUtils.m */; };
1E3A26111B2B2C8B00D59683 /* MSAICrashCXXExceptionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E3A260F1B2B2C8B00D59683 /* MSAICrashCXXExceptionHandler.h */; };
1E3A26121B2B2C8B00D59683 /* MSAICrashCXXExceptionHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1E3A26101B2B2C8B00D59683 /* MSAICrashCXXExceptionHandler.mm */; };
1E49A4BE161222B900463151 /* MSAIHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A5161222B900463151 /* MSAIHelper.h */; };
1E49A4C1161222B900463151 /* MSAIHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4A6161222B900463151 /* MSAIHelper.m */; };
1E49A4D8161222D400463151 /* ApplicationInsightsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4D4161222D400463151 /* ApplicationInsightsPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
@ -76,24 +62,15 @@
1E59559A15B6FDA500A03429 /* MSAIApplicationInsights.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB465148D7BF50015DEDC /* MSAIApplicationInsights.h */; settings = {ATTRIBUTES = (Public, ); }; };
1E59559B15B6FDA500A03429 /* ApplicationInsights.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E71509A15B5C76F004E88FF /* ApplicationInsights.h */; settings = {ATTRIBUTES = (Public, ); }; };
1E5A459516F0DFC200B55C04 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E400561D148D79B500EB22B9 /* Foundation.framework */; };
1E754E5C1621FBB70070AB92 /* MSAICrashManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E754E561621FBB70070AB92 /* MSAICrashManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
1E754E5D1621FBB70070AB92 /* MSAICrashManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E754E571621FBB70070AB92 /* MSAICrashManager.m */; };
1E754E5E1621FBB70070AB92 /* MSAICrashManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E754E581621FBB70070AB92 /* MSAICrashManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
1E754E601621FBB70070AB92 /* MSAICrashDataProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E754E5A1621FBB70070AB92 /* MSAICrashDataProvider.h */; };
1E754E611621FBB70070AB92 /* MSAICrashDataProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E754E5B1621FBB70070AB92 /* MSAICrashDataProvider.m */; };
1E84DB3417E099BA00AC83FD /* ApplicationInsightsFeatureConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E84DB3317E0977C00AC83FD /* ApplicationInsightsFeatureConfig.h */; settings = {ATTRIBUTES = (Public, ); }; };
1E90FD7318EDB86400CF0417 /* MSAICrashDetails.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E90FD7118EDB86400CF0417 /* MSAICrashDetails.h */; settings = {ATTRIBUTES = (Public, ); }; };
1E90FD7418EDB86400CF0417 /* MSAICrashDetails.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E90FD7218EDB86400CF0417 /* MSAICrashDetails.m */; };
1EA1170016F4D32C001C015C /* libApplicationInsights.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E5954F215B6F24A00A03429 /* libApplicationInsights.a */; };
1EB2E4C618FD4CEA008BB1CF /* MSAITelemetryManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EB2E4C418FD4CEA008BB1CF /* MSAITelemetryManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
1EB2E4C718FD4CEA008BB1CF /* MSAITelemetryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EB2E4C518FD4CEA008BB1CF /* MSAITelemetryManager.m */; };
1ECA8F4D192B5BD8006B9416 /* MSAICrashDetailsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ECA8F4B192B5BD8006B9416 /* MSAICrashDetailsPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
594931B3422F36B9D1DA449C /* MSAIPersistence.h in Headers */ = {isa = PBXBuildFile; fileRef = 594931F0F69C22CBB67A2AD9 /* MSAIPersistence.h */; };
59493E4E3899627127FA6760 /* MSAIPersistence.m in Sources */ = {isa = PBXBuildFile; fileRef = 59493E91C1D38C3FC5F77D19 /* MSAIPersistence.m */; };
8000A3D41B0E973F009F2B29 /* MSAICategoryContainerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8000A3D31B0E973F009F2B29 /* MSAICategoryContainerTests.m */; };
8004739C1ABB8FC200BBFE62 /* MSAIPersistencePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8004739B1ABB8FC200BBFE62 /* MSAIPersistencePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
803871BD1A94C0A600BF295F /* MSAIPageViewLogging_UIViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1BC8596D1A7ACC040018FB6B /* MSAIPageViewLogging_UIViewController.h */; };
803871C01A94C26500BF295F /* MSAICrashManagerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EFF03D717F20F8300A5F13C /* MSAICrashManagerPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
803871C21A94C26500BF295F /* MSAIContextPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B62F4DA1A692A6F00EB5AD0 /* MSAIContextPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
803871C31A94C26500BF295F /* MSAITelemetryManagerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EB2E4C818FD4E90008BB1CF /* MSAITelemetryManagerPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
803871C41A94C26500BF295F /* MSAIChannelPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B4D17E41A666EE30079D948 /* MSAIChannelPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
@ -128,10 +105,6 @@
807CFDB41A712974004EA1B6 /* MSAIEnvelope.m in Sources */ = {isa = PBXBuildFile; fileRef = 807CFD831A712974004EA1B6 /* MSAIEnvelope.m */; };
807CFDB51A712974004EA1B6 /* MSAIEventData.h in Headers */ = {isa = PBXBuildFile; fileRef = 807CFD841A712974004EA1B6 /* MSAIEventData.h */; };
807CFDB61A712974004EA1B6 /* MSAIEventData.m in Sources */ = {isa = PBXBuildFile; fileRef = 807CFD851A712974004EA1B6 /* MSAIEventData.m */; };
807CFDB71A712974004EA1B6 /* MSAIExceptionData.h in Headers */ = {isa = PBXBuildFile; fileRef = 807CFD861A712974004EA1B6 /* MSAIExceptionData.h */; };
807CFDB81A712974004EA1B6 /* MSAIExceptionData.m in Sources */ = {isa = PBXBuildFile; fileRef = 807CFD871A712974004EA1B6 /* MSAIExceptionData.m */; };
807CFDB91A712974004EA1B6 /* MSAIExceptionDetails.h in Headers */ = {isa = PBXBuildFile; fileRef = 807CFD881A712974004EA1B6 /* MSAIExceptionDetails.h */; };
807CFDBA1A712974004EA1B6 /* MSAIExceptionDetails.m in Sources */ = {isa = PBXBuildFile; fileRef = 807CFD891A712974004EA1B6 /* MSAIExceptionDetails.m */; };
807CFDBB1A712974004EA1B6 /* MSAIInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 807CFD8A1A712974004EA1B6 /* MSAIInternal.h */; };
807CFDBC1A712974004EA1B6 /* MSAIInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = 807CFD8B1A712974004EA1B6 /* MSAIInternal.m */; };
807CFDBD1A712974004EA1B6 /* MSAILocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 807CFD8C1A712974004EA1B6 /* MSAILocation.h */; };
@ -153,24 +126,17 @@
807CFDCD1A712974004EA1B6 /* MSAISession.h in Headers */ = {isa = PBXBuildFile; fileRef = 807CFD9C1A712974004EA1B6 /* MSAISession.h */; };
807CFDCE1A712974004EA1B6 /* MSAISession.m in Sources */ = {isa = PBXBuildFile; fileRef = 807CFD9D1A712974004EA1B6 /* MSAISession.m */; };
807CFDCF1A712974004EA1B6 /* MSAISeverityLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = 807CFD9E1A712974004EA1B6 /* MSAISeverityLevel.h */; };
807CFDD01A712974004EA1B6 /* MSAIStackFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 807CFD9F1A712974004EA1B6 /* MSAIStackFrame.h */; };
807CFDD11A712974004EA1B6 /* MSAIStackFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 807CFDA01A712974004EA1B6 /* MSAIStackFrame.m */; };
807CFDD21A712974004EA1B6 /* MSAIUser.h in Headers */ = {isa = PBXBuildFile; fileRef = 807CFDA11A712974004EA1B6 /* MSAIUser.h */; settings = {ATTRIBUTES = (Public, ); }; };
807CFDD31A712974004EA1B6 /* MSAIUser.m in Sources */ = {isa = PBXBuildFile; fileRef = 807CFDA21A712974004EA1B6 /* MSAIUser.m */; };
809E9E5A1AC455D9008A1AB5 /* MSAISessionState.h in Headers */ = {isa = PBXBuildFile; fileRef = 809E9E571AC455D9008A1AB5 /* MSAISessionState.h */; };
809E9E5B1AC455D9008A1AB5 /* MSAISessionStateData.h in Headers */ = {isa = PBXBuildFile; fileRef = 809E9E581AC455D9008A1AB5 /* MSAISessionStateData.h */; };
809E9E5C1AC455D9008A1AB5 /* MSAISessionStateData.m in Sources */ = {isa = PBXBuildFile; fileRef = 809E9E591AC455D9008A1AB5 /* MSAISessionStateData.m */; };
80B69EED1ADDC09900C47B0A /* MSAIGZIP.h in Headers */ = {isa = PBXBuildFile; fileRef = 80B69EEB1ADDC09900C47B0A /* MSAIGZIP.h */; };
80E1A3E71AE54B4200603B0A /* live_report_empty.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 80E1A3E41AE54B4200603B0A /* live_report_empty.plcrash */; };
80E1A3E81AE54B4200603B0A /* live_report_exception.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 80E1A3E51AE54B4200603B0A /* live_report_exception.plcrash */; };
80E1A3E91AE54B4200603B0A /* live_report_signal.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 80E1A3E61AE54B4200603B0A /* live_report_signal.plcrash */; };
80E1A4121AE54B5300603B0A /* MSAIAppClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3EA1AE54B5300603B0A /* MSAIAppClientTests.m */; };
80E1A4131AE54B5300603B0A /* MSAIApplicationInsightsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3EB1AE54B5300603B0A /* MSAIApplicationInsightsTests.m */; };
80E1A4141AE54B5300603B0A /* MSAIApplicationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3EC1AE54B5300603B0A /* MSAIApplicationTests.m */; };
80E1A4151AE54B5300603B0A /* MSAIBaseTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3ED1AE54B5300603B0A /* MSAIBaseTests.m */; };
80E1A4161AE54B5300603B0A /* MSAIChannelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3EE1AE54B5300603B0A /* MSAIChannelTests.m */; };
80E1A4171AE54B5300603B0A /* MSAICrashManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3EF1AE54B5300603B0A /* MSAICrashManagerTests.m */; };
80E1A4181AE54B5300603B0A /* MSAICrashDataProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3F01AE54B5300603B0A /* MSAICrashDataProviderTests.m */; };
80E1A4191AE54B5300603B0A /* MSAIDataPointTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3F11AE54B5300603B0A /* MSAIDataPointTests.m */; };
80E1A41A1AE54B5300603B0A /* MSAIDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3F21AE54B5300603B0A /* MSAIDataTests.m */; };
80E1A41B1AE54B5300603B0A /* MSAIDeviceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3F31AE54B5300603B0A /* MSAIDeviceTests.m */; };
@ -178,8 +144,6 @@
80E1A41D1AE54B5300603B0A /* MSAIEnvelopeManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3F51AE54B5300603B0A /* MSAIEnvelopeManagerTests.m */; };
80E1A41E1AE54B5300603B0A /* MSAIEnvelopeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3F61AE54B5300603B0A /* MSAIEnvelopeTests.m */; };
80E1A41F1AE54B5300603B0A /* MSAIEventDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3F71AE54B5300603B0A /* MSAIEventDataTests.m */; };
80E1A4201AE54B5300603B0A /* MSAIExceptionDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3F81AE54B5300603B0A /* MSAIExceptionDataTests.m */; };
80E1A4211AE54B5300603B0A /* MSAIExceptionDetailsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3F91AE54B5300603B0A /* MSAIExceptionDetailsTests.m */; };
80E1A4221AE54B5300603B0A /* MSAIHelperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3FA1AE54B5300603B0A /* MSAIHelperTests.m */; };
80E1A4231AE54B5300603B0A /* MSAIInternalTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3FB1AE54B5300603B0A /* MSAIInternalTests.m */; };
80E1A4241AE54B5300603B0A /* MSAIKeychainUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A3FC1AE54B5300603B0A /* MSAIKeychainUtilsTests.m */; };
@ -196,7 +160,6 @@
80E1A42F1AE54B5300603B0A /* MSAISenderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A4071AE54B5300603B0A /* MSAISenderTests.m */; };
80E1A4301AE54B5300603B0A /* MSAIContextHelperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A4081AE54B5300603B0A /* MSAIContextHelperTests.m */; };
80E1A4311AE54B5300603B0A /* MSAISessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A4091AE54B5300603B0A /* MSAISessionTests.m */; };
80E1A4321AE54B5300603B0A /* MSAIStackFrameTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A40A1AE54B5300603B0A /* MSAIStackFrameTests.m */; };
80E1A4331AE54B5300603B0A /* MSAITelemetryContextTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A40B1AE54B5300603B0A /* MSAITelemetryContextTests.m */; };
80E1A4341AE54B5300603B0A /* MSAITelemetryManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A40C1AE54B5300603B0A /* MSAITelemetryManagerTests.m */; };
80E1A4351AE54B5300603B0A /* MSAITestHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 80E1A40E1AE54B5300603B0A /* MSAITestHelper.m */; };
@ -231,17 +194,9 @@
/* Begin PBXFileReference section */
1B2439BF1AB8AB8100B07374 /* MSAIContextHelperPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSAIContextHelperPrivate.h; sourceTree = "<group>"; };
1B2B6E851C5AFF3600D89D13 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
1B2B6E891C5B039800D89D13 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = "<group>"; };
1B3B73071A94BC8E008DCADA /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };
1B3C386C1A82213000700081 /* MSAICrashData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAICrashData.h; sourceTree = "<group>"; };
1B3C386D1A82213000700081 /* MSAICrashData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAICrashData.m; sourceTree = "<group>"; };
1B3C386E1A82213000700081 /* MSAICrashDataBinary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAICrashDataBinary.h; sourceTree = "<group>"; };
1B3C386F1A82213000700081 /* MSAICrashDataBinary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAICrashDataBinary.m; sourceTree = "<group>"; };
1B3C38701A82213000700081 /* MSAICrashDataHeaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAICrashDataHeaders.h; sourceTree = "<group>"; };
1B3C38711A82213000700081 /* MSAICrashDataHeaders.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAICrashDataHeaders.m; sourceTree = "<group>"; };
1B3C38721A82213000700081 /* MSAICrashDataThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAICrashDataThread.h; sourceTree = "<group>"; };
1B3C38731A82213000700081 /* MSAICrashDataThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAICrashDataThread.m; sourceTree = "<group>"; };
1B3C38741A82213000700081 /* MSAICrashDataThreadFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAICrashDataThreadFrame.h; sourceTree = "<group>"; };
1B3C38751A82213000700081 /* MSAICrashDataThreadFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAICrashDataThreadFrame.m; sourceTree = "<group>"; };
1B3FB89C1A93756100D06311 /* MSAIReachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIReachability.h; sourceTree = "<group>"; };
1B3FB89D1A93756100D06311 /* MSAIReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIReachability.m; sourceTree = "<group>"; };
1B3FB8A51A9383C300D06311 /* MSAIReachabilityPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSAIReachabilityPrivate.h; sourceTree = "<group>"; };
@ -249,7 +204,6 @@
1B47E02D1A84D3DF000B4C3D /* MSAIEnvelopeManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIEnvelopeManager.m; sourceTree = "<group>"; };
1B47E0301A84D413000B4C3D /* MSAIEnvelopeManagerPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSAIEnvelopeManagerPrivate.h; sourceTree = "<group>"; };
1B4D17E41A666EE30079D948 /* MSAIChannelPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSAIChannelPrivate.h; sourceTree = "<group>"; };
1B53FEBE1A6425240082F2E9 /* CrashReporter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CrashReporter.framework; path = ../Vendor/CrashReporter.framework; sourceTree = "<group>"; };
1B62F4D61A692A3200EB5AD0 /* MSAIContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIContext.h; sourceTree = "<group>"; };
1B62F4D71A692A3200EB5AD0 /* MSAIContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIContext.m; sourceTree = "<group>"; };
1B62F4DA1A692A6F00EB5AD0 /* MSAIContextPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSAIContextPrivate.h; sourceTree = "<group>"; };
@ -269,8 +223,6 @@
1BE53D751AB889420048ABBC /* MSAIContextHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIContextHelper.m; sourceTree = "<group>"; };
1E0FEE26173BDB260061331F /* MSAIKeychainUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIKeychainUtils.h; sourceTree = "<group>"; };
1E0FEE27173BDB260061331F /* MSAIKeychainUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIKeychainUtils.m; sourceTree = "<group>"; };
1E3A260F1B2B2C8B00D59683 /* MSAICrashCXXExceptionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAICrashCXXExceptionHandler.h; sourceTree = "<group>"; };
1E3A26101B2B2C8B00D59683 /* MSAICrashCXXExceptionHandler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MSAICrashCXXExceptionHandler.mm; sourceTree = "<group>"; };
1E3A26131B2B2CFE00D59683 /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libc++.dylib"; path = "usr/lib/libc++.dylib"; sourceTree = SDKROOT; };
1E3A2B4C19645DC800D5BD66 /* ApplicationInsights-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ApplicationInsights-Prefix.pch"; sourceTree = "<group>"; };
1E49A4A5161222B900463151 /* MSAIHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIHelper.h; sourceTree = "<group>"; };
@ -282,20 +234,10 @@
1E66CA9115D4100500F35BED /* buildnumber.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = buildnumber.xcconfig; sourceTree = "<group>"; };
1E71509A15B5C76F004E88FF /* ApplicationInsights.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApplicationInsights.h; sourceTree = "<group>"; };
1E754DC61621BC170070AB92 /* ApplicationInsights.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = ApplicationInsights.xcconfig; sourceTree = "<group>"; };
1E754E561621FBB70070AB92 /* MSAICrashManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAICrashManager.h; sourceTree = "<group>"; };
1E754E571621FBB70070AB92 /* MSAICrashManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAICrashManager.m; sourceTree = "<group>"; };
1E754E581621FBB70070AB92 /* MSAICrashManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAICrashManagerDelegate.h; sourceTree = "<group>"; };
1E754E5A1621FBB70070AB92 /* MSAICrashDataProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAICrashDataProvider.h; sourceTree = "<group>"; };
1E754E5B1621FBB70070AB92 /* MSAICrashDataProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAICrashDataProvider.m; sourceTree = "<group>"; };
1E84DB3317E0977C00AC83FD /* ApplicationInsightsFeatureConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApplicationInsightsFeatureConfig.h; sourceTree = "<group>"; };
1E90FD7118EDB86400CF0417 /* MSAICrashDetails.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAICrashDetails.h; sourceTree = "<group>"; };
1E90FD7218EDB86400CF0417 /* MSAICrashDetails.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAICrashDetails.m; sourceTree = "<group>"; };
1E91D84619B924E600E9616D /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
1EB2E4C418FD4CEA008BB1CF /* MSAITelemetryManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAITelemetryManager.h; sourceTree = "<group>"; };
1EB2E4C518FD4CEA008BB1CF /* MSAITelemetryManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAITelemetryManager.m; sourceTree = "<group>"; };
1EB2E4C818FD4E90008BB1CF /* MSAITelemetryManagerPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSAITelemetryManagerPrivate.h; sourceTree = "<group>"; };
1ECA8F4B192B5BD8006B9416 /* MSAICrashDetailsPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAICrashDetailsPrivate.h; sourceTree = "<group>"; };
1EFF03D717F20F8300A5F13C /* MSAICrashManagerPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSAICrashManagerPrivate.h; sourceTree = "<group>"; };
594931F0F69C22CBB67A2AD9 /* MSAIPersistence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIPersistence.h; sourceTree = "<group>"; };
59493E91C1D38C3FC5F77D19 /* MSAIPersistence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIPersistence.m; sourceTree = "<group>"; };
8000A3D21B0E8D83009F2B29 /* ApplicationInsights-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ApplicationInsights-Info.plist"; sourceTree = "<group>"; };
@ -328,10 +270,6 @@
807CFD831A712974004EA1B6 /* MSAIEnvelope.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIEnvelope.m; sourceTree = "<group>"; };
807CFD841A712974004EA1B6 /* MSAIEventData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIEventData.h; sourceTree = "<group>"; };
807CFD851A712974004EA1B6 /* MSAIEventData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIEventData.m; sourceTree = "<group>"; };
807CFD861A712974004EA1B6 /* MSAIExceptionData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIExceptionData.h; sourceTree = "<group>"; };
807CFD871A712974004EA1B6 /* MSAIExceptionData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIExceptionData.m; sourceTree = "<group>"; };
807CFD881A712974004EA1B6 /* MSAIExceptionDetails.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIExceptionDetails.h; sourceTree = "<group>"; };
807CFD891A712974004EA1B6 /* MSAIExceptionDetails.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIExceptionDetails.m; sourceTree = "<group>"; };
807CFD8A1A712974004EA1B6 /* MSAIInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIInternal.h; sourceTree = "<group>"; };
807CFD8B1A712974004EA1B6 /* MSAIInternal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIInternal.m; sourceTree = "<group>"; };
807CFD8C1A712974004EA1B6 /* MSAILocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAILocation.h; sourceTree = "<group>"; };
@ -353,8 +291,6 @@
807CFD9C1A712974004EA1B6 /* MSAISession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAISession.h; sourceTree = "<group>"; };
807CFD9D1A712974004EA1B6 /* MSAISession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAISession.m; sourceTree = "<group>"; };
807CFD9E1A712974004EA1B6 /* MSAISeverityLevel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAISeverityLevel.h; sourceTree = "<group>"; };
807CFD9F1A712974004EA1B6 /* MSAIStackFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIStackFrame.h; sourceTree = "<group>"; };
807CFDA01A712974004EA1B6 /* MSAIStackFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIStackFrame.m; sourceTree = "<group>"; };
807CFDA11A712974004EA1B6 /* MSAIUser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIUser.h; sourceTree = "<group>"; };
807CFDA21A712974004EA1B6 /* MSAIUser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAIUser.m; sourceTree = "<group>"; };
809E9E571AC455D9008A1AB5 /* MSAISessionState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAISessionState.h; sourceTree = "<group>"; };
@ -362,16 +298,11 @@
809E9E591AC455D9008A1AB5 /* MSAISessionStateData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSAISessionStateData.m; sourceTree = "<group>"; };
80B69EEB1ADDC09900C47B0A /* MSAIGZIP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSAIGZIP.h; sourceTree = "<group>"; };
80B69EEF1ADDC49100C47B0A /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
80E1A3E41AE54B4200603B0A /* live_report_empty.plcrash */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = live_report_empty.plcrash; path = ApplicationInsightsTests/Fixtures/live_report_empty.plcrash; sourceTree = SOURCE_ROOT; };
80E1A3E51AE54B4200603B0A /* live_report_exception.plcrash */ = {isa = PBXFileReference; lastKnownFileType = file; name = live_report_exception.plcrash; path = ApplicationInsightsTests/Fixtures/live_report_exception.plcrash; sourceTree = SOURCE_ROOT; };
80E1A3E61AE54B4200603B0A /* live_report_signal.plcrash */ = {isa = PBXFileReference; lastKnownFileType = file; name = live_report_signal.plcrash; path = ApplicationInsightsTests/Fixtures/live_report_signal.plcrash; sourceTree = SOURCE_ROOT; };
80E1A3EA1AE54B5300603B0A /* MSAIAppClientTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIAppClientTests.m; path = ApplicationInsightsTests/MSAIAppClientTests.m; sourceTree = SOURCE_ROOT; };
80E1A3EB1AE54B5300603B0A /* MSAIApplicationInsightsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIApplicationInsightsTests.m; path = ApplicationInsightsTests/MSAIApplicationInsightsTests.m; sourceTree = SOURCE_ROOT; };
80E1A3EC1AE54B5300603B0A /* MSAIApplicationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIApplicationTests.m; path = ApplicationInsightsTests/MSAIApplicationTests.m; sourceTree = SOURCE_ROOT; };
80E1A3ED1AE54B5300603B0A /* MSAIBaseTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIBaseTests.m; path = ApplicationInsightsTests/MSAIBaseTests.m; sourceTree = SOURCE_ROOT; };
80E1A3EE1AE54B5300603B0A /* MSAIChannelTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIChannelTests.m; path = ApplicationInsightsTests/MSAIChannelTests.m; sourceTree = SOURCE_ROOT; };
80E1A3EF1AE54B5300603B0A /* MSAICrashManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAICrashManagerTests.m; path = ApplicationInsightsTests/MSAICrashManagerTests.m; sourceTree = SOURCE_ROOT; };
80E1A3F01AE54B5300603B0A /* MSAICrashDataProviderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAICrashDataProviderTests.m; path = ApplicationInsightsTests/MSAICrashDataProviderTests.m; sourceTree = SOURCE_ROOT; };
80E1A3F11AE54B5300603B0A /* MSAIDataPointTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIDataPointTests.m; path = ApplicationInsightsTests/MSAIDataPointTests.m; sourceTree = SOURCE_ROOT; };
80E1A3F21AE54B5300603B0A /* MSAIDataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIDataTests.m; path = ApplicationInsightsTests/MSAIDataTests.m; sourceTree = SOURCE_ROOT; };
80E1A3F31AE54B5300603B0A /* MSAIDeviceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIDeviceTests.m; path = ApplicationInsightsTests/MSAIDeviceTests.m; sourceTree = SOURCE_ROOT; };
@ -379,8 +310,6 @@
80E1A3F51AE54B5300603B0A /* MSAIEnvelopeManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIEnvelopeManagerTests.m; path = ApplicationInsightsTests/MSAIEnvelopeManagerTests.m; sourceTree = SOURCE_ROOT; };
80E1A3F61AE54B5300603B0A /* MSAIEnvelopeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIEnvelopeTests.m; path = ApplicationInsightsTests/MSAIEnvelopeTests.m; sourceTree = SOURCE_ROOT; };
80E1A3F71AE54B5300603B0A /* MSAIEventDataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIEventDataTests.m; path = ApplicationInsightsTests/MSAIEventDataTests.m; sourceTree = SOURCE_ROOT; };
80E1A3F81AE54B5300603B0A /* MSAIExceptionDataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIExceptionDataTests.m; path = ApplicationInsightsTests/MSAIExceptionDataTests.m; sourceTree = SOURCE_ROOT; };
80E1A3F91AE54B5300603B0A /* MSAIExceptionDetailsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIExceptionDetailsTests.m; path = ApplicationInsightsTests/MSAIExceptionDetailsTests.m; sourceTree = SOURCE_ROOT; };
80E1A3FA1AE54B5300603B0A /* MSAIHelperTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIHelperTests.m; path = ApplicationInsightsTests/MSAIHelperTests.m; sourceTree = SOURCE_ROOT; };
80E1A3FB1AE54B5300603B0A /* MSAIInternalTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIInternalTests.m; path = ApplicationInsightsTests/MSAIInternalTests.m; sourceTree = SOURCE_ROOT; };
80E1A3FC1AE54B5300603B0A /* MSAIKeychainUtilsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIKeychainUtilsTests.m; path = ApplicationInsightsTests/MSAIKeychainUtilsTests.m; sourceTree = SOURCE_ROOT; };
@ -397,7 +326,6 @@
80E1A4071AE54B5300603B0A /* MSAISenderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAISenderTests.m; path = ApplicationInsightsTests/MSAISenderTests.m; sourceTree = SOURCE_ROOT; };
80E1A4081AE54B5300603B0A /* MSAIContextHelperTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIContextHelperTests.m; path = ApplicationInsightsTests/MSAIContextHelperTests.m; sourceTree = SOURCE_ROOT; };
80E1A4091AE54B5300603B0A /* MSAISessionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAISessionTests.m; path = ApplicationInsightsTests/MSAISessionTests.m; sourceTree = SOURCE_ROOT; };
80E1A40A1AE54B5300603B0A /* MSAIStackFrameTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAIStackFrameTests.m; path = ApplicationInsightsTests/MSAIStackFrameTests.m; sourceTree = SOURCE_ROOT; };
80E1A40B1AE54B5300603B0A /* MSAITelemetryContextTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAITelemetryContextTests.m; path = ApplicationInsightsTests/MSAITelemetryContextTests.m; sourceTree = SOURCE_ROOT; };
80E1A40C1AE54B5300603B0A /* MSAITelemetryManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSAITelemetryManagerTests.m; path = ApplicationInsightsTests/MSAITelemetryManagerTests.m; sourceTree = SOURCE_ROOT; };
80E1A40D1AE54B5300603B0A /* MSAITestHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSAITestHelper.h; path = ApplicationInsightsTests/MSAITestHelper.h; sourceTree = SOURCE_ROOT; };
@ -436,7 +364,6 @@
files = (
1B85606F1A7A6A9D00A54FB7 /* UIKit.framework in Frameworks */,
1E5954DC15B6F24A00A03429 /* Foundation.framework in Frameworks */,
1B53FEBF1A6425240082F2E9 /* CrashReporter.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -447,7 +374,6 @@
80E1A45A1AE54D6200603B0A /* libOCMock.a in Frameworks */,
80ECBD1F1ADE9E39005CACF4 /* libz.dylib in Frameworks */,
1B3B73081A94BC8E008DCADA /* CoreTelephony.framework in Frameworks */,
1B53FEC01A6425240082F2E9 /* CrashReporter.framework in Frameworks */,
1EA1170016F4D32C001C015C /* libApplicationInsights.a in Frameworks */,
80E1A44C1AE54C7800603B0A /* OCHamcrestIOS.framework in Frameworks */,
1E5A459516F0DFC200B55C04 /* Foundation.framework in Frameworks */,
@ -491,16 +417,6 @@
807CFD731A712974004EA1B6 /* MSAIApplication.m */,
807CFD741A712974004EA1B6 /* MSAIBase.h */,
807CFD751A712974004EA1B6 /* MSAIBase.m */,
1B3C386C1A82213000700081 /* MSAICrashData.h */,
1B3C386D1A82213000700081 /* MSAICrashData.m */,
1B3C386E1A82213000700081 /* MSAICrashDataBinary.h */,
1B3C386F1A82213000700081 /* MSAICrashDataBinary.m */,
1B3C38701A82213000700081 /* MSAICrashDataHeaders.h */,
1B3C38711A82213000700081 /* MSAICrashDataHeaders.m */,
1B3C38721A82213000700081 /* MSAICrashDataThread.h */,
1B3C38731A82213000700081 /* MSAICrashDataThread.m */,
1B3C38741A82213000700081 /* MSAICrashDataThreadFrame.h */,
1B3C38751A82213000700081 /* MSAICrashDataThreadFrame.m */,
807CFD761A712974004EA1B6 /* MSAIData.h */,
807CFD771A712974004EA1B6 /* MSAIData.m */,
807CFD781A712974004EA1B6 /* MSAIDataPoint.h */,
@ -517,10 +433,6 @@
807CFD831A712974004EA1B6 /* MSAIEnvelope.m */,
807CFD841A712974004EA1B6 /* MSAIEventData.h */,
807CFD851A712974004EA1B6 /* MSAIEventData.m */,
807CFD861A712974004EA1B6 /* MSAIExceptionData.h */,
807CFD871A712974004EA1B6 /* MSAIExceptionData.m */,
807CFD881A712974004EA1B6 /* MSAIExceptionDetails.h */,
807CFD891A712974004EA1B6 /* MSAIExceptionDetails.m */,
807CFD8A1A712974004EA1B6 /* MSAIInternal.h */,
807CFD8B1A712974004EA1B6 /* MSAIInternal.m */,
807CFD8C1A712974004EA1B6 /* MSAILocation.h */,
@ -547,8 +459,6 @@
809E9E581AC455D9008A1AB5 /* MSAISessionStateData.h */,
809E9E591AC455D9008A1AB5 /* MSAISessionStateData.m */,
807CFD9E1A712974004EA1B6 /* MSAISeverityLevel.h */,
807CFD9F1A712974004EA1B6 /* MSAIStackFrame.h */,
807CFDA01A712974004EA1B6 /* MSAIStackFrame.m */,
807CFD6C1A712969004EA1B6 /* MSAITelemetryData.h */,
807CFD6D1A712969004EA1B6 /* MSAITelemetryData.m */,
807CFDA11A712974004EA1B6 /* MSAIUser.h */,
@ -560,14 +470,11 @@
1E5A459616F0DFC200B55C04 /* ApplicationInsights Tests */ = {
isa = PBXGroup;
children = (
1EA1170216F53B49001C015C /* Fixtures */,
80E1A3EA1AE54B5300603B0A /* MSAIAppClientTests.m */,
80E1A3EB1AE54B5300603B0A /* MSAIApplicationInsightsTests.m */,
80E1A3EC1AE54B5300603B0A /* MSAIApplicationTests.m */,
80E1A3ED1AE54B5300603B0A /* MSAIBaseTests.m */,
80E1A3EE1AE54B5300603B0A /* MSAIChannelTests.m */,
80E1A3EF1AE54B5300603B0A /* MSAICrashManagerTests.m */,
80E1A3F01AE54B5300603B0A /* MSAICrashDataProviderTests.m */,
80E1A3F11AE54B5300603B0A /* MSAIDataPointTests.m */,
80E1A3F21AE54B5300603B0A /* MSAIDataTests.m */,
80E1A3F31AE54B5300603B0A /* MSAIDeviceTests.m */,
@ -575,8 +482,6 @@
80E1A3F51AE54B5300603B0A /* MSAIEnvelopeManagerTests.m */,
80E1A3F61AE54B5300603B0A /* MSAIEnvelopeTests.m */,
80E1A3F71AE54B5300603B0A /* MSAIEventDataTests.m */,
80E1A3F81AE54B5300603B0A /* MSAIExceptionDataTests.m */,
80E1A3F91AE54B5300603B0A /* MSAIExceptionDetailsTests.m */,
80E1A3FA1AE54B5300603B0A /* MSAIHelperTests.m */,
80E1A3FB1AE54B5300603B0A /* MSAIInternalTests.m */,
80E1A3FC1AE54B5300603B0A /* MSAIKeychainUtilsTests.m */,
@ -593,7 +498,6 @@
80E1A4071AE54B5300603B0A /* MSAISenderTests.m */,
80E1A4081AE54B5300603B0A /* MSAIContextHelperTests.m */,
80E1A4091AE54B5300603B0A /* MSAISessionTests.m */,
80E1A40A1AE54B5300603B0A /* MSAIStackFrameTests.m */,
80E1A40B1AE54B5300603B0A /* MSAITelemetryContextTests.m */,
80E1A40C1AE54B5300603B0A /* MSAITelemetryManagerTests.m */,
80E1A40E1AE54B5300603B0A /* MSAITestHelper.m */,
@ -624,9 +528,10 @@
1E66CA8F15D40FF600F35BED /* Support */ = {
isa = PBXGroup;
children = (
1B2B6E891C5B039800D89D13 /* release.xcconfig */,
1B2B6E851C5AFF3600D89D13 /* module.modulemap */,
1E754DC61621BC170070AB92 /* ApplicationInsights.xcconfig */,
1E66CA9115D4100500F35BED /* buildnumber.xcconfig */,
1E91D84619B924E600E9616D /* module.modulemap */,
);
name = Support;
sourceTree = "<group>";
@ -657,34 +562,6 @@
name = Helper;
sourceTree = "<group>";
};
1E754E551621FBAF0070AB92 /* CrashReports */ = {
isa = PBXGroup;
children = (
1E90FD7118EDB86400CF0417 /* MSAICrashDetails.h */,
1E90FD7218EDB86400CF0417 /* MSAICrashDetails.m */,
1ECA8F4B192B5BD8006B9416 /* MSAICrashDetailsPrivate.h */,
1E754E561621FBB70070AB92 /* MSAICrashManager.h */,
1E754E571621FBB70070AB92 /* MSAICrashManager.m */,
1E754E581621FBB70070AB92 /* MSAICrashManagerDelegate.h */,
1EFF03D717F20F8300A5F13C /* MSAICrashManagerPrivate.h */,
1E3A260F1B2B2C8B00D59683 /* MSAICrashCXXExceptionHandler.h */,
1E3A26101B2B2C8B00D59683 /* MSAICrashCXXExceptionHandler.mm */,
1E754E5A1621FBB70070AB92 /* MSAICrashDataProvider.h */,
1E754E5B1621FBB70070AB92 /* MSAICrashDataProvider.m */,
);
name = CrashReports;
sourceTree = "<group>";
};
1EA1170216F53B49001C015C /* Fixtures */ = {
isa = PBXGroup;
children = (
80E1A3E41AE54B4200603B0A /* live_report_empty.plcrash */,
80E1A3E51AE54B4200603B0A /* live_report_exception.plcrash */,
80E1A3E61AE54B4200603B0A /* live_report_signal.plcrash */,
);
path = Fixtures;
sourceTree = "<group>";
};
1EB2E4C318FD4CBC008BB1CF /* Telemetry */ = {
isa = PBXGroup;
children = (
@ -743,7 +620,6 @@
80B69EEF1ADDC49100C47B0A /* libz.dylib */,
1B3B73071A94BC8E008DCADA /* CoreTelephony.framework */,
1B85606E1A7A6A9D00A54FB7 /* UIKit.framework */,
1B53FEBE1A6425240082F2E9 /* CrashReporter.framework */,
E400561D148D79B500EB22B9 /* Foundation.framework */,
);
name = Frameworks;
@ -762,7 +638,6 @@
isa = PBXGroup;
children = (
1BBBCEC31A65927900253031 /* Contracts */,
1E754E551621FBAF0070AB92 /* CrashReports */,
1E754E441621F95E0070AB92 /* Helper */,
1EB2E4C318FD4CBC008BB1CF /* Telemetry */,
1BA913001A9357A500251386 /* Persistence */,
@ -829,33 +704,24 @@
807CFDA31A712974004EA1B6 /* MSAIApplication.h in Headers */,
807CFDA71A712974004EA1B6 /* MSAIData.h in Headers */,
1BBBCF341A6594AE00253031 /* MSAIChannel.h in Headers */,
1E754E5C1621FBB70070AB92 /* MSAICrashManager.h in Headers */,
1B62F4D81A692A3200EB5AD0 /* MSAIContext.h in Headers */,
1E49A4D8161222D400463151 /* ApplicationInsightsPrivate.h in Headers */,
803871C01A94C26500BF295F /* MSAICrashManagerPrivate.h in Headers */,
803871C21A94C26500BF295F /* MSAIContextPrivate.h in Headers */,
1E3A26111B2B2C8B00D59683 /* MSAICrashCXXExceptionHandler.h in Headers */,
803871C31A94C26500BF295F /* MSAITelemetryManagerPrivate.h in Headers */,
1ECA8F4D192B5BD8006B9416 /* MSAICrashDetailsPrivate.h in Headers */,
80F334B21A9C93290098026F /* MSAIApplicationInsightsPrivate.h in Headers */,
8004739C1ABB8FC200BBFE62 /* MSAIPersistencePrivate.h in Headers */,
803871C41A94C26500BF295F /* MSAIChannelPrivate.h in Headers */,
803871C51A94C26500BF295F /* MSAITelemetryContextPrivate.h in Headers */,
1E90FD7318EDB86400CF0417 /* MSAICrashDetails.h in Headers */,
803871BD1A94C0A600BF295F /* MSAIPageViewLogging_UIViewController.h in Headers */,
1BC8596B1A7ACA820018FB6B /* MSAICategoryContainer.h in Headers */,
803871C61A94C26500BF295F /* MSAIEnvelopeManagerPrivate.h in Headers */,
803871C71A94C26500BF295F /* MSAISenderPrivate.h in Headers */,
1E754E5E1621FBB70070AB92 /* MSAICrashManagerDelegate.h in Headers */,
1BBBCF361A6594AE00253031 /* MSAITelemetryContext.h in Headers */,
80B69EED1ADDC09900C47B0A /* MSAIGZIP.h in Headers */,
807CFDC31A712974004EA1B6 /* MSAIOperation.h in Headers */,
809E9E5B1AC455D9008A1AB5 /* MSAISessionStateData.h in Headers */,
1B3C387A1A82213000700081 /* MSAICrashDataHeaders.h in Headers */,
807CFDB31A712974004EA1B6 /* MSAIEnvelope.h in Headers */,
807CFDAD1A712974004EA1B6 /* MSAIDependencySourceType.h in Headers */,
1B3C387C1A82213000700081 /* MSAICrashDataThread.h in Headers */,
807CFDB71A712974004EA1B6 /* MSAIExceptionData.h in Headers */,
807CFDBF1A712974004EA1B6 /* MSAIMessageData.h in Headers */,
807CFDC71A712974004EA1B6 /* MSAIPageViewPerfData.h in Headers */,
1B3FB89E1A93756100D06311 /* MSAIReachability.h in Headers */,
@ -864,11 +730,9 @@
807CFDC51A712974004EA1B6 /* MSAIPageViewData.h in Headers */,
807CFD701A712969004EA1B6 /* MSAITelemetryData.h in Headers */,
807CFD681A71294E004EA1B6 /* MSAIOrderedDictionary.h in Headers */,
807CFDB91A712974004EA1B6 /* MSAIExceptionDetails.h in Headers */,
1BE29B481A6FB8C20014A10F /* MSAISender.h in Headers */,
807CFDB01A712974004EA1B6 /* MSAIDomain.h in Headers */,
807CFDA91A712974004EA1B6 /* MSAIDataPoint.h in Headers */,
807CFDD01A712974004EA1B6 /* MSAIStackFrame.h in Headers */,
E4933E8017B66CDA00B11ACC /* MSAIHTTPOperation.h in Headers */,
807CFDAE1A712974004EA1B6 /* MSAIDevice.h in Headers */,
807CFDB51A712974004EA1B6 /* MSAIEventData.h in Headers */,
@ -877,20 +741,16 @@
807CFDCB1A712974004EA1B6 /* MSAIRequestData.h in Headers */,
807CFDA51A712974004EA1B6 /* MSAIBase.h in Headers */,
807CFD6E1A712969004EA1B6 /* MSAIObject.h in Headers */,
1B3C38781A82213000700081 /* MSAICrashDataBinary.h in Headers */,
807CFDD21A712974004EA1B6 /* MSAIUser.h in Headers */,
807CFDB21A712974004EA1B6 /* MSAIEnums.h in Headers */,
807CFDCF1A712974004EA1B6 /* MSAISeverityLevel.h in Headers */,
807CFDBB1A712974004EA1B6 /* MSAIInternal.h in Headers */,
807CFDAC1A712974004EA1B6 /* MSAIDependencyKind.h in Headers */,
809E9E5A1AC455D9008A1AB5 /* MSAISessionState.h in Headers */,
1E754E601621FBB70070AB92 /* MSAICrashDataProvider.h in Headers */,
807CFDC11A712974004EA1B6 /* MSAIMetricData.h in Headers */,
1B3C38761A82213000700081 /* MSAICrashData.h in Headers */,
1BE53D761AB889420048ABBC /* MSAIContextHelper.h in Headers */,
807CFDBD1A712974004EA1B6 /* MSAILocation.h in Headers */,
1E0FEE28173BDB260061331F /* MSAIKeychainUtils.h in Headers */,
1B3C387E1A82213000700081 /* MSAICrashDataThreadFrame.h in Headers */,
594931B3422F36B9D1DA449C /* MSAIPersistence.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -905,7 +765,6 @@
1E5954CC15B6F24A00A03429 /* Sources */,
1E5954DB15B6F24A00A03429 /* Frameworks */,
1E59558B15B6FD8800A03429 /* Headers */,
1EE9071A16F6871F003DDE1D /* ShellScript */,
);
buildRules = (
);
@ -941,7 +800,7 @@
isa = PBXProject;
attributes = {
LastTestingUpgradeCheck = 0600;
LastUpgradeCheck = 0600;
LastUpgradeCheck = 0710;
};
buildConfigurationList = E4005614148D79B500EB22B9 /* Build configuration list for PBXProject "ApplicationInsights" */;
compatibilityVersion = "Xcode 3.2";
@ -968,9 +827,6 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
80E1A3E81AE54B4200603B0A /* live_report_exception.plcrash in Resources */,
80E1A3E91AE54B4200603B0A /* live_report_signal.plcrash in Resources */,
80E1A3E71AE54B4200603B0A /* live_report_empty.plcrash in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -989,7 +845,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Sets the target folders and the final framework product.\nFMK_NAME=ApplicationInsights\nFMK_VERSION=A\n\n# Documentation\nAIS_DOCSET_VERSION_NAME=\"com.microsoft.applicationinsights.${AIS_DOCSET_NAME}-${VERSION_STRING}\"\n\n# Install dir will be the final output to the framework.\n# The following line create it in the root folder of the current project.\nPRODUCTS_DIR=${SRCROOT}/../Products\nZIP_FOLDER=${FMK_NAME}\nTEMP_DIR=${PRODUCTS_DIR}/${ZIP_FOLDER}\nINSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.framework\n\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator\n\n# Building the full featured SDK\n\n# Building both architectures.\nxcodebuild -project \"ApplicationInsights.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphoneos\nxcodebuild -project \"ApplicationInsights.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphonesimulator\n\n# Cleaning the products directory to make sure we have the latest files in it.\nif [ -d \"${PRODUCTS_DIR}\" ]\nthen\nrm -rf \"${PRODUCTS_DIR}\"\nfi\n\n# Creates and renews the final product folder.\nmkdir -p \"${INSTALL_DIR}\"\nmkdir -p \"${INSTALL_DIR}/Modules\"\nmkdir -p \"${INSTALL_DIR}/Versions\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers\"\n\n# Creates the internal links.\n# It MUST uses relative path, otherwise will not work when the folder is copied/moved.\nln -s \"${FMK_VERSION}\" \"${INSTALL_DIR}/Versions/Current\"\nln -s \"Versions/Current/Headers\" \"${INSTALL_DIR}/Headers\"\nln -s \"Versions/Current/Resources\" \"${INSTALL_DIR}/Resources\"\nln -s \"Versions/Current/${FMK_NAME}\" \"${INSTALL_DIR}/${FMK_NAME}\"\n\n# Copy the swift import file\ncp -f \"${SRCROOT}/module.modulemap\" \"${INSTALL_DIR}/Modules/\"\n\n# Copies the headers and resources files to the final product folder.\ncp -R \"${SRCROOT}/build/Release-iphoneos/include/${FMK_NAME}/\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -f \"${SRCROOT}/${FMK_NAME}.xcconfig\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\n\n# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.\nlipo -create \"${DEVICE_DIR}/lib${FMK_NAME}.a\" \"${SIMULATOR_DIR}/lib${FMK_NAME}.a\" -output \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\"\n\n# Combine the CrashReporter static library into a new ApplicationInsights static library file if they are not already present and copy the public headers too\nif [ -z $(otool -L \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" | grep 'libCrashReporter') ]\nthen\nlibtool -static -o \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${SRCROOT}/../Vendor/CrashReporter.framework/Versions/A/CrashReporter\"\nfi\n\n# Move the crash reporting only framework into a new folder\n#mkdir \"${INSTALL_DIR}/../${FMK_NAME}CrashOnly\"\n#mv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}CrashOnly/${FMK_NAME}.framework\"\n\n#rm -r \"${WRK_DIR}\"\n\n\n# copy license, changelog, documentation, integration json\n#cp -f \"${SRCROOT}/../Docs/Changelog-template.md\" \"${TEMP_DIR}/CHANGELOG\"\ncp -f \"${SRCROOT}/../Docs/Readme-template.md\" \"${TEMP_DIR}/README.md\"\ncp -f \"${SRCROOT}/../Docs/Readme-template.md\" \"${SRCROOT}/../README.md\"\ncp -f \"${SRCROOT}/../LICENSE\" \"${TEMP_DIR}\"\nmkdir \"${TEMP_DIR}/${AIS_DOCSET_VERSION_NAME}.docset\"\ncp -R \"${SRCROOT}/../documentation/docset/Contents\" \"${TEMP_DIR}/${AIS_DOCSET_VERSION_NAME}.docset\"\n\n# build zip\ncd \"${PRODUCTS_DIR}\"\nrm -f \"${FMK_NAME}-${VERSION_STRING}.zip\"\nzip -yr \"${FMK_NAME}-${VERSION_STRING}.zip\" \"${ZIP_FOLDER}\" -x \\*/.*\n";
shellScript = "# Sets the target folders and the final framework product.\nFMK_NAME=ApplicationInsights\nFMK_VERSION=A\n\n# Documentation\nAIS_DOCSET_VERSION_NAME=\"com.microsoft.applicationinsights.${AIS_DOCSET_NAME}-${VERSION_STRING}\"\n\n# Install dir will be the final output to the framework.\n# The following line create it in the root folder of the current project.\nPRODUCTS_DIR=${SRCROOT}/../Products\nZIP_FOLDER=${FMK_NAME}\nTEMP_DIR=${PRODUCTS_DIR}/${ZIP_FOLDER}\nINSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.framework\n\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator\n\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator\n\n# Building the full featured SDK\n\n# Building both architectures.\nxcodebuild -project \"ApplicationInsights.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphoneos\nxcodebuild -project \"ApplicationInsights.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphonesimulator\n\n# Cleaning the products directory to make sure we have the latest files in it.\nif [ -d \"${TEMP_DIR}\" ]\nthen\nrm -rf \"${TEMP_DIR}\"\nfi\n\n# Creates and renews the final product folder.\nmkdir -p \"${INSTALL_DIR}\"\nmkdir -p \"${INSTALL_DIR}/Modules\"\nmkdir -p \"${INSTALL_DIR}/Versions\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers\"\n\n# Creates the internal links.\n# It MUST uses relative path, otherwise will not work when the folder is copied/moved.\nln -s \"${FMK_VERSION}\" \"${INSTALL_DIR}/Versions/Current\"\nln -s \"Versions/Current/Headers\" \"${INSTALL_DIR}/Headers\"\nln -s \"Versions/Current/Resources\" \"${INSTALL_DIR}/Resources\"\nln -s \"Versions/Current/${FMK_NAME}\" \"${INSTALL_DIR}/${FMK_NAME}\"\n\n# Copy the swift import file\ncp -f \"${SRCROOT}/module.modulemap\" \"${INSTALL_DIR}/Modules/\"\n\n# Copies the headers and resources files to the final product folder.\ncp -R \"${SRCROOT}/build/Release-iphoneos/include/${FMK_NAME}/\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -f \"${SRCROOT}/${FMK_NAME}.xcconfig\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\n\n# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.\nlipo -create \"${DEVICE_DIR}/lib${FMK_NAME}.a\" \"${SIMULATOR_DIR}/lib${FMK_NAME}.a\" -output \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\"\n\nrm -r \"${WRK_DIR}\"\n\n# build embeddedframework folder and move framework into it\nmkdir \"${INSTALL_DIR}/../${FMK_NAME}\"\nmv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}/${FMK_NAME}.framework\"\n\n# copy license, changelog, documentation, integration json\n#cp -f \"${SRCROOT}/../Docs/Changelog-template.md\" \"${TEMP_DIR}/CHANGELOG\"\ncp -f \"${SRCROOT}/../Docs/Readme-template.md\" \"${TEMP_DIR}/README.md\"\ncp -f \"${SRCROOT}/../Docs/Readme-template.md\" \"${SRCROOT}/../README.md\"\ncp -f \"${SRCROOT}/../LICENSE\" \"${TEMP_DIR}\"\nmkdir \"${TEMP_DIR}/${AIS_DOCSET_VERSION_NAME}.docset\"\ncp -R \"${SRCROOT}/../documentation/docset/Contents\" \"${TEMP_DIR}/${AIS_DOCSET_VERSION_NAME}.docset\"\n\n# build zip\ncd \"${PRODUCTS_DIR}\"\nrm -f \"${FMK_NAME}-${VERSION_STRING}.zip\"\nzip -yr \"${FMK_NAME}-${VERSION_STRING}.zip\" \"${ZIP_FOLDER}\" -x \\*/.*\n";
};
1E8E66B215BC3D8200632A2E /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
@ -1004,19 +860,6 @@
shellPath = /bin/sh;
shellScript = "/usr/local/bin/appledoc \\\n --output \"${SOURCE_ROOT}/../documentation\" \\\n --ignore Vendor \\\n --ignore Products \\\n --ignore Support \\\n --ignore .m \\\n --ignore *Private.h \\\n --create-html \\\n --create-docset \\\n --install-docset \\\n --keep-intermediate-files \\\n --project-name \"${MSAI_DOCSET_NAME} ${VERSION_STRING}\" \\\n --project-version \"${VERSION_STRING}\" \\\n --project-company \"Microsoft\" \\\n --company-id \"com.microsoft\" \\\n --docset-bundle-name \"${MSAI_DOCSET_NAME} ${VERSION_STRING}\" \\\n --docset-feed-name \"${MSAI_DOCSET_NAME}\" \\\n --docset-desc \"\" \\\n --docset-platform-family \"iphoneos\" \\\n --index-desc \"${SOURCE_ROOT}/../docs/index.md\" \\\n --include \"${SOURCE_ROOT}/../docs/index.html\" \\\n --include \"${SOURCE_ROOT}/../docs/\" \\\n --merge-categories \\\n --no-repeat-first-par \\\n --warn-undocumented-object \\\n --warn-undocumented-member \\\n --warn-empty-description \\\n --warn-unknown-directive \\\n --warn-invalid-crossref \\\n --warn-missing-arg \\\n --logformat xcode \\\n --exit-threshold 2 \\\n \"${SOURCE_ROOT}/../\"\n";
};
1EE9071A16F6871F003DDE1D /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [ \"${CONFIGURATION}\" = \"CodeCoverage\" ]; then\n \"${SRCROOT}/../Vendor/XcodeCoverage/exportenv.sh\"\nfi";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -1032,20 +875,15 @@
807CFD6F1A712969004EA1B6 /* MSAIObject.m in Sources */,
807CFDAF1A712974004EA1B6 /* MSAIDevice.m in Sources */,
807CFDCA1A712974004EA1B6 /* MSAIRemoteDependencyData.m in Sources */,
1B3C387B1A82213000700081 /* MSAICrashDataHeaders.m in Sources */,
1E5954D315B6F24A00A03429 /* MSAIApplicationInsights.m in Sources */,
1BE29B491A6FB8C20014A10F /* MSAISender.m in Sources */,
1BBBCF371A6594AE00253031 /* MSAITelemetryContext.m in Sources */,
807CFDC21A712974004EA1B6 /* MSAIMetricData.m in Sources */,
1B47E02F1A84D3DF000B4C3D /* MSAIEnvelopeManager.m in Sources */,
1E3A26121B2B2C8B00D59683 /* MSAICrashCXXExceptionHandler.mm in Sources */,
807CFDB81A712974004EA1B6 /* MSAIExceptionData.m in Sources */,
E40E0B0D17DA1AFF005E38C1 /* MSAIAppClient.m in Sources */,
807CFDA61A712974004EA1B6 /* MSAIBase.m in Sources */,
1B3FB89F1A93756100D06311 /* MSAIReachability.m in Sources */,
809E9E5C1AC455D9008A1AB5 /* MSAISessionStateData.m in Sources */,
807CFDBA1A712974004EA1B6 /* MSAIExceptionDetails.m in Sources */,
1B3C387F1A82213000700081 /* MSAICrashDataThreadFrame.m in Sources */,
807CFDBC1A712974004EA1B6 /* MSAIInternal.m in Sources */,
807CFDBE1A712974004EA1B6 /* MSAILocation.m in Sources */,
E4933E8117B66CDA00B11ACC /* MSAIHTTPOperation.m in Sources */,
@ -1053,24 +891,17 @@
807CFDB41A712974004EA1B6 /* MSAIEnvelope.m in Sources */,
1E49A4C1161222B900463151 /* MSAIHelper.m in Sources */,
807CFDCE1A712974004EA1B6 /* MSAISession.m in Sources */,
807CFDD11A712974004EA1B6 /* MSAIStackFrame.m in Sources */,
1B3C38771A82213000700081 /* MSAICrashData.m in Sources */,
807CFD691A71294E004EA1B6 /* MSAIOrderedDictionary.m in Sources */,
807CFDC61A712974004EA1B6 /* MSAIPageViewData.m in Sources */,
1EB2E4C718FD4CEA008BB1CF /* MSAITelemetryManager.m in Sources */,
1E90FD7418EDB86400CF0417 /* MSAICrashDetails.m in Sources */,
1E49A4DB161222D400463151 /* ApplicationInsightsPrivate.m in Sources */,
807CFD711A712969004EA1B6 /* MSAITelemetryData.m in Sources */,
1BC8596C1A7ACA820018FB6B /* MSAICategoryContainer.m in Sources */,
807CFDB11A712974004EA1B6 /* MSAIDomain.m in Sources */,
1B3C38791A82213000700081 /* MSAICrashDataBinary.m in Sources */,
807CFDD31A712974004EA1B6 /* MSAIUser.m in Sources */,
807CFDB61A712974004EA1B6 /* MSAIEventData.m in Sources */,
807CFDA81A712974004EA1B6 /* MSAIData.m in Sources */,
1B3C387D1A82213000700081 /* MSAICrashDataThread.m in Sources */,
1B62F4D91A692A3200EB5AD0 /* MSAIContext.m in Sources */,
1E754E5D1621FBB70070AB92 /* MSAICrashManager.m in Sources */,
1E754E611621FBB70070AB92 /* MSAICrashDataProvider.m in Sources */,
807CFDA41A712974004EA1B6 /* MSAIApplication.m in Sources */,
1BBBCF351A6594AE00253031 /* MSAIChannel.m in Sources */,
1E0FEE29173BDB260061331F /* MSAIKeychainUtils.m in Sources */,
@ -1086,21 +917,16 @@
8000A3D41B0E973F009F2B29 /* MSAICategoryContainerTests.m in Sources */,
80E1A42F1AE54B5300603B0A /* MSAISenderTests.m in Sources */,
80E1A4291AE54B5300603B0A /* MSAIPageViewDataTests.m in Sources */,
80E1A4181AE54B5300603B0A /* MSAICrashDataProviderTests.m in Sources */,
80E1A4361AE54B5300603B0A /* MSAITestsDependencyInjection.m in Sources */,
80E1A41B1AE54B5300603B0A /* MSAIDeviceTests.m in Sources */,
80E1A4261AE54B5300603B0A /* MSAIMessageDataTests.m in Sources */,
80E1A4121AE54B5300603B0A /* MSAIAppClientTests.m in Sources */,
80E1A4171AE54B5300603B0A /* MSAICrashManagerTests.m in Sources */,
80E1A41C1AE54B5300603B0A /* MSAIDomainTests.m in Sources */,
80E1A4371AE54B5300603B0A /* MSAIUserTests.m in Sources */,
80E1A4211AE54B5300603B0A /* MSAIExceptionDetailsTests.m in Sources */,
80E1A4321AE54B5300603B0A /* MSAIStackFrameTests.m in Sources */,
80E1A4271AE54B5300603B0A /* MSAIMetricDataTests.m in Sources */,
80E1A41F1AE54B5300603B0A /* MSAIEventDataTests.m in Sources */,
80E1A4231AE54B5300603B0A /* MSAIInternalTests.m in Sources */,
80E1A4191AE54B5300603B0A /* MSAIDataPointTests.m in Sources */,
80E1A4201AE54B5300603B0A /* MSAIExceptionDataTests.m in Sources */,
80E1A4221AE54B5300603B0A /* MSAIHelperTests.m in Sources */,
80E1A42A1AE54B5300603B0A /* MSAIPageViewPerfDataTests.m in Sources */,
80E1A4161AE54B5300603B0A /* MSAIChannelTests.m in Sources */,
@ -1144,6 +970,7 @@
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_FILE = "$(PROJECT_DIR)/../Resources/ApplicationInsights-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.microsoft.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = ApplicationInsights.framework;
};
name = Debug;
@ -1152,6 +979,7 @@
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_FILE = "$(PROJECT_DIR)/../Resources/ApplicationInsights-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.microsoft.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = ApplicationInsights.framework;
};
name = Release;
@ -1194,10 +1022,6 @@
"$(PROJECT_DIR)",
);
GCC_THUMB_SUPPORT = NO;
OTHER_CFLAGS = (
"$(inherited)",
"-DNS_BLOCK_ASSERTIONS=1",
);
PRODUCT_NAME = ApplicationInsights;
PUBLIC_HEADERS_FOLDER_PATH = "include/$(PRODUCT_NAME)";
SKIP_INSTALL = YES;
@ -1226,10 +1050,7 @@
"$(SRCROOT)/../Vendor",
"$(SRCROOT)/ApplicationInsightsTests",
);
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
GCC_LINK_WITH_DYNAMIC_LIBRARIES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ApplicationInsightsTests/ApplicationInsightsTests-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"DEBUG=1",
@ -1252,6 +1073,7 @@
"$(inherited)",
"-ObjC",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.microsoft.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = ApplicationInsightsTests;
WARNING_CFLAGS = (
"-Wall",
@ -1277,10 +1099,8 @@
"$(SRCROOT)/../Vendor",
"$(SRCROOT)/ApplicationInsightsTests",
);
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
GCC_LINK_WITH_DYNAMIC_LIBRARIES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ApplicationInsightsTests/ApplicationInsightsTests-Prefix.pch";
GCC_WARN_UNINITIALIZED_AUTOS = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
@ -1299,6 +1119,7 @@
"$(inherited)",
"-ObjC",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.microsoft.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = ApplicationInsightsTests;
VALIDATE_PRODUCT = YES;
WARNING_CFLAGS = (
@ -1308,148 +1129,12 @@
};
name = Release;
};
1E68F4A716F7843F00053706 /* CodeCoverage */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1E66CA9115D4100500F35BED /* buildnumber.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_GENERATE_TEST_COVERAGE_FILES = YES;
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "$(SRCROOT)/../Classes/ApplicationInsights-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"MSAI_STATIC_LIBRARY=1",
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_THUMB_SUPPORT = NO;
GCC_VERSION = "";
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_STRICT_SELECTOR_MATCH = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = "../Resources/AIS-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
"IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0;
MACOSX_DEPLOYMENT_TARGET = 10.5;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"-Wshorten-64-to-32",
"-Wall",
);
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = iphoneos;
};
name = CodeCoverage;
};
1E68F4A816F7843F00053706 /* CodeCoverage */ = {
isa = XCBuildConfiguration;
buildSettings = {
"ARCHS[sdk=iphonesimulator*]" = "$(MSAI_SIM_ARCHS)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
DSTROOT = /tmp/AIS.dst;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/../Vendor\"",
"$(PROJECT_DIR)",
);
GCC_THUMB_SUPPORT = NO;
GENERATE_PROFILING_CODE = YES;
PRODUCT_NAME = ApplicationInsights;
PUBLIC_HEADERS_FOLDER_PATH = "include/$(PRODUCT_NAME)";
SKIP_INSTALL = YES;
"VALID_ARCHS[sdk=iphonesimulator*]" = "$(MSAI_SIM_ARCHS)";
WARNING_CFLAGS = (
"-Wall",
"-Wextra",
"-Wno-unused-parameter",
);
};
name = CodeCoverage;
};
1E68F4AA16F7843F00053706 /* CodeCoverage */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_THUMB_SUPPORT = NO;
INFOPLIST_FILE = "$(PROJECT_DIR)/../Resources/ApplicationInsights-Info.plist";
PRODUCT_NAME = "ApplicationInsights Documentation";
};
name = CodeCoverage;
};
1E68F4AB16F7843F00053706 /* CodeCoverage */ = {
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_FILE = "$(PROJECT_DIR)/../Resources/ApplicationInsights-Info.plist";
PRODUCT_NAME = ApplicationInsights.framework;
};
name = CodeCoverage;
};
1E68F4AC16F7843F00053706 /* CodeCoverage */ = {
isa = XCBuildConfiguration;
buildSettings = {
"ARCHS[sdk=iphonesimulator*]" = "$(MSAI_SIM_ARCHS)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SDKROOT)/Developer/Library/Frameworks\"",
"$(SRCROOT)/../Vendor",
"$(SRCROOT)/ApplicationInsightsTests",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ApplicationInsightsTests/ApplicationInsightsTests-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"DEBUG=1",
);
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GENERATE_PROFILING_CODE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../Classes",
"$(SRCROOT)/ApplicationInsightsTests",
);
INFOPLIST_FILE = "ApplicationInsightsTests/ApplicationInsightsTests-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.1;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/ApplicationInsightsTests",
);
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
);
PRODUCT_NAME = ApplicationInsightsTests;
WARNING_CFLAGS = (
"-Wall",
"-Wextra",
);
};
name = CodeCoverage;
};
1E8E66AE15BC3D7700632A2E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_THUMB_SUPPORT = NO;
INFOPLIST_FILE = "$(PROJECT_DIR)/../Resources/ApplicationInsights-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.microsoft.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "ApplicationInsights Documentation";
};
name = Debug;
@ -1459,6 +1144,7 @@
buildSettings = {
GCC_THUMB_SUPPORT = NO;
INFOPLIST_FILE = "$(PROJECT_DIR)/../Resources/ApplicationInsights-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.microsoft.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "ApplicationInsights Documentation";
};
name = Release;
@ -1472,6 +1158,7 @@
CLANG_WARN_ENUM_CONVERSION = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = NO;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@ -1496,10 +1183,6 @@
"IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0;
MACOSX_DEPLOYMENT_TARGET = 10.5;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"-Wshorten-64-to-32",
"-Wall",
);
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = iphoneos;
};
@ -1533,10 +1216,6 @@
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
"IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0;
MACOSX_DEPLOYMENT_TARGET = 10.5;
OTHER_CFLAGS = (
"-Wshorten-64-to-32",
"-Wall",
);
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = NO;
@ -1550,7 +1229,6 @@
isa = XCConfigurationList;
buildConfigurations = (
1E4F61EB1621AD970033EFC5 /* Debug */,
1E68F4AB16F7843F00053706 /* CodeCoverage */,
1E4F61EC1621AD970033EFC5 /* Release */,
);
defaultConfigurationIsVisible = 0;
@ -1560,7 +1238,6 @@
isa = XCConfigurationList;
buildConfigurations = (
1E5954F015B6F24A00A03429 /* Debug */,
1E68F4A816F7843F00053706 /* CodeCoverage */,
1E5954F115B6F24A00A03429 /* Release */,
);
defaultConfigurationIsVisible = 0;
@ -1570,7 +1247,6 @@
isa = XCConfigurationList;
buildConfigurations = (
1E5A45A016F0DFC200B55C04 /* Debug */,
1E68F4AC16F7843F00053706 /* CodeCoverage */,
1E5A45A116F0DFC200B55C04 /* Release */,
);
defaultConfigurationIsVisible = 0;
@ -1580,7 +1256,6 @@
isa = XCConfigurationList;
buildConfigurations = (
1E8E66AE15BC3D7700632A2E /* Debug */,
1E68F4AA16F7843F00053706 /* CodeCoverage */,
1E8E66AF15BC3D7700632A2E /* Release */,
);
defaultConfigurationIsVisible = 0;
@ -1590,7 +1265,6 @@
isa = XCConfigurationList;
buildConfigurations = (
E400563C148D79B500EB22B9 /* Debug */,
1E68F4A716F7843F00053706 /* CodeCoverage */,
E400563D148D79B500EB22B9 /* Release */,
);
defaultConfigurationIsVisible = 0;

Просмотреть файл

@ -23,21 +23,24 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
@ -52,10 +55,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction

Просмотреть файл

@ -22,10 +22,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
@ -38,15 +38,18 @@
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
@ -61,10 +64,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction

Просмотреть файл

@ -22,10 +22,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "CodeCoverage">
shouldUseLaunchSchemeArgsEnv = "YES">
<PostActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
@ -66,15 +66,18 @@
ReferencedContainer = "container:ApplicationInsights.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
@ -89,10 +92,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference

Просмотреть файл

@ -1,32 +0,0 @@
/*
* This file is only used by the binary framework target when building
* and creating the crash reporting only framework
*
* Attention: Do not include this into your projects yourself!
*/
#ifndef AppInsights_AppInsightsFeatureConfig_h
#define APPINSIGHTS_APPINSIGHTSFeatureConfig_h
/**
* If true, include support for handling crash reports
*
* _Default_: Enabled
*/
#ifndef APPINSIGHTS_FEATURE_CRASH_REPORTER
# define APPINSIGHTS_FEATURE_CRASH_REPORTER 1
#endif /* APPINSIGHTS_FEATURE_CRASH_REPORTER */
/**
* If true, include support for sending metrics data
*
* _Default_: Enabled
*/
#ifndef MSAI_FEATURE_METRICS
# define MSAI_FEATURE_METRICS 0
#endif /* MSAI_FEATURE_METRICS */
#endif /* AppInsights_AppInsightsFeatureConfig_h */

Просмотреть файл

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.microsoft.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>

Просмотреть файл

@ -1,23 +0,0 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
#if !__has_feature(nullability)
#define NS_ASSUME_NONNULL_BEGIN
#define NS_ASSUME_NONNULL_END
#define nullable
#define nonnull
#define null_unspecified
#define null_resettable
#define __nullable
#define __nonnull
#define __null_unspecified
#endif
#ifndef NS_ASSUME_NONNULL_BEGIN
#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
#endif
#ifndef NS_ASSUME_NONNULL_END
#define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
#endif

Просмотреть файл

Двоичный файл не отображается.

Двоичный файл не отображается.

Просмотреть файл

@ -28,26 +28,12 @@
[super setUp];
self.sut = [MSAIContextHelper new];
self.sut.metaData[@"sessions"] = [NSMutableDictionary new];
self.sut.metaData[@"users"] = [NSMutableDictionary new];
}
- (void)teardown {
NSString *path = [[MSAIPersistence sharedInstance] newFileURLForPersitenceType:MSAIPersistenceTypeMetaData];
[[MSAIPersistence sharedInstance] deleteFileAtPath:path];
[super tearDown];
}
#pragma mark - Setup Tests
- (void)testSetupCorrectly {
for (NSObject *object in self.sut.metaData.allValues) {
assertThat(object, instanceOf(NSMutableDictionary.class));
}
assertThatInteger(_sut.metaData.count, equalToInteger(2));
}
#pragma mark - User Tests
- (void)testNewUser {
@ -56,6 +42,42 @@
XCTAssertEqual(newUser.userId.length, 36U);
}
- (void)testUserGetsPersitedCorrectly {
NSString *anonymousID = @"anonymousID";
NSString *anonymousDate = @"anonymousDate";
NSString *authenticatedID = @"authenticatedID";
NSString *authenticatedDate = @"authenticatedDate";
NSString *accountID = @"accountID";
NSString *accountDate = @"accountDate";
NSString *storeRegion = @"storeRegion";
NSString *userAgent = @"userAgent";
MSAIUser *user = [MSAIUser new];
user.userId = anonymousID;
user.anonUserAcquisitionDate = anonymousDate;
user.authUserId = authenticatedID;
user.authUserAcquisitionDate = authenticatedDate;
user.accountId = accountID;
user.accountAcquisitionDate = accountDate;
user.storeRegion = storeRegion;
user.userAgent = userAgent;
// When
[self.sut saveUser:user];
MSAIUser *persistedUser = [self.sut loadUser];
// Verify
XCTAssertNotNil(persistedUser);
XCTAssertTrue([persistedUser.userId isEqualToString:anonymousID]);
XCTAssertTrue([persistedUser.anonUserAcquisitionDate isEqualToString:anonymousDate]);
XCTAssertTrue([persistedUser.authUserId isEqualToString:authenticatedID]);
XCTAssertTrue([persistedUser.authUserAcquisitionDate isEqualToString:authenticatedDate]);
XCTAssertTrue([persistedUser.accountId isEqualToString:accountID]);
XCTAssertTrue([persistedUser.accountAcquisitionDate isEqualToString:accountDate]);
XCTAssertTrue([persistedUser.storeRegion isEqualToString:storeRegion]);
XCTAssertTrue([persistedUser.userAgent isEqualToString:userAgent]);
}
- (void)testSetUserWithConfigurationBlock {
self.sut = OCMPartialMock(self.sut);
@ -89,61 +111,6 @@
}]]);
}
- (void)testAddUser {
XCTAssert([(NSDictionary *)self.sut.metaData[@"users"] count] == 0);
MSAIUser *testUser = [MSAIUser new];
[self.sut addUser:testUser forDate:[NSDate dateWithTimeIntervalSince1970:23]];
XCTAssert([(NSDictionary *)self.sut.metaData[@"users"] count] == 1);
XCTAssertEqualObjects(testUser, self.sut.metaData[@"users"][@"23"]);
}
- (void)testUserForDate {
MSAIUser *user1 = [self newUserWithId:@"10"];
MSAIUser *user2 = [self newUserWithId:@"20"];
MSAIUser *user3 = [self newUserWithId:@"30"];
[self.sut addUser:user1 forDate:[NSDate dateWithTimeIntervalSince1970:3]];
[self.sut addUser:user2 forDate:[NSDate dateWithTimeIntervalSince1970:33]];
[self.sut addUser:user3 forDate:[NSDate dateWithTimeIntervalSince1970:333]];
MSAIUser *user = [self.sut userForDate:[NSDate dateWithTimeIntervalSince1970:0]];
XCTAssertNil(user);
user = [self.sut userForDate:[NSDate dateWithTimeIntervalSince1970:2]];
XCTAssertNil(user);
user = [self.sut userForDate:[NSDate dateWithTimeIntervalSince1970:3+23]];
XCTAssertEqual(user, user1);
user = [self.sut userForDate:[NSDate dateWithTimeIntervalSince1970:33]];
XCTAssertEqual(user, user2);
user = [self.sut userForDate:[NSDate dateWithTimeIntervalSince1970:33+42]];
XCTAssertEqual(user, user2);
user = [self.sut userForDate:[NSDate dateWithTimeIntervalSince1970:333+1337]];
XCTAssertEqual(user, user3);
}
- (void)testRemoveUserId {
MSAIUser *userA = [self newUserWithId:@"a"];
MSAIUser *userB = [self newUserWithId:@"b"];
MSAIUser *userC = [self newUserWithId:@"c"];
[self.sut addUser:userA forDate:[NSDate dateWithTimeIntervalSince1970:0]];
[self.sut addUser:userB forDate:[NSDate dateWithTimeIntervalSince1970:1]];
[self.sut addUser:userC forDate:[NSDate dateWithTimeIntervalSince1970:2]];
[self.sut removeUserId:@"b"];
XCTAssertEqual(self.sut.metaData.count, 2U);
XCTAssertEqual([(NSDictionary *)self.sut.metaData[@"users"] count], 2U);
XCTAssertEqualObjects(self.sut.metaData[@"users"][@"0"], userA);
XCTAssertEqualObjects(self.sut.metaData[@"users"][@"2"], userC);
XCTAssertNil(self.sut.metaData[@"users"][@"1"]);
}
#pragma mark - Session Tests
#pragma mark Test Automtic Session Management
@ -162,7 +129,6 @@
- (void)testRenewSessionWithId {
self.sut = OCMPartialMock(self.sut);
XCTAssertEqual([(NSDictionary *)self.sut.metaData[@"sessions"] count], 0U);
NSString *testId = @"1337";
[self.sut renewSessionWithId:testId];
@ -176,102 +142,8 @@
}]]);
}
- (void)testAddSession {
NSDate *date = [NSDate date];
NSString *timestamp = [self.sut unixTimestampFromDate:date];
MSAISession *session = [self sessionWithId:@"4815162342"];
[self.sut addSession:session withDate:date];
XCTAssertEqual(((NSMutableDictionary *)self.sut.metaData[@"sessions"]).count, 1U);
XCTAssertEqualObjects(self.sut.metaData[@"sessions"][timestamp], session);
}
- (void)testSessionForDate {
MSAISession *session1 = [self sessionWithId:@"10"];
MSAISession *session2 = [self sessionWithId:@"20"];
MSAISession *session3 = [self sessionWithId:@"30"];
[self.sut addSession:session1 withDate:[NSDate dateWithTimeIntervalSince1970:3]];
[self.sut addSession:session2 withDate:[NSDate dateWithTimeIntervalSince1970:33]];
[self.sut addSession:session3 withDate:[NSDate dateWithTimeIntervalSince1970:333]];
MSAISession *session = [self.sut sessionForDate:[NSDate dateWithTimeIntervalSince1970:0]];
XCTAssertNil(session);
session = [self.sut sessionForDate:[NSDate dateWithTimeIntervalSince1970:2]];
XCTAssertNil(session);
session = [self.sut sessionForDate:[NSDate dateWithTimeIntervalSince1970:3+23]];
XCTAssertEqual(session, session1);
session = [self.sut sessionForDate:[NSDate dateWithTimeIntervalSince1970:33]];
XCTAssertEqual(session, session2);
session = [self.sut sessionForDate:[NSDate dateWithTimeIntervalSince1970:33+42]];
XCTAssertEqual(session, session2);
session = [self.sut sessionForDate:[NSDate dateWithTimeIntervalSince1970:333+1337]];
XCTAssertEqual(session, session3);
}
- (void)testRemoveSession {
MSAISession *sessionA = [self sessionWithId:@"a"];
MSAISession *sessionB = [self sessionWithId:@"b"];
MSAISession *sessionC = [self sessionWithId:@"c"];
[self.sut addSession:sessionA withDate:[NSDate dateWithTimeIntervalSince1970:0]];
[self.sut addSession:sessionB withDate:[NSDate dateWithTimeIntervalSince1970:1]];
[self.sut addSession:sessionC withDate:[NSDate dateWithTimeIntervalSince1970:2]];
[self.sut removeSession:[self sessionWithId:@"b"]];
XCTAssertEqual(self.sut.metaData.count, 2U);
XCTAssertEqual([(NSDictionary *)self.sut.metaData[@"sessions"] count], 2U);
XCTAssertNotNil(self.sut.metaData[@"sessions"][@"0"]);
XCTAssertNotNil(self.sut.metaData[@"sessions"][@"2"]);
XCTAssertNil(self.sut.metaData[@"sessions"][@"1"]);
}
#pragma mark -
- (void)testCleanUpMetaData {
XCTAssertEqual(self.sut.metaData.count, 2U);
XCTAssertEqual([(NSDictionary *)self.sut.metaData[@"sessions"] count], 0U);
XCTAssertEqual([(NSDictionary *)self.sut.metaData[@"users"] count ], 0U);
MSAISession *sessionA = [self sessionWithId:@"a"];
MSAISession *sessionB = [self sessionWithId:@"b"];
MSAISession *sessionC = [self sessionWithId:@"c"];
[self.sut addSession:sessionA withDate:[NSDate dateWithTimeIntervalSince1970:3]];
[self.sut addSession:sessionB withDate:[NSDate dateWithTimeIntervalSince1970:33]];
[self.sut addSession:sessionC withDate:[NSDate dateWithTimeIntervalSince1970:333]];
XCTAssertEqual([(NSDictionary *)self.sut.metaData[@"sessions"] count], 3U);
MSAIUser *user1 = [self newUserWithId:@"1"];
MSAIUser *user2 = [self newUserWithId:@"2"];
[self.sut addUser:user1 forDate:[NSDate dateWithTimeIntervalSince1970:777]];
[self.sut addUser:user2 forDate:[NSDate dateWithTimeIntervalSince1970:7777]];
XCTAssertEqual([(NSDictionary *)self.sut.metaData[@"users"] count], 2U);
[self.sut cleanUpMetaData];
XCTAssertEqual(self.sut.metaData.count, 2U);
XCTAssertEqual([(NSDictionary *)self.sut.metaData[@"sessions"] count], 1U);
XCTAssertEqual([(NSDictionary *)self.sut.metaData[@"users"] count ], 1U);
XCTAssertNil(self.sut.metaData[@"sessions"][@"3"]);
XCTAssertNil(self.sut.metaData[@"sessions"][@"33"]);
XCTAssertEqualObjects(self.sut.metaData[@"sessions"][@"333"], sessionC);
XCTAssertNil(self.sut.metaData[@"users"][@"777"]);
XCTAssertEqualObjects(self.sut.metaData[@"users"][@"7777"], user2);
}
- (void)testUnixTimestampFromDate {
NSString *timestamp = [self.sut unixTimestampFromDate:[NSDate dateWithTimeIntervalSince1970:42]];
XCTAssertEqualObjects(timestamp, @"42");

Просмотреть файл

@ -1,106 +0,0 @@
#import <XCTest/XCTest.h>
#import "MSAICrashDataProvider.h"
@interface MSAICrashDataProviderTests : XCTestCase
@end
@implementation MSAICrashDataProviderTests
- (void)setUp {
[super setUp];
}
- (void)tearDown {
[super tearDown];
}
- (void)testiOSImages {
NSString *processPath = nil;
NSString *appBundlePath = nil;
appBundlePath = @"/private/var/mobile/Containers/Bundle/Application/9107B4E2-CD8C-486E-A3B2-82A5B818F2A0/MyApp.app";
// Test with iOS App
processPath = [appBundlePath stringByAppendingString:@"/MyApp"];
[self testiOSNonAppSpecificImagesForProcessPath:processPath];
[self testAppBinaryWithImagePath:processPath processPath:processPath];
[self testiOSAppFrameworkAtProcessPath:processPath appBundlePath:appBundlePath];
// Test with iOS App Extension
processPath = [appBundlePath stringByAppendingString:@"/Plugins/MyAppExtension.appex/MyAppExtension"];
[self testiOSNonAppSpecificImagesForProcessPath:processPath];
[self testAppBinaryWithImagePath:processPath processPath:processPath];
[self testiOSAppFrameworkAtProcessPath:processPath appBundlePath:appBundlePath];
}
#pragma mark - Test Helper
- (void)testAppBinaryWithImagePath:(NSString *)imagePath processPath:(NSString *)processPath {
MSAIBinaryImageType imageType = [MSAICrashDataProvider imageTypeForImagePath:imagePath
processPath:processPath];
XCTAssert((imageType == MSAIBinaryImageTypeAppBinary), @"Test app %@ with process %@", imagePath, processPath);
}
#pragma mark - iOS Test Helper
- (void)testiOSAppFrameworkAtProcessPath:(NSString *)processPath appBundlePath:(NSString *)appBundlePath {
NSString *frameworkPath = [appBundlePath stringByAppendingString:@"/Frameworks/MyFrameworkLib.framework/MyFrameworkLib"];
MSAIBinaryImageType imageType = [MSAICrashDataProvider imageTypeForImagePath:frameworkPath
processPath:processPath];
XCTAssert((imageType == MSAIBinaryImageTypeAppFramework), @"Test framework %@ with process %@", frameworkPath, processPath);
frameworkPath = [appBundlePath stringByAppendingString:@"/Frameworks/libSwiftMyLib.framework/libSwiftMyLib"];
imageType = [MSAICrashDataProvider imageTypeForImagePath:frameworkPath
processPath:processPath];
XCTAssert((imageType == MSAIBinaryImageTypeAppFramework), @"Test framework %@ with process %@", frameworkPath, processPath);
NSMutableArray *swiftFrameworkPaths = [NSMutableArray new];
[swiftFrameworkPaths addObject:[appBundlePath stringByAppendingString:@"/Frameworks/libswiftCore.dylib"]];
[swiftFrameworkPaths addObject:[appBundlePath stringByAppendingString:@"/Frameworks/libswiftDarwin.dylib"]];
[swiftFrameworkPaths addObject:[appBundlePath stringByAppendingString:@"/Frameworks/libswiftDispatch.dylib"]];
[swiftFrameworkPaths addObject:[appBundlePath stringByAppendingString:@"/Frameworks/libswiftFoundation.dylib"]];
[swiftFrameworkPaths addObject:[appBundlePath stringByAppendingString:@"/Frameworks/libswiftObjectiveC.dylib"]];
[swiftFrameworkPaths addObject:[appBundlePath stringByAppendingString:@"/Frameworks/libswiftSecurity.dylib"]];
[swiftFrameworkPaths addObject:[appBundlePath stringByAppendingString:@"/Frameworks/libswiftCoreGraphics.dylib"]];
for (NSString *imagePath in swiftFrameworkPaths) {
MSAIBinaryImageType imageType = [MSAICrashDataProvider imageTypeForImagePath:imagePath
processPath:processPath];
XCTAssert((imageType == MSAIBinaryImageTypeOther), @"Test swift image %@ with process %@", imagePath, processPath);
}
}
- (void)testiOSNonAppSpecificImagesForProcessPath:(NSString *)processPath {
// system test paths
NSMutableArray *nonAppSpecificImagePaths = [NSMutableArray new];
// iOS frameworks
[nonAppSpecificImagePaths addObject:@"/System/Library/AccessibilityBundles/AccessibilitySettingsLoader.bundle/AccessibilitySettingsLoader"];
[nonAppSpecificImagePaths addObject:@"/System/Library/Frameworks/AVFoundation.framework/AVFoundation"];
[nonAppSpecificImagePaths addObject:@"/System/Library/Frameworks/AVFoundation.framework/libAVFAudio.dylib"];
[nonAppSpecificImagePaths addObject:@"/System/Library/PrivateFrameworks/AOSNotification.framework/AOSNotification"];
[nonAppSpecificImagePaths addObject:@"/System/Library/PrivateFrameworks/Accessibility.framework/Frameworks/AccessibilityUI.framework/AccessibilityUI"];
[nonAppSpecificImagePaths addObject:@"/System/Library/PrivateFrameworks/Accessibility.framework/Frameworks/AccessibilityUIUtilities.framework/AccessibilityUIUtilities"];
[nonAppSpecificImagePaths addObject:@"/usr/lib/libAXSafeCategoryBundle.dylib"];
[nonAppSpecificImagePaths addObject:@"/usr/lib/libAXSpeechManager.dylib"];
[nonAppSpecificImagePaths addObject:@"/usr/lib/libAccessibility.dylib"];
[nonAppSpecificImagePaths addObject:@"/usr/lib/system/libcache.dylib"];
[nonAppSpecificImagePaths addObject:@"/usr/lib/system/libcommonCrypto.dylib"];
[nonAppSpecificImagePaths addObject:@"/usr/lib/system/libcompiler_rt.dylib"];
// iOS Jailbreak libraries
[nonAppSpecificImagePaths addObject:@"/Library/MobileSubstrate/MobileSubstrate.dylib"];
[nonAppSpecificImagePaths addObject:@"/Library/MobileSubstrate/DynamicLibraries/WeeLoader.dylib"];
[nonAppSpecificImagePaths addObject:@"/Library/Frameworks/CydiaSubstrate.framework/Libraries/SubstrateLoader.dylib"];
[nonAppSpecificImagePaths addObject:@"/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate"];
[nonAppSpecificImagePaths addObject:@"/Library/MobileSubstrate/DynamicLibraries/WinterBoard.dylib"];
for (NSString *imagePath in nonAppSpecificImagePaths) {
MSAIBinaryImageType imageType = [MSAICrashDataProvider imageTypeForImagePath:imagePath
processPath:processPath];
XCTAssert((imageType == MSAIBinaryImageTypeOther), @"Test other image %@ with process %@", imagePath, processPath);
}
}
@end

Просмотреть файл

@ -1,175 +0,0 @@
#import <XCTest/XCTest.h>
#define HC_SHORTHAND
#import <OCHamcrestIOS/OCHamcrestIOS.h>
#define MOCKITO_SHORTHAND
#import <OCMockitoIOS/OCMockitoIOS.h>
#import "MSAICrashManager.h"
#import "MSAICrashManagerPrivate.h"
#import "MSAIContextPrivate.h"
#import "MSAIPersistencePrivate.h"
#import "MSAIEnvelope.h"
#import "MSAIBase.h"
#import "MSAICrashData.h"
#import "MSAITestHelper.h"
#import "MSAITelemetryContext.h"
#import "MSAITelemetryContextPrivate.h"
#import "MSAIEnvelopeManager.h"
#import "MSAIEnvelopeManagerPrivate.h"
#define kMSAICrashMetaAttachment @"MSAICrashMetaAttachment"
#if MSAI_FEATURE_CRASH_REPORTER
@interface MSAICrashManagerTests : XCTestCase
@end
@implementation MSAICrashManagerTests {
BOOL _startManagerInitialized;
}
- (void)setUp {
[super setUp];
_startManagerInitialized = NO;
MSAIContext *context = [[MSAIContext alloc]initWithInstrumentationKey:@"123"];
MSAITelemetryContext *telemetryContext = [[MSAITelemetryContext alloc] initWithAppContext:context];
[[MSAIEnvelopeManager sharedManager] configureWithTelemetryContext:telemetryContext];
}
- (void)tearDown {
[super tearDown];
}
#pragma mark - Helpers for start/stop
- (void)startManager {
[MSAICrashManager sharedManager].isCrashManagerDisabled = NO;
if(!_startManagerInitialized) {
[[MSAICrashManager sharedManager] startManager];
}
_startManagerInitialized = YES;
}
- (void)startManagerDisabled {
[MSAICrashManager sharedManager].isCrashManagerDisabled = YES;
if(!_startManagerInitialized) {
[[MSAICrashManager sharedManager] startManager];
}
_startManagerInitialized = YES;
}
#pragma mark - Setup Tests
- (void)testThatItInstantiates {
XCTAssertNotNil([MSAICrashManager sharedManager], @"Should be there");
}
- (void)testThatItIsSetup {
[self startManager];
XCTAssertTrue([[MSAICrashManager sharedManager] isSetupCorrectly]);
}
#pragma mark - Debugger
/**
* We are running this usually witin Xcode
* TODO: what to do if we do run this e.g. on Jenkins or Xcode bots ?
*/
- (void)testIsDebuggerAttached {
assertThatBool([MSAICrashManager sharedManager].debuggerIsAttached, isTrue());
}
- (void)testStartManagerWithModuleDisabled {
[self startManagerDisabled];
assertThatBool([MSAICrashManager sharedManager].isCrashManagerDisabled, isTrue());
}
#pragma mark - Crash Reporting
- (void)testHasPendingCrashReportWithNoFiles {
[MSAICrashManager sharedManager].isCrashManagerDisabled = NO;
assertThatBool([[MSAICrashManager sharedManager].plCrashReporter hasPendingCrashReport], isFalse());
}
- (void)testCreateCrashReportForAppKill {
//handle app kill (FakeCrashReport will be generated)
[[MSAICrashManager sharedManager] createCrashReportForAppKill]; //just creates a fake crash report and hands it over to MSAIPersistence
NSArray *bundle = [[MSAIPersistence sharedInstance] crashTemplateBundle];
XCTAssertNil(bundle);
if(bundle && ([bundle count] > 0)) {
id envelope = [bundle firstObject];
if(envelope && [envelope isKindOfClass:[MSAIEnvelope class]]) {
assertThatBool([((MSAIEnvelope *) envelope).data isKindOfClass:[MSAICrashData class]], isTrue());
}
}
}
#pragma mark - StartManager
- (void)testStartPLCrashReporterSetup {
// since PLCR is only initialized once ever, we need to pack all tests that rely on a PLCR instance
// in this test method. Ugly but otherwise this would require a major redesign of MSAICrashManager
// which we can't do at this moment
// This also limits us not being able to test various scenarios having a custom exception handler
// which would require us to run without a debugger anyway and which would also require a redesign
// to make this better testable with unit tests
id delegateMock = mockProtocol(@protocol(MSAICrashManagerDelegate));
[MSAICrashManager sharedManager].delegate = delegateMock;
[self startManager];
assertThat([MSAICrashManager sharedManager].plCrashReporter, notNilValue());
// When running from the debugger this is always nil and not the exception handler from PLCR
NSUncaughtExceptionHandler *currentHandler = NSGetUncaughtExceptionHandler();
BOOL result = ([MSAICrashManager sharedManager].exceptionHandler == currentHandler);
assertThatBool(result, isTrue());
// No files at startup
assertThatBool([[MSAICrashManager sharedManager].plCrashReporter hasPendingCrashReport], isFalse());
[[MSAICrashManager sharedManager] readCrashReportAndStartProcessing];
// handle a new empty crash report
assertThatBool([MSAITestHelper copyFixtureCrashReportWithFileName:@"live_report_empty"], isTrue());
assertThatBool([[MSAICrashManager sharedManager].plCrashReporter hasPendingCrashReport], isTrue());
[[MSAICrashManager sharedManager] readCrashReportAndStartProcessing];
// we should have 0 pending crash report
assertThatBool([[MSAICrashManager sharedManager].plCrashReporter hasPendingCrashReport], isFalse());
// handle a new signal crash report
assertThatBool([MSAITestHelper copyFixtureCrashReportWithFileName:@"live_report_signal"], isTrue());
// we should have now 1 pending crash report
assertThatBool([[MSAICrashManager sharedManager].plCrashReporter hasPendingCrashReport], isTrue());
[[MSAICrashManager sharedManager] readCrashReportAndStartProcessing];
// handle a new signal crash report
assertThatBool([MSAITestHelper copyFixtureCrashReportWithFileName:@"live_report_exception"], isTrue());
// we should have now 1 pending crash report
assertThatBool([[MSAICrashManager sharedManager].plCrashReporter hasPendingCrashReport], isTrue());
[[MSAICrashManager sharedManager] readCrashReportAndStartProcessing];
}
@end
#endif

Просмотреть файл

@ -15,8 +15,6 @@
#import "MSAIApplication.h"
#import "MSAIEventData.h"
#import "MSAIData.h"
#import <CrashReporter/CrashReporter.h>
#import <pthread.h>
@interface MSAIEnvelopeManagerTests : XCTestCase
@ -74,21 +72,6 @@
assertThat(data.baseType, equalTo(@"EventData"));
}
- (void)testThatItInstantiatesEnvelopeForCrash {
PLCrashReporterSignalHandlerType signalHandlerType = PLCrashReporterSignalHandlerTypeBSD;
PLCrashReporterSymbolicationStrategy symbolicationStrategy = PLCrashReporterSymbolicationStrategyAll;
MSAIPLCrashReporterConfig *config = [[MSAIPLCrashReporterConfig alloc] initWithSignalHandlerType: signalHandlerType
symbolicationStrategy: symbolicationStrategy];
MSAIPLCrashReporter *cm = [[MSAIPLCrashReporter alloc] initWithConfiguration:config];
NSData *data = [cm generateLiveReportWithThread:pthread_mach_thread_np(pthread_self())];
MSAIPLCrashReport *report = [[MSAIPLCrashReport alloc] initWithData:data error:nil];
MSAIEnvelope *envelope = [_sut envelopeForCrashReport:report];
[self checkEnvelopeTemplate:envelope];
assertThat(envelope.data, notNilValue());
assertThat(envelope.name, equalTo(@"Microsoft.ApplicationInsights.Crash"));
}
#pragma mark - Helper
- (void)checkEnvelopeTemplate:(MSAIEnvelope *)template{

Просмотреть файл

@ -1,91 +0,0 @@
#import <XCTest/XCTest.h>
#import "MSAIExceptionData.h"
#import "MSAIExceptionDetails.h"
#import "MSAIOrderedDictionary.h"
@interface MSAIExceptionDataTests : XCTestCase
@end
@implementation MSAIExceptionDataTests
- (void)testverPropertyWorksAsExpected {
NSNumber *expected;
expected = @42;
MSAIExceptionData *item = [MSAIExceptionData new];
item.version = expected;
NSNumber *actual = item.version;
XCTAssertTrue([actual isEqual:expected]);
expected = @13;
item.version = expected;
actual = item.version;
XCTAssertTrue([actual isEqual:expected]);
}
- (void)testhandled_atPropertyWorksAsExpected {
NSString *expected = @"Test string";
MSAIExceptionData *item = [MSAIExceptionData new];
item.handledAt = expected;
NSString *actual = item.handledAt;
XCTAssertTrue([actual isEqualToString:expected]);
expected = @"Other string";
item.handledAt = expected;
actual = item.handledAt;
XCTAssertTrue([actual isEqualToString:expected]);
}
- (void)testExceptionsPropertyWorksAsExpected {
MSAIExceptionData *item = [MSAIExceptionData new];
NSMutableArray *actual = (NSMutableArray *)item.exceptions;
XCTAssertNotNil(actual, @"Pass");
}
- (void)testseverity_levelPropertyWorksAsExpected {
MSAISeverityLevel expected = 5;
MSAIExceptionData *item = [MSAIExceptionData new];
item.severityLevel = expected;
MSAISeverityLevel actual = item.severityLevel;
XCTAssertTrue(actual == expected);
expected = 3;
item.severityLevel = expected;
actual = item.severityLevel;
XCTAssertTrue(actual == expected);
}
- (void)testPropertiesPropertyWorksAsExpected {
MSAIExceptionData *item = [MSAIExceptionData new];
MSAIOrderedDictionary *actual = (MSAIOrderedDictionary *)item.properties;
XCTAssertNotNil(actual, @"Pass");
}
- (void)testMeasurementsPropertyWorksAsExpected {
MSAIExceptionData *item = [MSAIExceptionData new];
MSAIOrderedDictionary *actual = (MSAIOrderedDictionary *)item.measurements;
XCTAssertNotNil(actual, @"Pass");
}
- (void)testSerialize {
MSAIExceptionData *item = [MSAIExceptionData new];
item.version = @42;
item.handledAt = @"Test string";
item.problemId = @"Test Id";
item.crashThreadId = @23;
NSArray *arrexceptions = @[[MSAIExceptionDetails new]];
for (MSAIExceptionDetails *arrItem in arrexceptions) {
[item.exceptions addObject:arrItem];
}
item.severityLevel = 5;
item.properties = [MSAIOrderedDictionary dictionaryWithObjectsAndKeys: @"test value 1", @"key1", @"test value 2", @"key2", nil];
MSAIOrderedDictionary *dictmeasurements = [MSAIOrderedDictionary dictionaryWithObjectsAndKeys:@3.1415, @"key1", @42.2, @"key2", nil];
for (id key in dictmeasurements) {
[item.measurements setObject:[dictmeasurements objectForKey:key] forKey:key];
}
NSString *actual = [item serializeToString];
NSString *expected = @"{\"ver\":42,\"handledAt\":\"Test string\",\"problemId\":\"Test Id\",\"crashThreadId\":23,\"exceptions\":[{\"hasFullStack\":true,\"parsedStack\":[]}],\"severityLevel\":5,\"properties\":{\"key1\":\"test value 1\",\"key2\":\"test value 2\"},\"measurements\":{\"key1\":3.1415,\"key2\":42.2}}";
XCTAssertTrue([actual isEqualToString:expected]);
}
@end

Просмотреть файл

@ -1,113 +0,0 @@
#import <XCTest/XCTest.h>
#import "MSAIExceptionDetails.h"
#import "MSAIStackFrame.h"
@interface MSAIExceptionDetailsTests : XCTestCase
@end
@implementation MSAIExceptionDetailsTests
- (void)testidPropertyWorksAsExpected {
NSNumber *expected;
expected = @42;
MSAIExceptionDetails *item = [MSAIExceptionDetails new];
item.exceptionDetailsId = expected;
NSNumber *actual = item.exceptionDetailsId;
XCTAssertTrue([actual isEqual:expected]);
expected = @13;
item.exceptionDetailsId = expected;
actual = item.exceptionDetailsId;
XCTAssertTrue([actual isEqual:expected]);
}
- (void)testouter_idPropertyWorksAsExpected {
NSNumber *expected = @42;
MSAIExceptionDetails *item = [MSAIExceptionDetails new];
item.outerId = expected;
NSNumber *actual = item.outerId;
XCTAssertTrue([actual isEqual:expected]);
expected = @13;
item.outerId = expected;
actual = item.outerId;
XCTAssertTrue([actual isEqual:expected]);
}
- (void)testtype_namePropertyWorksAsExpected {
NSString *expected = @"Test string";
MSAIExceptionDetails *item = [MSAIExceptionDetails new];
item.typeName = expected;
NSString *actual = item.typeName;
XCTAssertTrue([actual isEqualToString:expected]);
expected = @"Other string";
item.typeName = expected;
actual = item.typeName;
XCTAssertTrue([actual isEqualToString:expected]);
}
- (void)testmessagePropertyWorksAsExpected {
NSString *expected = @"Test string";
MSAIExceptionDetails *item = [MSAIExceptionDetails new];
item.message = expected;
NSString *actual = item.message;
XCTAssertTrue([actual isEqualToString:expected]);
expected = @"Other string";
item.message = expected;
actual = item.message;
XCTAssertTrue([actual isEqualToString:expected]);
}
- (void)testhas_full_stackPropertyWorksAsExpected {
BOOL expected = YES;
MSAIExceptionDetails *item = [MSAIExceptionDetails new];
item.hasFullStack = expected;
BOOL actual = item.hasFullStack;
XCTAssertTrue(actual == expected);
expected = NO;
item.hasFullStack = expected;
actual = item.hasFullStack;
XCTAssertTrue(actual == expected);
}
- (void)teststackPropertyWorksAsExpected {
NSString *expected = @"Test string";
MSAIExceptionDetails *item = [MSAIExceptionDetails new];
item.stack = expected;
NSString *actual = item.stack;
XCTAssertTrue([actual isEqualToString:expected]);
expected = @"Other string";
item.stack = expected;
actual = item.stack;
XCTAssertTrue([actual isEqualToString:expected]);
}
- (void)testParsed_stackPropertyWorksAsExpected {
MSAIExceptionDetails *item = [MSAIExceptionDetails new];
NSMutableArray *actual = (NSMutableArray *)item.parsedStack;
XCTAssertNotNil(actual, @"Pass");
}
- (void)testSerialize {
MSAIExceptionDetails *item = [MSAIExceptionDetails new];
item.exceptionDetailsId = @42;
item.outerId = @42;
item.typeName = @"Test string";
item.message = @"Test string";
item.hasFullStack = YES;
item.stack = @"Test string";
NSArray *arrparsedStack = @[[MSAIStackFrame new]];
for (MSAIStackFrame *arrItem in arrparsedStack) {
[item.parsedStack addObject:arrItem];
}
NSString *actual = [item serializeToString];
NSString *expected = @"{\"id\":42,\"outerId\":42,\"typeName\":\"Test string\",\"message\":\"Test string\",\"hasFullStack\":true,\"stack\":\"Test string\",\"parsedStack\":[{}]}";
XCTAssertTrue([actual isEqualToString:expected]);
}
@end

Просмотреть файл

@ -155,24 +155,10 @@ typedef void (^MSAIPersistenceTestBlock)(BOOL);
for (int i = 0; i < 1000; ++i) {
[_sut folderPathForPersistenceType:MSAIPersistenceTypeRegular];
}
for (int i = 0; i < 1000; ++i) {
[_sut folderPathForPersistenceType:MSAIPersistenceTypeCrashTemplate];
}
}];
}
#endif
- (void)testOverwriteCrashTemplateWorks {
// Create first crash template
[self createFileForDict:@{} withType:MSAIPersistenceTypeCrashTemplate];
XCTAssertEqual([self fileCountForType:MSAIPersistenceTypeCrashTemplate], 1U);
// Create a new crash template, which should overwrite the first one
[self createFileForDict:@{} withType:MSAIPersistenceTypeCrashTemplate];
XCTAssertEqual([self fileCountForType:MSAIPersistenceTypeCrashTemplate], 1U);
}
#pragma mark - Helper
- (NSData *)jsonDataFromArray:(NSArray *)array {

Просмотреть файл

@ -1,88 +0,0 @@
#import <XCTest/XCTest.h>
#import "MSAIStackFrame.h"
@interface MSAIStackFrameTests : XCTestCase
@end
@implementation MSAIStackFrameTests
- (void)testlevelPropertyWorksAsExpected {
NSNumber *expected;
expected = @42;
MSAIStackFrame *item = [MSAIStackFrame new];
item.level = expected;
NSNumber *actual = item.level;
XCTAssertTrue([actual isEqual:expected]);
expected = @13;
item.level = expected;
actual = item.level;
XCTAssertTrue([actual isEqual:expected]);
}
- (void)testmethodPropertyWorksAsExpected {
NSString *expected = @"Test string";
MSAIStackFrame *item = [MSAIStackFrame new];
item.method = expected;
NSString *actual = item.method;
XCTAssertTrue([actual isEqualToString:expected]);
expected = @"Other string";
item.method = expected;
actual = item.method;
XCTAssertTrue([actual isEqualToString:expected]);
}
- (void)testassemblyPropertyWorksAsExpected {
NSString *expected = @"Test string";
MSAIStackFrame *item = [MSAIStackFrame new];
item.assembly = expected;
NSString *actual = item.assembly;
XCTAssertTrue([actual isEqualToString:expected]);
expected = @"Other string";
item.assembly = expected;
actual = item.assembly;
XCTAssertTrue([actual isEqualToString:expected]);
}
- (void)testfile_namePropertyWorksAsExpected {
NSString *expected = @"Test string";
MSAIStackFrame *item = [MSAIStackFrame new];
item.fileName = expected;
NSString *actual = item.fileName;
XCTAssertTrue([actual isEqualToString:expected]);
expected = @"Other string";
item.fileName = expected;
actual = item.fileName;
XCTAssertTrue([actual isEqualToString:expected]);
}
- (void)testlinePropertyWorksAsExpected {
NSNumber *expected = @42;
MSAIStackFrame *item = [MSAIStackFrame new];
item.line = expected;
NSNumber *actual = item.line;
XCTAssertTrue([actual isEqual:expected]);
expected = @13;
item.line = expected;
actual = item.line;
XCTAssertTrue([actual isEqual:expected]);
}
- (void)testSerialize {
MSAIStackFrame *item = [MSAIStackFrame new];
item.level = @42;
item.method = @"Test string";
item.assembly = @"Test string";
item.fileName = @"Test string";
item.line = @42;
NSString *actual = [item serializeToString];
NSString *expected = @"{\"level\":42,\"method\":\"Test string\",\"assembly\":\"Test string\",\"fileName\":\"Test string\",\"line\":42}";
XCTAssertTrue([actual isEqualToString:expected]);
}
@end

Просмотреть файл

@ -65,6 +65,21 @@
XCTAssertFalse(self.sut.managerInitialised);
}
- (void)testDurationStringFromDuration {
NSTimeInterval testInterval = 1234567.0987654;
NSString *durationString = [self.sut durationStringFromDuration:testInterval];
XCTAssertEqualObjects(durationString, @"14:06:56:07.0987654");
NSTimeInterval testInterval2 = 5.65;
NSString *durationString2 = [self.sut durationStringFromDuration:testInterval2];
XCTAssertEqualObjects(durationString2, @"0:00:00:05.6500000");
}
- (void)testRegisterObservers {
// Instance already gets registered in init(). We have to unregister again, since we can't register twice.
[self.sut unregisterObservers];

Просмотреть файл

@ -1,3 +1,5 @@
#import <UIKit/UIkit.h>
NS_ASSUME_NONNULL_BEGIN
extern NSString *const kMSAIDummyInstrumentationKey;
@ -6,7 +8,6 @@ extern NSString *const kMSAIDummyInstrumentationKey;
+ (NSString *)jsonFixture:(NSString *)fixture;
+ (BOOL)createTempDirectory:(NSString *)directory;
+ (BOOL)copyFixtureCrashReportWithFileName:(NSString *)filename;
@end
NS_ASSUME_NONNULL_END

Просмотреть файл

@ -32,38 +32,4 @@ NSString *const kMSAIDummyInstrumentationKey = @"aaaaaaa-bbbb-cccc-dddd-01234567
return YES;
}
+ (BOOL)copyFixtureCrashReportWithFileName:(NSString *)filename {
NSFileManager *fm = [[NSFileManager alloc] init];
// the bundle identifier when running with unit tets is "otest"
const char *progname = getprogname();
if (progname == NULL) {
return NO;
}
NSString *bundleIdentifierPathString = [NSString stringWithUTF8String: progname];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
// create the PLCR cache dir
NSString *plcrRootCrashesDir = [paths[0] stringByAppendingPathComponent:@"com.plausiblelabs.crashreporter.data"];
if (![MSAITestHelper createTempDirectory:plcrRootCrashesDir])
return NO;
NSString *plcrCrashesDir = [plcrRootCrashesDir stringByAppendingPathComponent:bundleIdentifierPathString];
if (![MSAITestHelper createTempDirectory:plcrCrashesDir])
return NO;
NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:filename ofType:@"plcrash"];
NSError *theError = NULL;
[fm copyItemAtPath:filePath toPath:[plcrCrashesDir stringByAppendingPathComponent:@"live_report.plcrash"] error:&theError];
if (theError)
return NO;
else
return YES;
}
@end

Просмотреть файл

@ -1,9 +1,11 @@
#include "ApplicationInsights.xcconfig"
BUILD_NUMBER = 9
VERSION_STRING = 1.0-beta.6
BUILD_NUMBER = 10
VERSION_STRING = 1.0-beta.7
GCC_PREPROCESSOR_DEFINITIONS = MSAI_VERSION="@\""$(VERSION_STRING)"\"" MSAI_BUILD="@\""$(BUILD_NUMBER)"\"" MSAI_C_VERSION="\""$(VERSION_STRING)"\"" MSAI_C_BUILD="\""$(BUILD_NUMBER)"\"" $(XCODEBUILD_GCC_PREPROCESSOR_DEFINITIONS)
MSAI_ARM_ARCHS = armv7 armv7s arm64
MSAI_SIM_ARCHS = x86_64 i386
ARCHS = $(MSAI_ARM_ARCHS)
VALID_ARCHS = $(MSAI_ARM_ARCHS)
OTHER_CFLAGS[sdk=iphoneos9.*] = $(HOCKEYSDK_WARNING_FLAGS) -fembed-bitcode
OTHER_CFLAGS[sdk=iphonesimulator9.*] = $(HOCKEYSDK_WARNING_FLAGS) -fembed-bitcode-marker

1
Support/release.xcconfig Normal file
Просмотреть файл

@ -0,0 +1 @@
#include "buildnumber.xcconfig"

Просмотреть файл

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

1
Vendor/CrashReporter.framework/Headers поставляемый
Просмотреть файл

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

1
Vendor/CrashReporter.framework/Resources поставляемый
Просмотреть файл

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

Двоичные данные
Vendor/CrashReporter.framework/Versions/A/CrashReporter поставляемый

Двоичный файл не отображается.

Просмотреть файл

@ -1,363 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausiblelabs.com>
*
* Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#ifdef __APPLE__
#import <AvailabilityMacros.h>
#endif
// This must be included before any other PLCrashReporter includes, as
// it redefines symbol names
#import "PLCrashNamespace.h"
#import "PLCrashReporter.h"
#import "PLCrashReport.h"
#import "PLCrashReportTextFormatter.h"
/**
* @defgroup functions Crash Reporter Functions Reference
*/
/**
* @defgroup types Crash Reporter Data Types Reference
*/
/**
* @defgroup constants Crash Reporter Constants Reference
*/
/**
* @internal
* @defgroup plcrash_internal Crash Reporter Internal Documentation
*/
/**
* @defgroup enums Enumerations
* @ingroup constants
*/
/**
* @defgroup globals Global Variables
* @ingroup constants
*/
/**
* @defgroup exceptions Exceptions
* @ingroup constants
*/
/* Exceptions */
extern NSString *PLCrashReporterException;
/* Error Domain and Codes */
extern NSString *PLCrashReporterErrorDomain;
/**
* NSError codes in the Plausible Crash Reporter error domain.
* @ingroup enums
*/
typedef enum {
/** An unknown error has occured. If this
* code is received, it is a bug, and should be reported. */
PLCrashReporterErrorUnknown = 0,
/** An Mach or POSIX operating system error has occured. The underlying NSError cause may be fetched from the userInfo
* dictionary using the NSUnderlyingErrorKey key. */
PLCrashReporterErrorOperatingSystem = 1,
/** The crash report log file is corrupt or invalid */
PLCrashReporterErrorCrashReportInvalid = 2,
/** An attempt to use a resource which was in use at the time in a manner which would have conflicted with the request. */
PLCrashReporterErrorResourceBusy = 3
} PLCrashReporterError;
/* Library Imports */
#import "PLCrashReporter.h"
#import "PLCrashReport.h"
#import "PLCrashReportTextFormatter.h"
/**
* @mainpage Plausible Crash Reporter
*
* @section intro_sec Introduction
*
* Plausile CrashReporter implements in-process crash reporting on the iPhone and Mac OS X.
*
* The following features are supported:
*
* - Implemented as an in-process signal handler.
* - Does not interfer with debugging in gdb..
* - Handles both uncaught Objective-C exceptions and fatal signals (SIGSEGV, SIGBUS, etc).
* - Full thread state for all active threads (backtraces, register dumps) is provided.
*
* If your application crashes, a crash report will be written. When the application is next run, you may check for a
* pending crash report, and submit the report to your own HTTP server, send an e-mail, or even introspect the
* report locally.
*
* @section intro_encoding Crash Report Format
*
* Crash logs are encoded using <a href="http://code.google.com/p/protobuf/">google protobuf</a>, and may be decoded
* using the provided PLCrashReport API. Additionally, the include plcrashutil handles conversion of binary crash reports to the
* symbolicate-compatible iPhone text format.
*
* @section doc_sections Documentation Sections
* - @subpage example_usage_iphone
* - @subpage error_handling
* - @subpage async_safety
*/
/**
* @page example_usage_iphone Example iPhone Usage
*
* @code
* //
* // Called to handle a pending crash report.
* //
* - (void) handleCrashReport {
* PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter];
* NSData *crashData;
* NSError *error;
*
* // Try loading the crash report
* crashData = [crashReporter loadPendingCrashReportDataAndReturnError: &error];
* if (crashData == nil) {
* NSLog(@"Could not load crash report: %@", error);
* goto finish;
* }
*
* // We could send the report from here, but we'll just print out
* // some debugging info instead
* PLCrashReport *report = [[[PLCrashReport alloc] initWithData: crashData error: &error] autorelease];
* if (report == nil) {
* NSLog(@"Could not parse crash report");
* goto finish;
* }
*
* NSLog(@"Crashed on %@", report.systemInfo.timestamp);
* NSLog(@"Crashed with signal %@ (code %@, address=0x%" PRIx64 ")", report.signalInfo.name,
* report.signalInfo.code, report.signalInfo.address);
*
* // Purge the report
* finish:
* [crashReporter purgePendingCrashReport];
* return;
* }
*
* // from UIApplicationDelegate protocol
* - (void) applicationDidFinishLaunching: (UIApplication *) application {
* PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter];
* NSError *error;
*
* // Check if we previously crashed
* if ([crashReporter hasPendingCrashReport])
* [self handleCrashReport];
* // Enable the Crash Reporter
* if (![crashReporter enableCrashReporterAndReturnError: &error])
* NSLog(@"Warning: Could not enable crash reporter: %@", error);
*
* }
* @endcode
*
*/
/**
* @page error_handling Error Handling Programming Guide
*
* Where a method may return an error, Plausible Crash Reporter provides access to the underlying
* cause via an optional NSError argument.
*
* All returned errors will be a member of one of the below defined domains, however, new domains and
* error codes may be added at any time. If you do not wish to report on the error cause, many methods
* support a simple form that requires no NSError argument.
*
* @section error_domains Error Domains, Codes, and User Info
*
* @subsection crashreporter_errors Crash Reporter Errors
*
* Any errors in Plausible Crash Reporter use the #PLCrashReporterErrorDomain error domain, and and one
* of the error codes defined in #PLCrashReporterError.
*/
/**
* @page async_safety Async-Safe Programming Guide
*
* Plausible CrashReporter provides support for executing an application specified function in the context of the
* crash reporter's signal handler, after the crash report has been written to disk. This was a regularly requested
* feature, and provides the ability to implement application finalization in the event of a crash. However, writing
* code intended for execution inside of a signal handler is exceptionally difficult, and is not recommended.
*
* @section program_flow Program Flow and Signal Handlers
*
* When the signal handler is called the normal flow of the program is interrupted, and your program is an unknown
* state. Locks may be held, the heap may be corrupt (or in the process of being updated), and your signal
* handler may invoke a function that was being executed at the time of the signal. This may result in deadlocks,
* data corruption, and program termination.
*
* @section functions Async-Safe Functions
*
* A subset of functions are defined to be async-safe by the OS, and are safely callable from within a signal handler. If
* you do implement a custom post-crash handler, it must be async-safe. A table of POSIX-defined async-safe functions
* and additional information is available from the
* <a href="https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers">CERT programming guide - SIG30-C</a>
*
* Most notably, the Objective-C runtime itself is not async-safe, and Objective-C may not be used within a signal
* handler.
*
* @sa PLCrashReporter::setCrashCallbacks:
*/
/**
* @page mach_exceptions Mach Exceptions on Mac OS X and iOS
*
* PLCrashReporter includes support for monitoring crashes via an in-process Mach exception handler. There are a small
* number of crash cases that will not be caught with via a POSIX signal handler, but can be caught via a Mach
* exception handler:
*
* - Stack overflow. sigaltstack() is broken in later iOS releases, and even if functional, must be configured
* on a per-thread basis.
* - Internal Apple assertions that call libSystem's __assert. These include compiler-checked constraints
* for built-in functions, such as strcpy_chk(). The __abort() implementation actually disables the SIGABRT
* signal handler (resetting it to SIG_DFL) prior to to issueing a SIGABRT, bypassing signal-based crash
* reporters entirely.
*
* Unfortunately, the latter issue (__assert) can not be handled on iOS; trapping abort requires that
* a Mach exception handler operate out-of-process, which is impossible on iOS. On Mac OS X, this will
* only be handled once we've implemented fully out-of-process crash excution.
*
* On Mac OS X, the Mach exception implementation is fully supported using entirely public API. On iOS,
* the APIs required are not fully public -- more details on the implications of this for exception handling on
* iOS may be found in @ref mach_exceptions_ios below. It is worth noting that even where the Mach exception APIs
* are fully supported, kernel-internal constants, as well
* as architecture-specific trap information, may be required to fully interpret a Mach exception's root cause.
*
* For example, the EXC_SOFTWARE exception is dispatched for four different failure types, using the exception
* code to differentiate failure types:
* - Non-existent system call invoked (SIGSYS)
* - Write on a pipe with no reader (SIGPIPE)
* - Abort program (SIGABRT -- unused)
* - Kill program (SIGKILL)
*
* Of those four types, only the constant required to interpret the SIGKILL behavior (EXC_SOFT_SIGNAL) is publicly defined.
* Of the remaining three failure types, the constant values are kernel implementation-private, defined only in the available
* kernel sources. On iOS, these sources are unavailable, and while they generally do match the Mac OS X implementation, there
* are no gaurantees that this is -- or will remain -- the case in the future.
*
* Likewise, interpretation of particular fault types requires information regarding the underlying machine traps
* that triggered the Mach exceptions. For example, a floating point trap on x86/x86-64 will trigger an EXC_ARITHMETIC,
* with a subcode value containing the value of the FPU status register. Determining the exact FPU cause requires
* extracting the actual exception flags from status register as per the x86 architecture documentation. The exact format
* of this subcode value is not actually documented outside the kernel, and may change in future releases.
*
* While we have the advantage of access to the x86 kernel sources, the situation on ARM is even less clear. The actual
* use of the Mach exception codes and subcodes is largely undefined by both headers and publicly available documentation,
* and the available x86 kernel sources are of little use in interpreting this data.
*
* As such, while Mach exceptions may catch some cases that BSD signals can not, they are not a perfect solution,
* and may also provide less insight into the actual failures that occur. By comparison, the BSD signal interface
* is both fully defined and architecture independent, with any necessary interpretation of the Mach exception
* codes handled in-kernel at the time of exception dispatch. It is generally recommended by Apple as the preferred
* interface, and should generally be preferred by PLCrashReporter API clients.
*
* @section mach_exceptions_compatibility Compatibility Issues
*
* @subsection Debuggers
*
* Enabling in-process Mach exception handlers will conflict with any attached debuggers; the debugger
* may suspend the processes Mach exception handling thread, which will result in any exception messages
* sent via the debugger being lost, as the in-process handler will be unable to receive and forward
* the messages.
*
* @subsection Managed Runtimes (Xamarin, Unity)
*
* A Mach exception handler may conflict with any managed runtime that registers a BSD signal handler that
* can safely handle otherwise fatal signals, allowing execution to proceed. This includes products
* such as Xamarin for iOS.
*
* In such a case, PLCrashReporter will write a crash report for non-fatal signals, as there is no
* immediate mechanism for determining whether a signal handler exists and that it can safely
* handle the failure. This can result in unexpected delays in application execution, increased I/O to
* disk, and other undesirable operations.
*
* @section mach_exceptions_ios Mach Exceptions on iOS
*
* The APIs required for Mach exception handling are not fully public on iOS. After filing a request with
* Apple DTS to clarify the status of the Mach exception APIs on iOS, and implementing a Mach Exception
* handler using only supported API, they provided the following guidance:
*
* <em>Our engineers have reviewed your request and have determined that this would be best handled as a bug report,
* which you have already filed. There is no documented way of accomplishing this, nor is there a workaround
* possible.</em>
*
* Due to user request, PLCrashReporter provides an optional implementation of Mach exception handling for both
* iOS and Mac OS X.
*
* This implementation uses only supported API on Mac OS X, and depends on limited undefined API on iOS. The reporter
* may be excluded entirely at build time by modifying the PLCRASH_FEATURE_MACH_EXCEPTIONS build configuration; it
* may also be disabled at runtime by configuring the PLCrashReporter instance appropriately via PLCrashReporterConfig.
*
* The iOS implementation is implemented almost entirely using public API, and links against no actual private symbols;
* the use of undocumented functionality is limited to assuming the use of specific msgh_id values (see below
* for details). As a result, it may be considered perfectly safe to include the Mach Exception code in the
* standard build, and enable/disable it at runtime.
*
* The following issues exist in the iOS implementation:
* - The msgh_id values required for an exception reply message are not available from the available
* headers and must be hard-coded. This prevents one from safely replying to exception messages, which
* means that it is impossible to (correctly) inform the server that an exception has *not* been
* handled.
*
* Impact:
* This can lead to the process locking up and not dispatching to the host exception handler (eg, Apple's
* crash reporter), depending on the behavior of the kernel exception code.
*
* - The mach_* structure/type variants required by MACH_EXCEPTION_CODES are not publicly defined (on Mac OS X,
* these are provided by mach_exc.defs). This prevents one from forwarding exception messages to an existing
* handler that was registered with a MACH_EXCEPTION_CODES behavior (eg, forwarding is entirely non-functional
* on ARM64 devices).
*
* Impact:
* This can break forwarding to any task exception handler that registers itself with MACH_EXCEPTION_CODES,
* including other handlers registered within the current process, eg, by a managed runtime. This could
* also result in misinterpretation of a Mach exception message, in the case where the message format is
* modified by Apple to be incompatible with the existing 32-bit format.
*
* This is the case with LLDB; it will register a task exception handler with MACH_EXCEPTION_CODES set. Failure
* to correctly forward these exceptions will result in the debugger breaking in interesting ways; for example,
* changes to the set of dyld-loaded images are detected by setting a breakpoint on the dyld image registration
* funtions, and this functionality will break if the exception is not correctly forwarded.
*
* Since Mach exception handling is important for a fully functional crash reporter, we have also filed a radar
* to request that the API be made public:
* Radar: rdar://12939497 RFE: Provide mach_exc.defs for iOS
*
* At the time of this writing, the radar remains open/unresolved.
*/

Просмотреть файл

@ -1,58 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausiblelabs.com>
*
* Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PLCRASH_ASYNC_SIGNAL_INFO_H
#define PLCRASH_ASYNC_SIGNAL_INFO_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @internal
*
* @defgroup plcrash_async_signal_info Signal Information
* @ingroup plcrash_async
*
* Provides mapping of signal number and code to strings.
*
* @{
*/
const char *plcrash_async_signal_signame (int signal);
const char *plcrash_async_signal_sigcode (int signal, int si_code);
/**
* @} plcrash_async_signal_info
*/
#ifdef __cplusplus
}
#endif
#endif /* PLCRASH_ASYNC_SIGNAL_INFO_H */

Просмотреть файл

@ -1,104 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausible.coop>
*
* Copyright (c) 2012-2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PLCRASH_FEATURE_CONFIG_H
#define PLCRASH_FEATURE_CONFIG_H
#include <TargetConditionals.h>
/**
* @internal
*
* Build-time configuration for PLCrashReporter.
*
* This is used to automatically enable/disable features on a per-platform and per-configuration
* basis; it may also be used by third-party vendors to configure a custom build of PLCrashReporter.
*
* @defgroup build_config Build Configuration
* @ingroup constants
* @{
*/
/*
* Defaults
*/
/*
* For release builds, disable unused unwind implementations on targets that do not use them. For non-release
* builds, we include the unwind implementations to allow testing on a broader range of targets.
*/
#ifdef PLCF_RELEASE_BUILD
# if defined(__arm__)
# ifndef PLCRASH_FEATURE_UNWIND_DWARF
# define PLCRASH_FEATURE_UNWIND_DWARF 0
# endif
# ifndef PLCRASH_FEATURE_UNWIND_COMPACT
# define PLCRASH_FEATURE_UNWIND_COMPACT 0
# endif
# endif
#endif
/*
* Configuration Flags
*/
#ifndef PLCRASH_FEATURE_MACH_EXCEPTIONS
/**
* If true, enable Mach exception support. On Mac OS X, the Mach exception implementation is fully supported,
* using publicly available API. On iOS, the APIs required for a complete implementation are not public. However, a
* popular commercial crash reporter is now shipping with support for Mach exceptions, which implies that either
* they've received special dispensation to use private APIs / private structures, they've found another way to do
* it, or they're just using undocumented functionality and hoping for the best.
*
* The exposed surface of undocumented API usage is relatively low, and there has been strong user demand to
* implement Mach exception handling regardless of concerns over API visiblity. Given this, we've enabled
* Mach exception handling by default, and provided both build-time and runtime configuration
* to disable its use.
*
* For more information on the potential issues with enabling mach exception support, @sa @ref mach_exceptions.
*/
# define PLCRASH_FEATURE_MACH_EXCEPTIONS 1
#endif
#ifndef PLCRASH_FEATURE_UNWIND_DWARF
/** If true, enable DWARF unwinding support. */
# define PLCRASH_FEATURE_UNWIND_DWARF 1
#endif
#ifndef PLCRASH_FEATURE_UNWIND_COMPACT
/** If true, enable compact unwinding support. */
# define PLCRASH_FEATURE_UNWIND_COMPACT 1
#endif
/**
* @}
*/
#endif /* PLCRASH_FEATURE_CONFIG_H */

Просмотреть файл

@ -1,48 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausiblelabs.com>
*
* Copyright (c) 2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PLCRASH_CONSTANTS_H
#define PLCRASH_CONSTANTS_H
#if defined(__cplusplus)
# define PLCR_EXPORT extern "C"
# define PLCR_C_BEGIN_DECLS extern "C" {
# define PLCR_C_END_DECLS }
#else
# define PLCR_EXPORT extern
# define PLCR_C_BEGIN_DECLS
# define PLCR_C_END_DECLS
#endif
#ifdef __clang__
# define PLCR_PRAGMA_CLANG(_p) _Pragma(_p)
#else
# define PLCR_PRAGMA_CLANG(_p)
#endif
#endif /* PLCRASH_CONSTANTS_H */

Просмотреть файл

@ -1,80 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausible.coop>
*
* Copyright (c) 2012-2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* For external library integrators:
*
* Set this value to any valid C symbol prefix. This will automatically
* prepend the given prefix to all external symbols in the library.
*
* This may be used to avoid symbol conflicts between multiple libraries
* that may both incorporate PLCrashReporter.
*/
#define PLCRASHREPORTER_PREFIX MSAI
#ifdef PLCRASHREPORTER_PREFIX
// We need two extra layers of indirection to make CPP substitute
// the PLCRASHREPORTER_PREFIX define.
#define PLNS_impl2(prefix, symbol) prefix ## symbol
#define PLNS_impl(prefix, symbol) PLNS_impl2(prefix, symbol)
#define PLNS(symbol) PLNS_impl(PLCRASHREPORTER_PREFIX, symbol)
#define PLCrashMachExceptionServer PLNS(PLCrashMachExceptionServer)
#define PLCrashReport PLNS(PLCrashReport)
#define PLCrashReportApplicationInfo PLNS(PLCrashReportApplicationInfo)
#define PLCrashReportBinaryImageInfo PLNS(PLCrashReportBinaryImageInfo)
#define PLCrashReportExceptionInfo PLNS(PLCrashReportExceptionInfo)
#define PLCrashReportMachExceptionInfo PLNS(PLCrashReportMachExceptionInfo)
#define PLCrashReportMachineInfo PLNS(PLCrashReportMachineInfo)
#define PLCrashReportProcessInfo PLNS(PLCrashReportProcessInfo)
#define PLCrashReportProcessorInfo PLNS(PLCrashReportProcessorInfo)
#define PLCrashReportRegisterInfo PLNS(PLCrashReportRegisterInfo)
#define PLCrashReportSignalInfo PLNS(PLCrashReportSignalInfo)
#define PLCrashReportStackFrameInfo PLNS(PLCrashReportStackFrameInfo)
#define PLCrashReportSymbolInfo PLNS(PLCrashReportSymbolInfo)
#define PLCrashReportSystemInfo PLNS(PLCrashReportSystemInfo)
#define PLCrashReportTextFormatter PLNS(PLCrashReportTextFormatter)
#define PLCrashReportThreadInfo PLNS(PLCrashReportThreadInfo)
#define PLCrashReporter PLNS(PLCrashReporter)
#define PLCrashSignalHandler PLNS(PLCrashSignalHandler)
#define PLCrashReportHostArchitecture PLNS(PLCrashReportHostArchitecture)
#define PLCrashReportHostOperatingSystem PLNS(PLCrashReportHostOperatingSystem)
#define PLCrashReporterErrorDomain PLNS(PLCrashReporterErrorDomain)
#define PLCrashReporterException PLNS(PLCrashReporterException)
#define PLCrashHostInfo PLNS(PLCrashHostInfo)
#define PLCrashMachExceptionPort PLNS(PLCrashMachExceptionPort)
#define PLCrashMachExceptionPortSet PLNS(PLCrashMachExceptionPortSet)
#define PLCrashProcessInfo PLNS(PLCrashProcessInfo)
#define PLCrashReporterConfig PLNS(PLCrashReporterConfig)
#define PLCrashUncaughtExceptionHandler PLNS(PLCrashUncaughtExceptionHandler)
#define PLCrashMachExceptionForward PLNS(PLCrashMachExceptionForward)
#define PLCrashSignalHandlerForward PLNS(PLCrashSignalHandlerForward)
#define plcrash_signal_handler PLNS(plcrash_signal_handler)
#endif

Просмотреть файл

@ -1,200 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausiblelabs.com>
*
* Copyright (c) 2008-2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#import "PLCrashReportApplicationInfo.h"
#import "PLCrashReportBinaryImageInfo.h"
#import "PLCrashReportExceptionInfo.h"
#import "PLCrashReportMachineInfo.h"
#import "PLCrashReportMachExceptionInfo.h"
#import "PLCrashReportProcessInfo.h"
#import "PLCrashReportProcessorInfo.h"
#import "PLCrashReportRegisterInfo.h"
#import "PLCrashReportSignalInfo.h"
#import "PLCrashReportStackFrameInfo.h"
#import "PLCrashReportSymbolInfo.h"
#import "PLCrashReportSystemInfo.h"
#import "PLCrashReportThreadInfo.h"
/**
* @ingroup constants
* Crash file magic identifier */
#define PLCRASH_REPORT_FILE_MAGIC "plcrash"
/**
* @ingroup constants
* Crash format version byte identifier. Will not change outside of the introduction of
* an entirely new crash log format. */
#define PLCRASH_REPORT_FILE_VERSION 1
/**
* @ingroup types
* Crash log file header format.
*
* Crash log files start with 7 byte magic identifier (#PLCRASH_REPORT_FILE_MAGIC),
* followed by a single unsigned byte version number (#PLCRASH_REPORT_FILE_VERSION).
* The crash log message format itself is extensible, so this version number will only
* be incremented in the event of an incompatible encoding or format change.
*/
struct PLCrashReportFileHeader {
/** Crash log magic identifier, not NULL terminated */
const char magic[7];
/** Crash log encoding/format version */
const uint8_t version;
/** File data */
const uint8_t data[];
} __attribute__((packed));
/**
* @internal
* Private decoder instance variables (used to hide the underlying protobuf parser).
*/
typedef struct _PLCrashReportDecoder _PLCrashReportDecoder;
@interface PLCrashReport : NSObject {
@private
/** Private implementation variables (used to hide the underlying protobuf parser) */
_PLCrashReportDecoder *_decoder;
/** System info */
PLCrashReportSystemInfo *_systemInfo;
/** Machine info */
PLCrashReportMachineInfo *_machineInfo;
/** Application info */
PLCrashReportApplicationInfo *_applicationInfo;
/** Process info */
PLCrashReportProcessInfo *_processInfo;
/** Signal info */
PLCrashReportSignalInfo *_signalInfo;
/** Mach exception info */
PLCrashReportMachExceptionInfo *_machExceptionInfo;
/** Thread info (PLCrashReportThreadInfo instances) */
NSArray *_threads;
/** Binary images (PLCrashReportBinaryImageInfo instances */
NSArray *_images;
/** Exception information (may be nil) */
PLCrashReportExceptionInfo *_exceptionInfo;
/** Report UUID */
CFUUIDRef _uuid;
}
- (id) initWithData: (NSData *) encodedData error: (NSError **) outError;
- (PLCrashReportBinaryImageInfo *) imageForAddress: (uint64_t) address;
/**
* System information.
*/
@property(nonatomic, readonly) PLCrashReportSystemInfo *systemInfo;
/**
* YES if machine information is available.
*/
@property(nonatomic, readonly) BOOL hasMachineInfo;
/**
* Machine information. Only available in later (v1.1+) crash report format versions. If not available,
* will be nil.
*/
@property(nonatomic, readonly) PLCrashReportMachineInfo *machineInfo;
/**
* Application information.
*/
@property(nonatomic, readonly) PLCrashReportApplicationInfo *applicationInfo;
/**
* YES if process information is available.
*/
@property(nonatomic, readonly) BOOL hasProcessInfo;
/**
* Process information. Only available in later (v1.1+) crash report format versions. If not available,
* will be nil.
*/
@property(nonatomic, readonly) PLCrashReportProcessInfo *processInfo;
/**
* Signal information. This provides the signal and signal code of the fatal signal.
*/
@property(nonatomic, readonly) PLCrashReportSignalInfo *signalInfo;
/**
* Mach exception information, if available. This will only be included in the
* case that encoding crash reporter's exception-based reporting was enabled, and a Mach
* exception was caught.
*
* @warning If Mach exception information is available, the legacy signalInfo property will also be provided; this
* s required to maintain backwards compatibility with the established API. Note, however, that the signal info may be derived from the
* Mach exception info by the encoding crash reporter, and thus may not exactly match the kernel exception-to-signal
* mappings implemented in xnu. As such, when Mach exception info is available, its use should be preferred.
*/
@property(nonatomic, readonly) PLCrashReportMachExceptionInfo *machExceptionInfo;
/**
* Thread information. Returns a list of PLCrashReportThreadInfo instances.
*/
@property(nonatomic, readonly) NSArray *threads;
/**
* Binary image information. Returns a list of PLCrashReportBinaryImageInfo instances.
*/
@property(nonatomic, readonly) NSArray *images;
/**
* YES if exception information is available.
*/
@property(nonatomic, readonly) BOOL hasExceptionInfo;
/**
* Exception information. Only available if a crash was caused by an uncaught exception,
* otherwise nil.
*/
@property(nonatomic, readonly) PLCrashReportExceptionInfo *exceptionInfo;
/**
* A client-generated 16-byte UUID. May be used to filter duplicate reports submitted or generated
* by a single client. Only available in later (v1.2+) crash report format versions. If not available,
* will be NULL.
*/
@property(nonatomic, readonly) CFUUIDRef uuidRef;
@end

Просмотреть файл

@ -1,62 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausiblelabs.com>
*
* Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
@interface PLCrashReportApplicationInfo : NSObject {
@private
/** Application identifier */
NSString *_applicationIdentifier;
/** Application version */
NSString *_applicationVersion;
/** Application marketing version */
NSString *_applicationMarketingVersion;
}
- (id) initWithApplicationIdentifier: (NSString *) applicationIdentifier
applicationVersion: (NSString *) applicationVersion
applicationMarketingVersion: (NSString *) applicationMarketingVersion;
/**
* The application identifier. This is usually the application's CFBundleIdentifier value.
*/
@property(nonatomic, readonly) NSString *applicationIdentifier;
/**
* The application version. This is usually the application's CFBundleVersion value.
*/
@property(nonatomic, readonly) NSString *applicationVersion;
/**
* The application marketing version. This is usually the application's CFBundleShortVersionString value if available. May be nil.
*/
@property(nonatomic, readonly) NSString *applicationMarketingVersion;
@end

Просмотреть файл

@ -1,90 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausiblelabs.com>
*
* Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#import "PLCrashReportProcessorInfo.h"
@interface PLCrashReportBinaryImageInfo : NSObject {
@private
/** Code type */
PLCrashReportProcessorInfo *_processorInfo;
/** Base image address */
uint64_t _baseAddress;
/** Image segment size */
uint64_t _imageSize;
/** Name of binary image */
NSString *_imageName;
/** If the UUID is available */
BOOL _hasImageUUID;
/** 128-bit object UUID. May be nil. */
NSString *_imageUUID;
}
- (id) initWithCodeType: (PLCrashReportProcessorInfo *) processorInfo
baseAddress: (uint64_t) baseAddress
size: (uint64_t) imageSize
name: (NSString *) imageName
uuid: (NSData *) uuid;
/**
* Image code type, or nil if unavailable.
*/
@property(nonatomic, readonly) PLCrashReportProcessorInfo *codeType;
/**
* Image base address.
*/
@property(nonatomic, readonly) uint64_t imageBaseAddress;
/**
* Segment size.
*/
@property(nonatomic, readonly) uint64_t imageSize;
/**
* Image name (absolute path)
*/
@property(nonatomic, readonly) NSString *imageName;
/**
* YES if this image has an associated UUID.
*/
@property(nonatomic, readonly) BOOL hasImageUUID;
/**
* 128-bit object UUID (matches Mach-O DWARF dSYM files). May be nil if unavailable.
*/
@property(nonatomic, readonly) NSString *imageUUID;
@end

Просмотреть файл

@ -1,65 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausiblelabs.com>
*
* Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#import "PLCrashReportThreadInfo.h"
@interface PLCrashReportExceptionInfo : NSObject {
@private
/** Name */
NSString *_name;
/** Reason */
NSString *_reason;
/** Ordered list of PLCrashReportStackFrame instances, or nil if unavailable. */
NSArray *_stackFrames;
}
- (id) initWithExceptionName: (NSString *) name reason: (NSString *) reason;
- (id) initWithExceptionName: (NSString *) name
reason: (NSString *) reason
stackFrames: (NSArray *) stackFrames;
/**
* The exception name.
*/
@property(nonatomic, readonly) NSString *exceptionName;
/**
* The exception reason.
*/
@property(nonatomic, readonly) NSString *exceptionReason;
/* The exception's original call stack, as an array of PLCrashReportStackFrameInfo instances, or nil if unavailable.
* This may be preserved across rethrow of an exception, and can be used to determine the original call stack. */
@property(nonatomic, readonly) NSArray *stackFrames;
@end

Просмотреть файл

@ -1,51 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausiblelabs.com>
*
* Copyright (c) 2008-2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#import "PLCrashReport.h"
/**
* A crash report formatter accepts a PLCrashReport instance, formats it according to implementation-specified rules,
* (such as implementing text output support), and returns the result.
*/
@protocol PLCrashReportFormatter
/**
* Format the provided @a report.
*
* @param report Report to be formatted.
* @param outError A pointer to an NSError object variable. If an error occurs, this pointer will contain an error
* object indicating why the pending crash report could not be formatted. If no error occurs, this parameter will
* be left unmodified. You may specify nil for this parameter, and no error information will be provided.
*
* @return Returns the formatted report data on success, or nil on failure.
*/
- (NSData *) formatReport: (PLCrashReport *) report error: (NSError **) outError;
@end

Просмотреть файл

@ -1,48 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausiblelabs.com>
*
* Copyright (c) 2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
@interface PLCrashReportMachExceptionInfo : NSObject {
@private
/** The Mach exception type. */
uint64_t _type;
/** The Mach exception codes, represented as an ordered array of NSNumber instances. */
NSArray *_codes;
}
- (id) initWithType: (uint64_t) type codes: (NSArray *) codes;
/** The Mach exception type. */
@property(nonatomic, readonly) uint64_t type;
/** The Mach exception codes, represented as an ordered array of 64-bit unsigned NSNumber instances. */
@property(nonatomic, readonly) NSArray *codes;
@end

Просмотреть файл

@ -1,73 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausible.coop>
*
* Copyright (c) 2008-2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#import "PLCrashReportProcessorInfo.h"
@interface PLCrashReportMachineInfo : NSObject {
@private
/** The hardware model name (eg, MacBookPro6,1). This may be unavailable, and this property will be nil. */
NSString *_modelName;
/** The processor type. */
PLCrashReportProcessorInfo *_processorInfo;
/* The number of actual physical processor cores. */
NSUInteger _processorCount;
/* The number of logical processors. */
NSUInteger _logicalProcessorCount;
}
- (id) initWithModelName: (NSString *) modelName
processorInfo: (PLCrashReportProcessorInfo *) processorInfo
processorCount: (NSUInteger) processorCount
logicalProcessorCount: (NSUInteger) logicalProcessorCount;
/** The hardware model name (eg, MacBookPro6,1). This may be unavailable, and this property will be nil. */
@property(nonatomic, readonly) NSString *modelName;
/** The processor type. This will be unavailable in reports generated prior to PLCrashReporter 1.2, in which case this property will be nil. */
@property(nonatomic, readonly) PLCrashReportProcessorInfo *processorInfo;
/*
* The number of actual physical processor cores. Note that the number of active processors may be managed by the
* operating system's power management system, and this value may not reflect the number of active
* processors at the time of the crash.
*/
@property(nonatomic, readonly) NSUInteger processorCount;
/*
* The number of logical processors. Note that the number of active processors may be managed by the
* operating system's power management system, and this value may not reflect the number of active
* processors at the time of the crash.
*/
@property(nonatomic, readonly) NSUInteger logicalProcessorCount;
@end

Просмотреть файл

@ -1,103 +0,0 @@
/*
* Author: Damian Morris <damian@moso.com.au>
*
* Copyright (c) 2010 MOSO Corporation, Pty Ltd.
* Copyright (c) 2010-2013 Plausible Labs Cooperative, Inc.
*
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
@interface PLCrashReportProcessInfo : NSObject {
@private
/** Process name, or nil if unavailable. */
NSString *_processName;
/** Process ID */
NSUInteger _processID;
/** Process path */
NSString* _processPath;
/** Date and time that the crashing process was started. This may be unavailable, and this property
* will be nil. */
NSDate *_processStartTime;
/** Parent process name, or nil if unavailable. */
NSString *_parentProcessName;
/** Parent process ID */
NSUInteger _parentProcessID;
/** If false, the process is being run via process-level CPU emulation (such as Rosetta). */
BOOL _native;
}
- (id) initWithProcessName: (NSString *) processName
processID: (NSUInteger) processID
processPath: (NSString *) processPath
processStartTime: (NSDate *) processStartTime
parentProcessName: (NSString *) parentProcessName
parentProcessID: (NSUInteger) parentProcessID
native: (BOOL) native;
/**
* The process name. This value may not be included in the crash report, in which case this property
* will be nil.
*/
@property(nonatomic, readonly) NSString *processName;
/**
* The process ID.
*/
@property(nonatomic, readonly) NSUInteger processID;
/**
* The path to the process executable. This value may not be included in the crash report, in which case this property
* will be nil.
*/
@property(nonatomic, readonly) NSString *processPath;
/**
* Date and time that the crashing process was started. This value may not be included in the crash report, in which case this property
* will be nil.
*/
@property(nonatomic, readonly) NSDate *processStartTime;
/**
* The parent process name. This value may not be included in the crash report, in which case this property
* will be nil.
*/
@property(nonatomic, readonly) NSString *parentProcessName;
/**
* The parent process ID.
*/
@property(nonatomic, readonly) NSUInteger parentProcessID;
/** The process' native execution status. If false, the process is being run via process-level CPU emulation (such as Rosetta). */
@property(nonatomic, readonly) BOOL native;
@end

Просмотреть файл

@ -1,74 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausible.coop>
*
* Copyright (c) 2008-2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#import <mach/machine.h>
/**
* @ingroup constants
*
* The type encodings supported for CPU types and subtypes. Currently only Apple
* Mach-O defined encodings are supported.
*
* @internal
* These enum values match the protobuf values. Keep them synchronized.
*/
typedef enum {
/** Unknown cpu type encoding. */
PLCrashReportProcessorTypeEncodingUnknown = 0,
/** Apple Mach-defined processor types. */
PLCrashReportProcessorTypeEncodingMach = 1
} PLCrashReportProcessorTypeEncoding;
@interface PLCrashReportProcessorInfo : NSObject {
@private
/** Type encoding */
PLCrashReportProcessorTypeEncoding _typeEncoding;
/** CPU type */
uint64_t _type;
/** CPU subtype */
uint64_t _subtype;
}
- (id) initWithTypeEncoding: (PLCrashReportProcessorTypeEncoding) typeEncoding
type: (uint64_t) type
subtype: (uint64_t) subtype;
/** The CPU type encoding. */
@property(nonatomic, readonly) PLCrashReportProcessorTypeEncoding typeEncoding;
/** The CPU type. */
@property(nonatomic, readonly) uint64_t type;
/** The CPU subtype. */
@property(nonatomic, readonly) uint64_t subtype;
@end

Просмотреть файл

@ -1,52 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausible.coop>
*
* Copyright (c) 2008-2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
@interface PLCrashReportRegisterInfo : NSObject {
@private
/** Register name */
NSString *_registerName;
/** Register value */
uint64_t _registerValue;
}
- (id) initWithRegisterName: (NSString *) registerName registerValue: (uint64_t) registerValue;
/**
* Register name.
*/
@property(nonatomic, readonly) NSString *registerName;
/**
* Register value.
*/
@property(nonatomic, readonly) uint64_t registerValue;
@end

Просмотреть файл

@ -1,60 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausiblelabs.com>
*
* Copyright (c) 2008-2009 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
@interface PLCrashReportSignalInfo : NSObject {
@private
/** Signal name */
NSString *_name;
/** Signal code */
NSString *_code;
/** Fauling instruction or address */
uint64_t _address;
}
- (id) initWithSignalName: (NSString *) name code: (NSString *) code address: (uint64_t) address;
/**
* The signal name.
*/
@property(nonatomic, readonly) NSString *name;
/**
* The signal code.
*/
@property(nonatomic, readonly) NSString *code;
/**
* The faulting instruction or address.
*/
@property(nonatomic, readonly) uint64_t address;
@end

Просмотреть файл

@ -1,52 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausible.coop>
*
* Copyright (c) 2008-2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#import "PLCrashReportSymbolInfo.h"
@interface PLCrashReportStackFrameInfo : NSObject {
@private
/** Frame instruction pointer. */
uint64_t _instructionPointer;
/** Symbol information, if available. Otherwise, will be nil. */
PLCrashReportSymbolInfo *_symbolInfo;
}
- (id) initWithInstructionPointer: (uint64_t) instructionPointer symbolInfo: (PLCrashReportSymbolInfo *) symbolInfo;
/**
* Frame's instruction pointer.
*/
@property(nonatomic, readonly) uint64_t instructionPointer;
/** Symbol information for this frame.
* This may be unavailable, and this property will be nil. */
@property(nonatomic, readonly) PLCrashReportSymbolInfo *symbolInfo;
@end

Просмотреть файл

@ -1,61 +0,0 @@
/*
* Author: Landon Fuller <landonf@plausible.coop>
*
* Copyright (c) 2012-2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
@interface PLCrashReportSymbolInfo : NSObject {
@private
/** The symbol name. */
NSString *_symbolName;
/** The symbol start address. */
uint64_t _startAddress;
/** The symbol end address, if explicitly defined. Will be 0 if unknown. */
uint64_t _endAddress;
}
- (id) initWithSymbolName: (NSString *) symbolName
startAddress: (uint64_t) startAddress
endAddress: (uint64_t) endAddress;
/** The symbol name. */
@property(nonatomic, readonly) NSString *symbolName;
/** The symbol start address. */
@property(nonatomic, readonly) uint64_t startAddress;
/* The symbol end address, if explicitly defined. This will only be included if the end address is
* explicitly defined (eg, by DWARF debugging information), will not be derived by best-guess
* heuristics.
*
* If unknown, the address will be 0.
*/
@property(nonatomic, readonly) uint64_t endAddress;
@end

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше