Skip to content

Commit

Permalink
Merge pull request #1483 from bugsnag/release-v6.23.0
Browse files Browse the repository at this point in the history
Release v6.23.0
  • Loading branch information
nickdowell authored Sep 14, 2022
2 parents 6945f4b + 5861789 commit 735ed75
Show file tree
Hide file tree
Showing 118 changed files with 902 additions and 1,731 deletions.
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.22.3/Bugsnag"
github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa/tree/v6.23.0/Bugsnag"
github_url: "https://github.com/bugsnag/bugsnag-cocoa"
hide_documentation_coverage: true
module: "Bugsnag"
module_version: "6.22.3"
module_version: "6.23.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.22.3",
"version": "6.23.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.22.3"
"tag": "v6.23.0"
},
"ios": {
"frameworks": [
Expand Down
106 changes: 74 additions & 32 deletions Bugsnag.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions Bugsnag/Breadcrumbs/BSGNetworkBreadcrumb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// BSGNetworkBreadcrumb.h
// Bugsnag
//
// Created by Nick Dowell on 24/08/2022.
// Copyright © 2022 Bugsnag Inc. All rights reserved.
//

#import <Bugsnag/Bugsnag.h>

NS_ASSUME_NONNULL_BEGIN

API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0))
BugsnagBreadcrumb * _Nullable BSGNetworkBreadcrumbWithTaskMetrics(NSURLSessionTask *task, NSURLSessionTaskMetrics *metrics);

NSDictionary<NSString *, id> * _Nullable BSGURLParamsForQueryItems(NSArray<NSURLQueryItem *> * _Nullable queryItems);

NSString * _Nullable BSGURLStringForComponents(NSURLComponents * _Nullable URLComponents);

NS_ASSUME_NONNULL_END
96 changes: 96 additions & 0 deletions Bugsnag/Breadcrumbs/BSGNetworkBreadcrumb.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//
// BSGNetworkBreadcrumb.m
// Bugsnag
//
// Created by Nick Dowell on 24/08/2022.
// Copyright © 2022 Bugsnag Inc. All rights reserved.
//

#import "BSGNetworkBreadcrumb.h"

BugsnagBreadcrumb * BSGNetworkBreadcrumbWithTaskMetrics(NSURLSessionTask *task, NSURLSessionTaskMetrics *metrics) {
NSURLRequest *request = task.originalRequest ? task.originalRequest : task.currentRequest;
if (!request) {
return nil;
}

NSMutableDictionary *metadata = [NSMutableDictionary dictionary];
metadata[@"duration"] = @((unsigned)(metrics.taskInterval.duration * 1000));
metadata[@"method"] = request.HTTPMethod;

NSURL *url = request.URL;
if (url) {
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
metadata[@"url"] = BSGURLStringForComponents(components);
metadata[@"urlParams"] = BSGURLParamsForQueryItems(components.queryItems);
}

if (task.countOfBytesSent) {
metadata[@"requestContentLength"] = @(task.countOfBytesSent);
} else if (request.HTTPBody) {
// Fall back because task.countOfBytesSent is 0 when a custom NSURLProtocol is used
metadata[@"requestContentLength"] = @(request.HTTPBody.length);
}

NSString *message = @"NSURLSession request error";

// NSURLSessionTaskTransactionMetrics.response is nil when a custom NSURLProtocol is used.
// If there was an error, task.response will be nil.
NSURLResponse *response = task.response;
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = ((NSHTTPURLResponse *)response).statusCode;
if (100 <= statusCode && statusCode < 400) {
message = @"NSURLSession request succeeded";
}
if (400 <= statusCode && statusCode < 500) {
message = @"NSURLSession request failed";
}
metadata[@"responseContentLength"] = @(task.countOfBytesReceived);
metadata[@"status"] = @(statusCode);
}

BugsnagBreadcrumb *breadcrumb = [BugsnagBreadcrumb new];
breadcrumb.message = message;
breadcrumb.metadata = metadata;
breadcrumb.type = BSGBreadcrumbTypeRequest;
return breadcrumb;
}

NSDictionary<NSString *, id> * BSGURLParamsForQueryItems(NSArray<NSURLQueryItem *> *queryItems) {
if (!queryItems) {
return nil;
}
NSMutableDictionary *result = [NSMutableDictionary new];
for (NSURLQueryItem *item in queryItems) {
// - note: If a NSURLQueryItem name-value pair is empty (i.e. the query string starts with '&', ends
// with '&', or has "&&" within it), you get a NSURLQueryItem with a zero-length name and a nil value.
// If a NSURLQueryItem name-value pair has nothing before the equals sign, you get a zero-length name.
// If a NSURLQueryItem name-value pair has nothing after the equals sign, you get a zero-length value.
// If a NSURLQueryItem name-value pair has no equals sign, the NSURLQueryItem name-value pair string
// is the name and you get a nil value.
id value = item.value ?: [NSNull null];

id existingValue = result[item.name];
if ([existingValue isKindOfClass:[NSMutableArray class]]) {
[existingValue addObject:value];
} else if (existingValue) {
result[item.name] = [NSMutableArray arrayWithObjects:existingValue, value, nil];
} else {
result[item.name] = value;
}
}
return result;
}

NSString * BSGURLStringForComponents(NSURLComponents *components) {
if (components.rangeOfQuery.location == NSNotFound) {
return components.string;
}
NSRange rangeOfQuery = components.rangeOfQuery;
NSString *string = [components.string stringByReplacingCharactersInRange:rangeOfQuery withString:@""];
// rangeOfQuery does not include the '?' character, so that must be removed separately
if ([string characterAtIndex:rangeOfQuery.location - 1] == '?') {
string = [string stringByReplacingCharactersInRange:NSMakeRange(rangeOfQuery.location - 1, 1) withString:@""];
}
return string;
}
3 changes: 3 additions & 0 deletions Bugsnag/Breadcrumbs/BSGNotificationBreadcrumbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@

#import <Bugsnag/BugsnagBreadcrumb.h>

#import "BSGDefines.h"

@class BugsnagConfiguration;

NS_ASSUME_NONNULL_BEGIN

static NSString * const BSGNotificationBreadcrumbsMessageAppWillTerminate = @"App Will Terminate";

BSG_OBJC_DIRECT_MEMBERS
@interface BSGNotificationBreadcrumbs : NSObject

#pragma mark Initializers
Expand Down
20 changes: 20 additions & 0 deletions Bugsnag/Breadcrumbs/BSGNotificationBreadcrumbs.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,33 @@
#define BSG_HAVE_TABLE_VIEW (TARGET_OS_OSX || TARGET_OS_IOS || TARGET_OS_TV)
#define BSG_HAVE_TEXT_CONTROL (TARGET_OS_OSX || TARGET_OS_IOS )

BSG_OBJC_DIRECT_MEMBERS
@interface BSGNotificationBreadcrumbs ()

@property (nonatomic) NSDictionary<NSNotificationName, NSString *> *notificationNameMap;

@end

@interface BSGNotificationBreadcrumbs (/* not objc_direct */)

- (void)addBreadcrumbForNotification:(NSNotification *)notification;

- (void)addBreadcrumbForControlNotification:(NSNotification *)notification;

- (void)addBreadcrumbForMenuItemNotification:(NSNotification *)notification;

- (void)addBreadcrumbForTableViewNotification:(NSNotification *)notification;

#if TARGET_OS_IOS
- (void)orientationDidChange:(NSNotification *)notification;
#endif

- (void)thermalStateDidChange:(NSNotification *)notification API_AVAILABLE(ios(11.0), tvos(11.0));

@end


BSG_OBJC_DIRECT_MEMBERS
@implementation BSGNotificationBreadcrumbs

- (instancetype)initWithConfiguration:(BugsnagConfiguration *)configuration
Expand Down
3 changes: 3 additions & 0 deletions Bugsnag/Breadcrumbs/BugsnagBreadcrumbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@

#import <Foundation/Foundation.h>

#import "BSGDefines.h"

@class BugsnagBreadcrumb;
@class BugsnagConfiguration;
typedef struct BSG_KSCrashReportWriter BSG_KSCrashReportWriter;

NS_ASSUME_NONNULL_BEGIN

BSG_OBJC_DIRECT_MEMBERS
@interface BugsnagBreadcrumbs : NSObject

- (instancetype)initWithConfiguration:(BugsnagConfiguration *)config;
Expand Down
1 change: 1 addition & 0 deletions Bugsnag/Breadcrumbs/BugsnagBreadcrumbs.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ @interface BugsnagBreadcrumbs ()

#pragma mark -

BSG_OBJC_DIRECT_MEMBERS
@implementation BugsnagBreadcrumbs

- (instancetype)initWithConfiguration:(BugsnagConfiguration *)config {
Expand Down
20 changes: 3 additions & 17 deletions Bugsnag/Bugsnag+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,17 @@

#import <Bugsnag/Bugsnag.h>

#import "BSGDefines.h"

NS_ASSUME_NONNULL_BEGIN

BSG_OBJC_DIRECT_MEMBERS
@interface Bugsnag ()

#pragma mark Properties

@property (class, readonly, nonatomic) BOOL bugsnagStarted;

@property (class, readonly, nonatomic) BugsnagClient *client;

/// Will be nil until +startWithApiKey: or +startWithConfiguration: has been called.
@property (class, readonly, nullable, nonatomic) BugsnagConfiguration *configuration;

#pragma mark Methods

+ (void)addRuntimeVersionInfo:(NSString *)info withKey:(NSString *)key; // Used in BugsnagReactNative

+ (void)notifyInternal:(BugsnagEvent *)event block:(BOOL (^)(BugsnagEvent *))block; // Used in BugsnagReactNative

+ (void)purge;

+ (void)removeOnBreadcrumbBlock:(BugsnagOnBreadcrumbBlock)block;

+ (void)updateCodeBundleId:(NSString *)codeBundleId; // Used in BugsnagReactNative

@end

NS_ASSUME_NONNULL_END
50 changes: 10 additions & 40 deletions Bugsnag/Bugsnag.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@
#import "Bugsnag+Private.h"
#import "BugsnagBreadcrumbs.h"
#import "BugsnagClient+Private.h"
#import "BugsnagInternals.h"
#import "BugsnagLogger.h"

static BugsnagClient *bsg_g_bugsnag_client = NULL;

BSG_OBJC_DIRECT_MEMBERS
@implementation Bugsnag

+ (BugsnagClient *_Nonnull)start {
Expand Down Expand Up @@ -68,17 +70,6 @@ + (void)purge {
bsg_g_bugsnag_client = nil;
}

+ (BugsnagConfiguration *)configuration {
if ([self bugsnagStarted]) {
return self.client.configuration;
}
return nil;
}

+ (BugsnagConfiguration *)instance {
return [self configuration];
}

+ (BugsnagClient *)client {
return bsg_g_bugsnag_client;
}
Expand Down Expand Up @@ -127,18 +118,6 @@ + (void)notifyError:(NSError *)error block:(BugsnagOnErrorBlock)block {
}
}

/**
* Intended for use by other clients (React Native/Unity). Calling this method
* directly from iOS is not supported.
*/
+ (void)notifyInternal:(BugsnagEvent *_Nonnull)event
block:(BugsnagOnErrorBlock)block {
if ([self bugsnagStarted]) {
[self.client notifyInternal:event
block:block];
}
}

+ (BOOL)bugsnagStarted {
if (!self.client.started) {
bsg_log_err(@"Ensure you have started Bugsnag with startWithApiKey: "
Expand Down Expand Up @@ -173,9 +152,16 @@ + (void)leaveBreadcrumbWithMessage:(NSString *_Nonnull)message
}
}

+ (void)leaveNetworkRequestBreadcrumbForTask:(NSURLSessionTask *)task
metrics:(NSURLSessionTaskMetrics *)metrics {
if ([self bugsnagStarted]) {
[self.client leaveNetworkRequestBreadcrumbForTask:task metrics:metrics];
}
}

+ (NSArray<BugsnagBreadcrumb *> *_Nonnull)breadcrumbs {
if ([self bugsnagStarted]) {
return self.client.breadcrumbs.breadcrumbs ?: @[];
return self.client.breadcrumbs;
} else {
return @[];
}
Expand All @@ -201,13 +187,6 @@ + (BOOL)resumeSession {
}
}

+ (void)addRuntimeVersionInfo:(NSString *)info
withKey:(NSString *)key {
if ([self bugsnagStarted]) {
[self.client addRuntimeVersionInfo:info withKey:key];
}
}

// =============================================================================
// MARK: - <BugsnagFeatureFlagStore>
// =============================================================================
Expand Down Expand Up @@ -356,15 +335,6 @@ + (void)removeOnSessionBlock:(BugsnagOnSessionBlock _Nonnull )block
}
}

/**
* Intended for internal use only - sets the code bundle id for React Native
*/
+ (void)updateCodeBundleId:(NSString *)codeBundleId {
if ([self bugsnagStarted]) {
self.client.codeBundleId = codeBundleId;
}
}

// =============================================================================
// MARK: - OnBreadcrumb
// =============================================================================
Expand Down
Loading

0 comments on commit 735ed75

Please sign in to comment.