diff --git a/ApplicationInsights.podspec b/ApplicationInsights.podspec
index e21e67ae..6a132d12 100644
--- a/ApplicationInsights.podspec
+++ b/ApplicationInsights.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "ApplicationInsights"
- s.version = "1.0-beta.4"
+ s.version = "1.0-beta.5"
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.
diff --git a/Classes/MSAIChannel.m b/Classes/MSAIChannel.m
index 1567634c..46bec784 100644
--- a/Classes/MSAIChannel.m
+++ b/Classes/MSAIChannel.m
@@ -38,6 +38,7 @@ + (void)setSharedChannel:(MSAIChannel *)channel {
- (instancetype)init {
if(self = [super init]) {
+ msai_resetSafeJsonStream(&MSAISafeJsonEventsString);
_dataItemCount = 0;
if (msai_isDebuggerAttached()) {
_senderBatchSize = debugMaxBatchCount;
@@ -60,7 +61,7 @@ - (BOOL)isQueueBusy{
- (void)persistDataItemQueue {
[self invalidateTimer];
- if(strlen(MSAISafeJsonEventsString) == 0) {
+ if(!MSAISafeJsonEventsString || strlen(MSAISafeJsonEventsString) == 0) {
return;
}
@@ -72,7 +73,7 @@ - (void)persistDataItemQueue {
}
- (void)resetQueue {
- msai_resetSafeJsonStream(&(MSAISafeJsonEventsString));
+ msai_resetSafeJsonStream(&MSAISafeJsonEventsString);
_dataItemCount = 0;
}
diff --git a/Classes/MSAICrashDataProvider.h b/Classes/MSAICrashDataProvider.h
index 3c9c38d2..03c13d96 100644
--- a/Classes/MSAICrashDataProvider.h
+++ b/Classes/MSAICrashDataProvider.h
@@ -30,5 +30,7 @@ typedef NS_ENUM (NSInteger, MSAIBinaryImageType) {
+ (MSAIEnvelope *)crashDataForCrashReport:(MSAIPLCrashReport *)report handledException:(nullable NSException *)exception;
+ (MSAIEnvelope *)crashDataForCrashReport:(MSAIPLCrashReport *)report;
++ (MSAIBinaryImageType)imageTypeForImagePath:(NSString *)imagePath processPath:(NSString *)processPath;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/Classes/MSAICrashDataProvider.m b/Classes/MSAICrashDataProvider.m
index d78ad051..00a10781 100644
--- a/Classes/MSAICrashDataProvider.m
+++ b/Classes/MSAICrashDataProvider.m
@@ -208,8 +208,6 @@ @implementation MSAICrashDataProvider
+ (MSAIEnvelope *)crashDataForCrashReport:(MSAIPLCrashReport *)report handledException:(NSException *)exception{
- NSMutableArray *addresses = [NSMutableArray new];
-
MSAIEnvelope *envelope = [[MSAIEnvelopeManager sharedManager] envelope];
/* System info */
@@ -366,10 +364,12 @@ + (MSAIEnvelope *)crashDataForCrashReport:(MSAIPLCrashReport *)report handledExc
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 */
@@ -451,6 +451,8 @@ + (MSAIEnvelope *)crashDataForCrashReport:(MSAIPLCrashReport *)report handledExc
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;
@@ -507,6 +509,7 @@ + (MSAIEnvelope *)crashDataForCrashReport:(MSAIPLCrashReport *)report handledExc
if(threadData.frames.count > 0){
[[(MSAICrashDataThreadFrame *)threadData.frames[0] registers] setValue:formattedRegValue forKey:formattedRegName];
+ [addresses addObject:[NSNumber numberWithUnsignedLongLong:reg.registerValue]];
}
break;
}
@@ -529,14 +532,25 @@ + (MSAIEnvelope *)crashDataForCrashReport:(MSAIPLCrashReport *)report handledExc
uint64_t endAddress = imageInfo.imageBaseAddress + (MAX((uint64_t)1, imageInfo.imageSize) - 1);
binary.endAddress = [NSString stringWithFormat:fmt, endAddress];
- if([self isBinaryWithStart:startAddress end:endAddress inAddresses:addresses]){
+ 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 (imageInfo.imageName && [imageInfo.imageName length] > 0) {
+#if TARGET_IPHONE_SIMULATOR
imageName = [imageInfo.imageName stringByAbbreviatingWithTildeInPath];
- if ([imageName length] > 0 && [[imageName substringToIndex:1] isEqualToString:@"~"])
+#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];
@@ -574,6 +588,37 @@ + (BOOL)isBinaryWithStart:(uint64_t)start end:(uint64_t)end inAddresses:(NSArray
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.
diff --git a/Classes/MSAICrashManager.m b/Classes/MSAICrashManager.m
index 1969325b..eb1f1992 100644
--- a/Classes/MSAICrashManager.m
+++ b/Classes/MSAICrashManager.m
@@ -80,11 +80,11 @@ static void plcr_post_crash_callback(siginfo_t *info, ucontext_t *uap, void *con
//
// We'll evaluate this further to see if there is a safe solution.
//
-@interface BITCrashCXXExceptionWrapperException : NSException
+@interface MSAICrashCXXExceptionWrapperException : NSException
- (instancetype)initWithCXXExceptionInfo:(const MSAICrashUncaughtCXXExceptionInfo *)info;
@end
-@implementation BITCrashCXXExceptionWrapperException {
+@implementation MSAICrashCXXExceptionWrapperException {
const MSAICrashUncaughtCXXExceptionInfo *_info;
}
@@ -116,7 +116,7 @@ - (NSArray *)callStackReturnAddresses {
// 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()([[BITCrashCXXExceptionWrapperException alloc] initWithCXXExceptionInfo:info]);
+ NSGetUncaughtExceptionHandler()([[MSAICrashCXXExceptionWrapperException alloc] initWithCXXExceptionInfo:info]);
abort();
}
@@ -144,8 +144,8 @@ + (instancetype)sharedManager {
* Main startup sequence initializing PLCrashReporter if it wasn't disabled
*/
- (void)startManager {
- if(self.isCrashManagerDisabled) return;
- if(![MSAICrashManager sharedManager].isSetupCorrectly) {
+ if (self.isCrashManagerDisabled) {return;}
+ if (![MSAICrashManager sharedManager].isSetupCorrectly) {
[self checkCrashManagerDisabled];
[self registerObservers];
diff --git a/README.md b/README.md
index 2c951658..1dc61d2c 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
[](https://travis-ci.org/Microsoft/ApplicationInsights-iOS)
-# Application Insights for iOS (1.0-beta.4)
+# Application Insights for iOS (1.0-beta.5)
This is the repository of the iOS SDK for Application Insights. [Application Insights](http://azure.microsoft.com/en-us/services/application-insights/) is a service that allows developers to keep their applications available, performing, and succeeding. 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.
@@ -26,31 +26,9 @@ The SDK runs on devices with iOS 6.0 or higher.
## 1. Release Notes
-* Make integration a lot easier, using the `@import ApplicationInsights;` syntax. This makes manual linking of system frameworks unnecessary!
-(_Note: Requires support for modules. This is enabled by default for all projects created with Xcode 5 or newer._)
-* Add feature to set common properties that will apply to all telemetry data items.
-
- ```objectivec
- [MSAITelemetryManager setCommonProperties:@{@"custom info":@"some value"}];
- ```
-
-* Allow for further customization of user context fields.
-Note that this means that the old way of setting the user ID, `setUserId:`, is now deprecated!
-
- ```objectivec
- [[MSAIApplicationInsights sharedInstance] setUserWithConfigurationBlock:^(MSAIUser *user) {
- user.userId = @"your_user_id";
- user.accountId = @"user@example.com";
- }];
- ```
-
-* Add support for unhandled C++ exceptions
-* Switch to sending data in JSON Stream format to improve compatibility with different server backends.
-* Improve crash reports by sending additional exception information.
-* Add instructions to Readme about how to setup the SDK with WatchKit extensions.
-* Add logging incase the developer tries to send objects that are not NSJSONSerialization compatible.
-* Fix issues with the backwars compatiblity of the nullability annotation.
-* Various other small improvements and fixes.
+* 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.
See [here](https://github.com/Microsoft/ApplicationInsights-iOS/releases) for the release notes of previous versions.
diff --git a/Support/ApplicationInsightsTests/MSAICrashDataProviderTests.m b/Support/ApplicationInsightsTests/MSAICrashDataProviderTests.m
index 5ab21034..d54c4432 100644
--- a/Support/ApplicationInsightsTests/MSAICrashDataProviderTests.m
+++ b/Support/ApplicationInsightsTests/MSAICrashDataProviderTests.m
@@ -9,12 +9,98 @@ @implementation MSAICrashDataProviderTests
- (void)setUp {
[super setUp];
- // Put setup code here. This method is called before the invocation of each test method in the class.
}
-- (void)tearDown {
+- (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
diff --git a/Support/buildnumber.xcconfig b/Support/buildnumber.xcconfig
index d06b591e..e392f93c 100644
--- a/Support/buildnumber.xcconfig
+++ b/Support/buildnumber.xcconfig
@@ -1,7 +1,7 @@
#include "ApplicationInsights.xcconfig"
-BUILD_NUMBER = 7
-VERSION_STRING = 1.0-beta.4
+BUILD_NUMBER = 8
+VERSION_STRING = 1.0-beta.5
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
diff --git a/docs/Readme-template.md b/docs/Readme-template.md
index 2c951658..1dc61d2c 100644
--- a/docs/Readme-template.md
+++ b/docs/Readme-template.md
@@ -1,6 +1,6 @@
[](https://travis-ci.org/Microsoft/ApplicationInsights-iOS)
-# Application Insights for iOS (1.0-beta.4)
+# Application Insights for iOS (1.0-beta.5)
This is the repository of the iOS SDK for Application Insights. [Application Insights](http://azure.microsoft.com/en-us/services/application-insights/) is a service that allows developers to keep their applications available, performing, and succeeding. 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.
@@ -26,31 +26,9 @@ The SDK runs on devices with iOS 6.0 or higher.
## 1. Release Notes
-* Make integration a lot easier, using the `@import ApplicationInsights;` syntax. This makes manual linking of system frameworks unnecessary!
-(_Note: Requires support for modules. This is enabled by default for all projects created with Xcode 5 or newer._)
-* Add feature to set common properties that will apply to all telemetry data items.
-
- ```objectivec
- [MSAITelemetryManager setCommonProperties:@{@"custom info":@"some value"}];
- ```
-
-* Allow for further customization of user context fields.
-Note that this means that the old way of setting the user ID, `setUserId:`, is now deprecated!
-
- ```objectivec
- [[MSAIApplicationInsights sharedInstance] setUserWithConfigurationBlock:^(MSAIUser *user) {
- user.userId = @"your_user_id";
- user.accountId = @"user@example.com";
- }];
- ```
-
-* Add support for unhandled C++ exceptions
-* Switch to sending data in JSON Stream format to improve compatibility with different server backends.
-* Improve crash reports by sending additional exception information.
-* Add instructions to Readme about how to setup the SDK with WatchKit extensions.
-* Add logging incase the developer tries to send objects that are not NSJSONSerialization compatible.
-* Fix issues with the backwars compatiblity of the nullability annotation.
-* Various other small improvements and fixes.
+* 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.
See [here](https://github.com/Microsoft/ApplicationInsights-iOS/releases) for the release notes of previous versions.