Skip to content
This repository was archived by the owner on Sep 14, 2020. It is now read-only.

Commit cbeb424

Browse files
Next release (#351)
Next release
2 parents 4b31d08 + ec98e59 commit cbeb424

28 files changed

Lines changed: 818 additions & 20 deletions

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
Changelog
22
=========
33

4-
## TBD
4+
## 2.18.0 (2019-05-08)
5+
6+
* Collect version information in device.runtimeVersions
7+
[#345](https://github.com/bugsnag/bugsnag-react-native/pull/345)
58

69
Run checkstyle and lint on Android code, address existing violations
710
[#452](https://github.com/bugsnag/bugsnag-react-native/pull/336)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Bugsnag exception reporter for React Native
2-
[![Documentation](https://img.shields.io/badge/documentation-2.17.1-blue.svg)](http://docs.bugsnag.com/platforms/react-native/)
2+
[![Documentation](https://img.shields.io/badge/documentation-2.18.0-blue.svg)](http://docs.bugsnag.com/platforms/react-native/)
33

44
Automatic [React Native crash reporting](https://www.bugsnag.com/platforms/react-native-error-reporting/) with Bugsnag helps you detect both native OS and JavaScript errors in your React Native apps.
55

android/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ android {
1212
minSdkVersion safeExtGet('minSdkVersion', 16)
1313
targetSdkVersion safeExtGet('targetSdkVersion', 26)
1414
versionCode 4
15-
versionName '2.17.1'
15+
versionName '2.18.0'
1616
consumerProguardFiles 'proguard-rules.pro'
1717
}
1818
lintOptions {
@@ -23,7 +23,7 @@ android {
2323
}
2424

2525
dependencies {
26-
compile 'com.bugsnag:bugsnag-android:4.13.0'
26+
compile 'com.bugsnag:bugsnag-android:4.14.0'
2727
compile 'com.facebook.react:react-native:+'
2828
}
2929

@@ -39,4 +39,4 @@ task("checkstyle", type: Checkstyle) {
3939
include "**/*.java"
4040
exclude "**/external/**/*.java"
4141
classpath = files()
42-
}
42+
}

android/src/main/java/com/bugsnag/BugsnagReactNative.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.bugsnag.android.Bugsnag;
55
import com.bugsnag.android.Client;
66
import com.bugsnag.android.Configuration;
7+
import com.bugsnag.android.InternalHooks;
78

89
import android.content.Context;
910

@@ -119,6 +120,7 @@ public void startWithOptions(ReadableMap options) {
119120
libraryVersion = options.getString("version");
120121
bugsnagAndroidVersion = client.getClass().getPackage().getSpecificationVersion();
121122
configureRuntimeOptions(client, options);
123+
InternalHooks.configureClient(client);
122124

123125
logger.info(String.format("Initialized Bugsnag React Native %s/Android %s",
124126
libraryVersion,
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.bugsnag;
2+
3+
import com.facebook.react.modules.systeminfo.ReactNativeVersion;
4+
5+
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
9+
public class RuntimeVersions {
10+
11+
/**
12+
* Adds information about the react native version to a device dictionary
13+
*
14+
* @param device the device dictionary
15+
*/
16+
public static void addRuntimeVersions(Map<String, Object> device) {
17+
@SuppressWarnings("unchecked") // ignore type erasure when casting Map
18+
Map<String, Object> runtimeVersions = (Map<String, Object>) device.get("runtimeVersions");
19+
20+
if (runtimeVersions == null) {
21+
runtimeVersions = new HashMap<String, Object>();
22+
device.put("runtimeVersions", runtimeVersions);
23+
}
24+
runtimeVersions.put("reactNative", findReactNativeVersion());
25+
}
26+
27+
// see https://github.com/facebook/react-native/blob/6df2edeb2a33d529e4b13a5b6767f300d08aeb0a/scripts/bump-oss-version.js
28+
private static String findReactNativeVersion() {
29+
StringBuilder sb = new StringBuilder();
30+
31+
String major = getStringSafe("major", ReactNativeVersion.VERSION);
32+
if (major != null) {
33+
sb.append(major);
34+
sb.append(".");
35+
}
36+
37+
String minor = getStringSafe("minor", ReactNativeVersion.VERSION);
38+
if (minor != null) {
39+
sb.append(minor);
40+
sb.append(".");
41+
}
42+
43+
String patch = getStringSafe("patch", ReactNativeVersion.VERSION);
44+
if (patch != null) {
45+
sb.append(patch);
46+
}
47+
48+
String prerelease = getStringSafe("prerelease", ReactNativeVersion.VERSION);
49+
if (prerelease != null) {
50+
sb.append("-");
51+
sb.append(prerelease);
52+
}
53+
return sb.toString();
54+
}
55+
56+
private static String getStringSafe(String key, Map<String, Object> map) {
57+
Object obj = map.get(key);
58+
return (obj != null) ? obj.toString() : null;
59+
}
60+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.bugsnag.android;
2+
3+
import com.bugsnag.RuntimeVersions;
4+
5+
public class InternalHooks {
6+
7+
/**
8+
* Configures the bugsnag client by hooking into package-visible APIs within bugsnag-android
9+
*/
10+
public static void configureClient(Client client) {
11+
client.getConfig().addBeforeSendSession(new BeforeSendSession() {
12+
@Override
13+
public void beforeSendSession(SessionTrackingPayload payload) {
14+
RuntimeVersions.addRuntimeVersions(payload.getDevice());
15+
}
16+
});
17+
18+
client.getConfig().beforeSend(new BeforeSend() {
19+
@Override
20+
public boolean run(Report report) {
21+
RuntimeVersions.addRuntimeVersions(report.getError().getDeviceData());
22+
return true;
23+
}
24+
});
25+
}
26+
}

cocoa/BugsnagReactNative.m

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#import "Bugsnag.h"
22
#import "BSG_KSCrashC.h"
33
#import "BugsnagReactNative.h"
4+
#import "RCTVersion.h"
45
#import <React/RCTConvert.h>
56

67
NSString *const BSGInfoPlistKey = @"BugsnagAPIKey";
@@ -271,6 +272,23 @@ + (void)startWithConfiguration:(BugsnagConfiguration *)config {
271272
config.shouldAutoCaptureSessions = [RCTConvert BOOL:options[@"autoCaptureSessions"]];
272273
config.automaticallyCollectBreadcrumbs = [RCTConvert BOOL:options[@"automaticallyCollectBreadcrumbs"]];
273274

275+
[config addBeforeSendSession:^void(NSMutableDictionary *_Nonnull data) {
276+
data[@"device"] = [self addDeviceRuntimeVersion:data[@"device"]
277+
reactNativeVersion:[self findReactNativeVersion]];
278+
}];
279+
280+
[config addBeforeSendBlock:^bool(NSDictionary *_Nonnull rawEventData,
281+
BugsnagCrashReport *_Nonnull report) {
282+
NSString *reactNativeVersion = report.metaData[@"_bugsnag"][@"reactNativeVersion"];
283+
if (reactNativeVersion != nil) {
284+
report.device = [self addDeviceRuntimeVersion:report.device reactNativeVersion:reactNativeVersion];
285+
}
286+
report.metaData = [self removeRuntimeVersionFromMetaData:report];
287+
288+
return !([report.errorClass hasPrefix:@"RCTFatalException"]
289+
&& [report.errorMessage hasPrefix:@"Unhandled JS Exception"]);
290+
}];
291+
274292
if (notifyURLPath.length > 0) {
275293
[config setEndpointsForNotify:notifyURLPath
276294
sessions:sessionURLPath];
@@ -299,6 +317,68 @@ + (void)startWithConfiguration:(BugsnagConfiguration *)config {
299317
// session to compensate.
300318
[Bugsnag resumeSession];
301319
}
320+
[self addRuntimeVersionToMetaData:config];
321+
}
322+
323+
/**
324+
* Stores runtime version info in a metadata tab (it will be moved to a
325+
* different payload location before sending)
326+
*/
327+
- (void)addRuntimeVersionToMetaData:(BugsnagConfiguration *)config {
328+
[config.metaData addAttribute:@"reactNativeVersion"
329+
withValue:[self findReactNativeVersion]
330+
toTabWithName:@"_bugsnag"];
331+
}
332+
333+
- (NSDictionary *)removeRuntimeVersionFromMetaData:(BugsnagCrashReport *)report {
334+
NSMutableDictionary *metadata = report.metaData.mutableCopy;
335+
metadata[@"_bugsnag"] = nil;
336+
return metadata;
337+
}
338+
339+
- (NSDictionary *)addDeviceRuntimeVersion:(NSDictionary *)device
340+
reactNativeVersion:(NSString *)reactNativeVersion {
341+
NSMutableDictionary *copy = [device mutableCopy];
342+
NSMutableDictionary *runtimeVersions = [copy[@"runtimeVersions"] mutableCopy];
343+
344+
if (runtimeVersions == nil) {
345+
runtimeVersions = [NSMutableDictionary new];
346+
}
347+
runtimeVersions[@"reactNative"] = reactNativeVersion;
348+
copy[@"runtimeVersions"] = runtimeVersions;
349+
return copy;
350+
}
351+
352+
// see https://github.com/facebook/react-native/blob/6df2edeb2a33d529e4b13a5b6767f300d08aeb0a/scripts/bump-oss-version.js
353+
- (NSString *)findReactNativeVersion {
354+
static dispatch_once_t onceToken;
355+
static NSString *BSGReactNativeVersion = nil;
356+
dispatch_once(&onceToken, ^{
357+
NSDictionary *versionMap = RCTGetReactNativeVersion();
358+
NSNumber *major = versionMap[@"major"];
359+
NSNumber *minor = versionMap[@"minor"];
360+
NSNumber *patch = versionMap[@"patch"];
361+
NSString *prerelease = versionMap[@"prerelease"];
362+
NSMutableString *versionString = [NSMutableString new];
363+
364+
if (![major isEqual:[NSNull null]]) {
365+
[versionString appendString:[major stringValue]];
366+
[versionString appendString:@"."];
367+
}
368+
if (![minor isEqual:[NSNull null]]) {
369+
[versionString appendString:[minor stringValue]];
370+
[versionString appendString:@"."];
371+
}
372+
if (![patch isEqual:[NSNull null]]) {
373+
[versionString appendString:[patch stringValue]];
374+
}
375+
if (![prerelease isEqual:[NSNull null]]) {
376+
[versionString appendString:@"-"];
377+
[versionString appendString:prerelease];
378+
}
379+
BSGReactNativeVersion = [NSString stringWithString:versionString];
380+
});
381+
return BSGReactNativeVersion;
302382
}
303383

304384
- (void)setNotifierDetails:(NSString *)packageVersion {

cocoa/vendor/bugsnag-cocoa/Source/BugsnagConfiguration.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ typedef void (^BugsnagNotifyBlock)(BugsnagCrashReport *_Nonnull report);
5656
typedef bool (^BugsnagBeforeSendBlock)(NSDictionary *_Nonnull rawEventData,
5757
BugsnagCrashReport *_Nonnull reports);
5858

59+
/**
60+
* A configuration block for modifying a session. Intended for internal usage only.
61+
*
62+
* @param sessionPayload The session about to be delivered
63+
*/
64+
typedef void(^BeforeSendSession)(NSMutableDictionary *_Nonnull sessionPayload);
65+
5966
/**
6067
* A handler for modifying data before sending it to Bugsnag
6168
*
@@ -126,6 +133,13 @@ BugsnagBreadcrumbs *breadcrumbs;
126133
*/
127134
@property(readonly, strong, nullable)
128135
NSArray<BugsnagBeforeSendBlock> *beforeSendBlocks;
136+
137+
/**
138+
* Hooks for modifying sessions before they are sent to Bugsnag. Intended for internal use only by React Native/Unity.
139+
*/
140+
@property(readonly, strong, nullable)
141+
NSArray<BeforeSendSession> *beforeSendSessionBlocks;
142+
129143
/**
130144
* Optional handler invoked when a crash or fatal signal occurs
131145
*/
@@ -205,6 +219,13 @@ BugsnagBreadcrumbs *breadcrumbs;
205219
*/
206220
- (void)addBeforeSendBlock:(BugsnagBeforeSendBlock _Nonnull)block;
207221

222+
/**
223+
* Add a callback to be invoked before a session is sent to Bugsnag. Intended for internal usage only.
224+
*
225+
* @param block A block which can modify the session
226+
*/
227+
- (void)addBeforeSendSession:(BeforeSendSession _Nonnull)block;
228+
208229
/**
209230
* Clear all callbacks
210231
*/

cocoa/vendor/bugsnag-cocoa/Source/BugsnagConfiguration.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ @interface BugsnagNotifier ()
4848
@interface BugsnagConfiguration ()
4949
@property(nonatomic, readwrite, strong) NSMutableArray *beforeNotifyHooks;
5050
@property(nonatomic, readwrite, strong) NSMutableArray *beforeSendBlocks;
51+
@property(nonatomic, readwrite, strong) NSMutableArray *beforeSendSessionBlocks;
5152
@end
5253

5354
@implementation BugsnagConfiguration
@@ -62,6 +63,7 @@ - (id)init {
6263
_notifyURL = [NSURL URLWithString:BSGDefaultNotifyUrl];
6364
_beforeNotifyHooks = [NSMutableArray new];
6465
_beforeSendBlocks = [NSMutableArray new];
66+
_beforeSendSessionBlocks = [NSMutableArray new];
6567
_notifyReleaseStages = nil;
6668
_breadcrumbs = [BugsnagBreadcrumbs new];
6769
_automaticallyCollectBreadcrumbs = YES;
@@ -106,6 +108,10 @@ - (void)addBeforeSendBlock:(BugsnagBeforeSendBlock)block {
106108
[(NSMutableArray *)self.beforeSendBlocks addObject:[block copy]];
107109
}
108110

111+
- (void)addBeforeSendSession:(BeforeSendSession)block {
112+
[(NSMutableArray *)self.beforeSendSessionBlocks addObject:[block copy]];
113+
}
114+
109115
- (void)clearBeforeSendBlocks {
110116
[(NSMutableArray *)self.beforeSendBlocks removeAllObjects];
111117
}

cocoa/vendor/bugsnag-cocoa/Source/BugsnagKSCrashSysInfoParser.m

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,12 @@
118118
BSGDictSetSafeObject(deviceState, report[@"machine"], @"model");
119119
BSGDictSetSafeObject(deviceState, report[@"system_name"], @"osName");
120120
BSGDictSetSafeObject(deviceState, report[@"system_version"], @"osVersion");
121-
BSGDictSetSafeObject(deviceState, report[@"os_version"], @"osBuild");
121+
122+
NSMutableDictionary *runtimeVersions = [NSMutableDictionary new];
123+
BSGDictSetSafeObject(runtimeVersions, report[@"os_version"], @"osBuild");
124+
BSGDictSetSafeObject(runtimeVersions, report[@"clang_version"], @"clangVersion");
125+
BSGDictSetSafeObject(deviceState, runtimeVersions, @"runtimeVersions");
126+
122127
BSGDictSetSafeObject(deviceState, @(PLATFORM_WORD_SIZE), @"wordSize");
123128
BSGDictSetSafeObject(deviceState, @"Apple", @"manufacturer");
124129
BSGDictSetSafeObject(deviceState, report[@"jailbroken"], @"jailbroken");

0 commit comments

Comments
 (0)