Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v6.21.0 #1441

Merged
merged 13 commits into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .jazzy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ author_url: "https://www.bugsnag.com"
author: "Bugsnag Inc"
clean: false # avoid deleting docs/.git
framework_root: "Bugsnag"
github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa/tree/v6.20.0/Bugsnag"
github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa/tree/v6.21.0/Bugsnag"
github_url: "https://github.com/bugsnag/bugsnag-cocoa"
hide_documentation_coverage: true
module: "Bugsnag"
module_version: "6.20.0"
module_version: "6.21.0"
objc: true
output: "docs"
readme: "README.md"
Expand Down
4 changes: 2 additions & 2 deletions Bugsnag.podspec.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Bugsnag",
"version": "6.20.0",
"version": "6.21.0",
"summary": "The Bugsnag crash reporting framework for Apple platforms.",
"homepage": "https://bugsnag.com",
"license": "MIT",
Expand All @@ -9,7 +9,7 @@
},
"source": {
"git": "https://github.com/bugsnag/bugsnag-cocoa.git",
"tag": "v6.20.0"
"tag": "v6.21.0"
},
"ios": {
"frameworks": [
Expand Down
2 changes: 1 addition & 1 deletion Bugsnag.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES // -Warc-bridge-cas

// Warning flags that have no dedicated Xcode build settings

WARNING_CFLAGS = -Wcast-qual -Wconditional-uninitialized -Wcustom-atomic-properties -Wdirect-ivar-access -Wdocumentation-unknown-command -Wformat-nonliteral -Widiomatic-parentheses -Wimplicit-int-float-conversion -Wimport-preprocessor-directive-pedantic -Wincomplete-implementation -Wmissing-variable-declarations -Wno-unknown-warning-option -Wnonportable-include-path -Wnullable-to-nonnull-conversion -Woverriding-method-mismatch -Wpointer-sign -Wswitch-enum -Wunused-macros
WARNING_CFLAGS = -Wcast-qual -Wconditional-uninitialized -Wcustom-atomic-properties -Wdirect-ivar-access -Wdocumentation-unknown-command -Wformat-nonliteral -Widiomatic-parentheses -Wimplicit-int-float-conversion -Wimport-preprocessor-directive-pedantic -Wincomplete-implementation -Wmissing-variable-declarations -Wno-unknown-warning-option -Wnonportable-include-path -Wnullable-to-nonnull-conversion -Woverriding-method-mismatch -Wpointer-sign -Wswitch-enum -Wundef -Wunused-macros

// Some flags that were considered and rejected:
//
Expand Down
46 changes: 10 additions & 36 deletions Bugsnag.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

13 changes: 6 additions & 7 deletions Bugsnag/Breadcrumbs/BSGNotificationBreadcrumbs.m
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,8 @@ - (void)startListeningForStateChangeNotification:(NSNotificationName)notificatio
}

- (BOOL)tryAddSceneNotification:(NSNotification *)notification {
#if !TARGET_OS_WATCH && \
((defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0) || \
(defined(__TVOS_13_0) && __TV_OS_VERSION_MAX_ALLOWED >= __TVOS_13_0))
#if (TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0) || \
(TARGET_OS_TV && defined(__TVOS_13_0) && __TV_OS_VERSION_MAX_ALLOWED >= __TVOS_13_0)
if (@available(iOS 13.0, tvOS 13.0, *)) {
if ([notification.name hasPrefix:@"UIScene"] && [notification.object isKindOfClass:UISCENE]) {
UIScene *scene = notification.object;
Expand Down Expand Up @@ -304,13 +303,12 @@ - (BOOL)tryAddSceneNotification:(NSNotification *)notification {
- (BOOL)tryAddWindowNotification:(NSNotification *)notification {
#if BSG_HAVE_WINDOW

#if !TARGET_OS_OSX && \
(defined(__IPHONE_2_0) || (defined(__TVOS_9_0) && __TV_OS_VERSION_MAX_ALLOWED >= __TVOS_9_0))
#if TARGET_OS_IOS || TARGET_OS_TV
if ([notification.name hasPrefix:@"UIWindow"] && [notification.object isKindOfClass:UIWINDOW]) {
UIWindow *window = notification.object;
NSMutableDictionary *metadata = [NSMutableDictionary dictionary];
metadata[@"description"] = nullStringIfBlank(window.description);
#if !TARGET_OS_TV && (defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0)
#if TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
if (@available(iOS 13.0, *)) {
UIWindowScene *scene = window.windowScene;
metadata[@"sceneTitle"] = nullStringIfBlank(scene.title);
Expand All @@ -327,13 +325,14 @@ - (BOOL)tryAddWindowNotification:(NSNotification *)notification {
return YES;
}
#endif

#if TARGET_OS_OSX
if ([notification.name hasPrefix:@"NSWindow"] && [notification.object isKindOfClass:NSWINDOW]) {
NSWindow *window = notification.object;
NSMutableDictionary *metadata = [NSMutableDictionary dictionary];
metadata[@"description"] = nullStringIfBlank(window.description);
metadata[@"title"] = nullStringIfBlank(window.title);
#if defined(__MAC_11_0) && __MAC_OS_VERSION_MAX_ALLOWED >= __MAC_11_0
#if defined(__MAC_11_0) && __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_11_0
if (@available(macOS 11.0, *)) {
metadata[@"subtitle"] = nullStringIfBlank(window.subtitle);
}
Expand Down
61 changes: 33 additions & 28 deletions Bugsnag/Client/BugsnagClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
*
* @param writer report writer which will receive updated metadata
*/
void BSSerializeDataCrashHandler(const BSG_KSCrashReportWriter *writer) {
static void BSSerializeDataCrashHandler(const BSG_KSCrashReportWriter *writer) {
BOOL isCrash = YES;
BSGSessionWriteCrashReport(writer);

Expand All @@ -101,6 +101,17 @@ void BSSerializeDataCrashHandler(const BSG_KSCrashReportWriter *writer) {
writer->addJSONElement(writer, "metaData", bsg_g_bugsnag_data.metadataJSON);
writer->addJSONElement(writer, "state", bsg_g_bugsnag_data.stateJSON);

writer->beginObject(writer, "app"); {
if (bsg_runContext->memoryLimit) {
writer->addUIntegerElement(writer, "freeMemory", bsg_runContext->memoryAvailable);
writer->addUIntegerElement(writer, "memoryLimit", bsg_runContext->memoryLimit);
}
if (bsg_runContext->memoryFootprint) {
writer->addUIntegerElement(writer, "memoryUsage", bsg_runContext->memoryFootprint);
}
}
writer->endContainer(writer);

#if BSG_HAVE_BATTERY
if (BSGIsBatteryStateKnown(bsg_runContext->batteryState)) {
writer->addFloatingPointElement(writer, "batteryLevel", bsg_runContext->batteryLevel);
Expand Down Expand Up @@ -699,18 +710,13 @@ - (void)notifyInternal:(BugsnagEvent *_Nonnull)event
return;
}

// Device information that isn't part of `event.device`
NSMutableDictionary *deviceMetadata = [NSMutableDictionary dictionary];
#if BSG_HAVE_BATTERY
if (BSGIsBatteryStateKnown(BSGGetDevice().batteryState)) {
deviceMetadata[BSGKeyBatteryLevel] = @(BSGGetDevice().batteryLevel);
deviceMetadata[BSGKeyCharging] = BSGIsBatteryCharging(BSGGetDevice().batteryState) ? @YES : @NO;
}
#if TARGET_OS_WATCH
// Update BSGRunContext because we cannot observe battery level or state on watchOS :-(
bsg_runContext->batteryLevel = BSGGetDevice().batteryLevel;
bsg_runContext->batteryState = BSGGetDevice().batteryState;
#endif
if (@available(iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
deviceMetadata[BSGKeyThermalState] = BSGStringFromThermalState(bsg_runContext->thermalState);
}
[event.metadata addMetadata:deviceMetadata toSection:BSGKeyDevice];
[event.metadata addMetadata:BSGAppMetadataFromRunContext(bsg_runContext) toSection:BSGKeyApp];
[event.metadata addMetadata:BSGDeviceMetadataFromRunContext(bsg_runContext) toSection:BSGKeyDevice];

// App hang events will already contain feature flags
if (!event.featureFlagStore.count) {
Expand Down Expand Up @@ -1026,12 +1032,17 @@ - (void)appHangDetectedAtDate:(NSDate *)date withThreads:(NSArray<BugsnagThread

NSArray<BugsnagBreadcrumb *> *breadcrumbs = [self.breadcrumbs breadcrumbsBeforeDate:date];

BugsnagMetadata *metadata = [self.metadata deepCopy];

[metadata addMetadata:BSGAppMetadataFromRunContext(bsg_runContext) toSection:BSGKeyApp];
[metadata addMetadata:BSGDeviceMetadataFromRunContext(bsg_runContext) toSection:BSGKeyDevice];

self.appHangEvent =
[[BugsnagEvent alloc] initWithApp:app
device:device
handledState:handledState
user:self.configuration.user
metadata:[self.metadata deepCopy]
metadata:metadata
breadcrumbs:breadcrumbs
errors:@[error]
threads:threads
Expand Down Expand Up @@ -1155,27 +1166,21 @@ - (nullable BugsnagEvent *)generateEventForLastLaunchWithError:(BugsnagError *)e
if (bsg_lastRunContext->timestamp > 0) {
device.time = [NSDate dateWithTimeIntervalSinceReferenceDate:bsg_lastRunContext->timestamp];
}
device.freeMemory = @(bsg_lastRunContext->hostMemoryFree);

NSDictionary *metadataDict = BSGJSONDictionaryFromFile(BSGFileLocations.current.metadata, 0, nil);
BugsnagMetadata *metadata = [[BugsnagMetadata alloc] initWithDictionary:metadataDict ?: @{}];

// Device information that isn't part of `event.device`
NSMutableDictionary *deviceMetadata = [NSMutableDictionary dictionary];
#if BSG_HAVE_BATTERY
if (BSGIsBatteryStateKnown(bsg_lastRunContext->batteryState)) {
deviceMetadata[BSGKeyBatteryLevel] = @(bsg_lastRunContext->batteryLevel);
// Our intepretation of "charging" really means "plugged in"
deviceMetadata[BSGKeyCharging] = BSGIsBatteryCharging(bsg_lastRunContext->batteryState) ? @YES : @NO;
}
#endif
[metadata addMetadata:BSGAppMetadataFromRunContext((const struct BSGRunContext *_Nonnull)bsg_lastRunContext) toSection:BSGKeyApp];
[metadata addMetadata:BSGDeviceMetadataFromRunContext((const struct BSGRunContext *_Nonnull)bsg_lastRunContext) toSection:BSGKeyDevice];

#if BSG_HAVE_OOM_DETECTION
// Don't set to @NO because server may interpret any non-nil value as meaning true
deviceMetadata[BSGKeyLowMemoryWarning] = BSGRunContextWasMemoryWarning() ? @YES : nil;
#endif
if (@available(iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
deviceMetadata[BSGKeyThermalState] = BSGStringFromThermalState(bsg_lastRunContext->thermalState);
if (BSGRunContextWasMemoryWarning()) {
[metadata addMetadata:@YES
withKey:BSGKeyLowMemoryWarning
toSection:BSGKeyDevice];
}
[metadata addMetadata:deviceMetadata toSection:BSGKeyDevice];
#endif

NSDictionary *userDict = stateDict[BSGKeyUser];
BugsnagUser *user = [[BugsnagUser alloc] initWithDictionary:userDict];
Expand Down
3 changes: 2 additions & 1 deletion Bugsnag/Configuration/BugsnagConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ - (nonnull id)copyWithZone:(nullable NSZone *)zone {
// Omit apiKey - it's set explicitly in the line above
#if BSG_HAVE_APP_HANG_DETECTION
[copy setAppHangThresholdMillis:self.appHangThresholdMillis];
[copy setReportBackgroundAppHangs:self.reportBackgroundAppHangs];
#endif
[copy setAppType:self.appType];
[copy setAppVersion:self.appVersion];
Expand Down Expand Up @@ -213,7 +214,7 @@ - (instancetype)initWithApiKey:(NSString *)apiKey {
_telemetry = BSGTelemetryAll;

NSString *releaseStage = nil;
#if DEBUG
#if defined(DEBUG) && DEBUG
releaseStage = BSGKeyDevelopment;
#else
releaseStage = BSGKeyProduction;
Expand Down
3 changes: 0 additions & 3 deletions Bugsnag/Delivery/BSGEventUploadKSCrashReportOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

#import "BSGInternalErrorReporter.h"
#import "BSGJSONSerialization.h"
#import "BSG_KSCrashDoctor.h"
#import "BSG_KSCrashReportFields.h"
#import "BSG_RFC3339DateTool.h"
#import "BugsnagAppWithState.h"
Expand Down Expand Up @@ -163,8 +162,6 @@ - (NSMutableDictionary *)fixupCrashReport:(NSDictionary *)report {
NSMutableDictionary *crashReport =
[report[@BSG_KSCrashField_Crash] mutableCopy];
mutableReport[@BSG_KSCrashField_Crash] = crashReport;
BSG_KSCrashDoctor *doctor = [BSG_KSCrashDoctor doctor];
crashReport[@BSG_KSCrashField_Diagnosis] = [doctor diagnoseCrash:report];

return mutableReport;
}
Expand Down
11 changes: 5 additions & 6 deletions Bugsnag/Helpers/BSGAppHangDetector.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
@interface BSGAppHangDetector ()

@property (weak, nonatomic) id<BSGAppHangDetectorDelegate> delegate;
@property (nonatomic) BOOL recordAllThreads;
@property (nonatomic) CFRunLoopObserverRef observer;
@property (atomic) dispatch_time_t processingDeadline;
@property (nonatomic) dispatch_semaphore_t processingStarted;
Expand Down Expand Up @@ -67,7 +66,6 @@ - (void)startWithDelegate:(id<BSGAppHangDetectorDelegate>)delegate {
bsg_log_debug(@"Starting App Hang detector with threshold = %g seconds", threshold);

self.delegate = delegate;
self.recordAllThreads = configuration.sendThreads == BSGThreadSendPolicyAlways;
self.processingStarted = dispatch_semaphore_create(0);
self.processingFinished = dispatch_semaphore_create(0);

Expand Down Expand Up @@ -140,14 +138,14 @@ - (void)detectAppHangs {
shouldReportAppHang = NO;
}

#if DEBUG
#if defined(DEBUG) && DEBUG
if (shouldReportAppHang && bsg_ksmachisBeingTraced()) {
bsg_log_debug(@"Ignoring app hang because debugger is attached");
shouldReportAppHang = NO;
}
#endif

if (shouldReportAppHang && !bsg_runContext->isForeground) {
if (shouldReportAppHang && !bsg_runContext->isForeground && !self.delegate.configuration.reportBackgroundAppHangs) {
bsg_log_debug(@"Ignoring app hang because app is in the background");
shouldReportAppHang = NO;
}
Expand All @@ -172,9 +170,10 @@ - (void)appHangDetected {

NSDate *date = [NSDate date];
NSDictionary *systemInfo = [BSG_KSSystemInfo systemInfo];
id<BSGAppHangDetectorDelegate> delegate = self.delegate;

NSArray<BugsnagThread *> *threads = nil;
if (self.recordAllThreads) {
if (delegate.configuration.sendThreads == BSGThreadSendPolicyAlways) {
threads = [BugsnagThread allThreads:YES callStackReturnAddresses:NSThread.callStackReturnAddresses];
// By default the calling thread is marked as "Error reported from this thread", which is not correct case for app hangs.
[threads enumerateObjectsUsingBlock:^(BugsnagThread * _Nonnull thread, NSUInteger idx,
Expand All @@ -185,7 +184,7 @@ - (void)appHangDetected {
threads = BSGArrayWithObject([BugsnagThread mainThread]);
}

[self.delegate appHangDetectedAtDate:date withThreads:threads systemInfo:systemInfo];
[delegate appHangDetectedAtDate:date withThreads:threads systemInfo:systemInfo];
}

- (void)appHangEnded {
Expand Down
3 changes: 3 additions & 0 deletions Bugsnag/Helpers/BSGKeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ static BSGKey const BSGKeyExtraRuntimeInfo = @"extraRuntimeInfo";
static BSGKey const BSGKeyFeatureFlag = @"featureFlag";
static BSGKey const BSGKeyFeatureFlags = @"featureFlags";
static BSGKey const BSGKeyFrameAddress = @"frameAddress";
static BSGKey const BSGKeyFreeMemory = @"freeMemory";
static BSGKey const BSGKeyGroupingHash = @"groupingHash";
static BSGKey const BSGKeyHandled = @"handled";
static BSGKey const BSGKeyHandledCount = @"handledCount";
Expand All @@ -72,6 +73,8 @@ static BSGKey const BSGKeyMaxBreadcrumbs = @"maxBreadcrumbs";
static BSGKey const BSGKeyMaxPersistedEvents = @"maxPersistedEvents";
static BSGKey const BSGKeyMaxPersistedSessions = @"maxPersistedSessions";
static BSGKey const BSGKeyMessage = @"message";
static BSGKey const BSGKeyMemoryLimit = @"memoryLimit";
static BSGKey const BSGKeyMemoryUsage = @"memoryUsage";
static BSGKey const BSGKeyMetadata = @"metaData";
static BSGKey const BSGKeyMethod = @"method";
static BSGKey const BSGKeyName = @"name";
Expand Down
11 changes: 9 additions & 2 deletions Bugsnag/Helpers/BSGRunContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// During development this is not strictly necessary since last run's data will
// not be loaded if the struct's size has changed.
//
#define BSGRUNCONTEXT_VERSION 3
#define BSGRUNCONTEXT_VERSION 4

struct BSGRunContext {
long structVersion;
Expand All @@ -46,7 +46,10 @@ struct BSGRunContext {
dispatch_source_memorypressure_flags_t memoryPressure;
#endif
double timestamp __attribute__((aligned(8)));
size_t availableMemory;
unsigned long long hostMemoryFree;
unsigned long long memoryAvailable;
unsigned long long memoryFootprint;
unsigned long long memoryLimit;
};

/// Information about the current run of the app / process.
Expand All @@ -61,10 +64,14 @@ extern const struct BSGRunContext *_Nullable bsg_lastRunContext;

#pragma mark -

#ifdef FOUNDATION_EXTERN
void BSGRunContextInit(NSString *_Nonnull path);
#endif

#pragma mark -

BSG_PRIVATE void BSGRunContextUpdateMemory(void);

BSG_PRIVATE void BSGRunContextUpdateTimestamp(void);

#pragma mark -
Expand Down
Loading