Skip to content

Commit

Permalink
Merge pull request #90 from rollbar/wj-device-attributes
Browse files Browse the repository at this point in the history
Send device attributes in payload client key
  • Loading branch information
waltjones authored Nov 5, 2019
2 parents 3fae06f + 5861d4a commit 9272907
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 2 deletions.
1 change: 1 addition & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ dependencies {
implementation 'com.rollbar:rollbar-java:1.4.0'
implementation 'com.rollbar:rollbar-android:1.4.0@aar'
implementation 'com.facebook.react:react-native:+'
implementation 'com.google.code.gson:gson:+'
}
21 changes: 21 additions & 0 deletions android/src/main/java/com/rollbar/RollbarReactNative.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.util.Map;

import com.google.gson.JsonObject;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactApplicationContext;
Expand All @@ -10,6 +12,7 @@
import com.facebook.react.bridge.ReactMethod;

import android.content.Context;
import android.os.Build;

import com.rollbar.android.Rollbar;
import com.rollbar.android.provider.NotifierProvider;
Expand Down Expand Up @@ -515,4 +518,22 @@ public void setPerson(ReadableMap personInfo) {
public void clearPerson() {
Rollbar.instance().clearPersonData();
}

// Defined as synchronous because the data must be returned in the
// javascript configuration constructor before Rollbar.js is initialized.
@ReactMethod(isBlockingSynchronousMethod = true)
public String deviceAttributes() {
JsonObject attributes = new JsonObject();

attributes.addProperty("os", "android");
attributes.addProperty("phone_model", android.os.Build.MODEL);
attributes.addProperty("android_version", android.os.Build.VERSION.RELEASE);
attributes.addProperty("board", android.os.Build.BOARD);
attributes.addProperty("brand", android.os.Build.BRAND);
attributes.addProperty("device", android.os.Build.DEVICE);
attributes.addProperty("manufacturer", android.os.Build.MANUFACTURER);
attributes.addProperty("product", android.os.Build.PRODUCT);

return attributes.toString();
}
}
37 changes: 37 additions & 0 deletions ios/RollbarReactNative.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#else
#import "RCTConvert.h"
#endif
#include <sys/utsname.h>

@implementation RollbarReactNative

Expand Down Expand Up @@ -254,4 +255,40 @@ + (void)critical:(NSString*)message exception:(NSException*)exception data:(NSDi
[[Rollbar currentConfiguration] setPersonId:nil username:nil email:nil];
}

// Defined as synchronous because the data must be returned in the
// javascript configuration constructor before Rollbar.js is initialized.
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(deviceAttributes)
{
struct utsname systemInfo;
uname(&systemInfo);
NSString *deviceCode = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];

NSBundle *mainBundle = [NSBundle mainBundle];
NSString *version = [mainBundle objectForInfoDictionaryKey:(NSString*)kCFBundleVersionKey];
NSString *shortVersion = [mainBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
NSString *bundleName = [mainBundle objectForInfoDictionaryKey:(NSString *)kCFBundleNameKey];
NSString *bundleIdentifier = [mainBundle objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey];

NSDictionary *attributes = @{
@"os": @"ios",
@"os_version": [[UIDevice currentDevice] systemVersion],
@"system_name": [[UIDevice currentDevice] systemName],
@"device_name": [[UIDevice currentDevice] name],
@"device_code" : deviceCode,
@"code_version": version ? version : @"",
@"short_version": shortVersion ? shortVersion : @"",
@"bundle_identifier": bundleIdentifier ? bundleIdentifier : @"",
@"app_name": bundleName ? bundleName : @""
};

NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:attributes
options:0
error:&error];

NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

return jsonString;
}

@end
26 changes: 24 additions & 2 deletions src/Rollbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Platform, NativeModules } from 'react-native';

import Rollbar from 'rollbar/src/react-native/rollbar';

import { merge } from '../src/merge';

const NativeClient = NativeModules.RollbarReactNative;

export class Client {
Expand Down Expand Up @@ -106,13 +108,16 @@ export class Configuration {
this.logLevel = options.logLevel || 'debug';
this.reportLevel = options.reportLevel || 'debug';
this.endpoint = options.endpoint || 'https://api.rollbar.com/api/1/item/';
this.appVersion = options.appVersion || undefined;
this.appVersion = options.appVersion || 'foo';
this.codeBundleId = options.codeBundleId || undefined;
this.releaseStage = options.releaseStage || undefined;
this.enabledReleaseStages = options.enabledReleaseStages || undefined;
this.captureUncaught = options.captureUncaught !== undefined ? options.captureUncaught : true;
this.captureUnhandledRejections = options.captureUnhandledRejections !== undefined ? options.captureUnhandledRejections : !__DEV__;
this.payload = options.payload || {};

// Ensure captureDeviceInfo is set before calling payloadOptions() below.
this.captureDeviceInfo = options.captureDeviceInfo === undefined ? true : options.captureDeviceInfo;
this.payload = merge(options.payload, this.payloadOptions());
this.enabled = options.enabled === undefined ? true : options.enabled;
this.verbose = options.verbose || false;
this.transform = options.transform;
Expand All @@ -135,6 +140,22 @@ export class Configuration {
}
}

payloadOptions = () => {
if (!this.captureDeviceInfo) {
return {};
}

return {
client: {
os: this.deviceAttributes()
}
}
}

deviceAttributes = () => {
return JSON.parse(NativeClient.deviceAttributes());
}

toJSON = () => {
var result = {
accessToken: this.accessToken,
Expand All @@ -144,6 +165,7 @@ export class Configuration {
reportLevel: this.reportLevel,
enabled: this.enabled,
verbose: this.verbose,
captureDeviceInfo: this.captureDeviceInfo,
transform: this.transform,
rewriteFilenamePatterns: this.rewriteFilenamePatterns,
payload: {
Expand Down
52 changes: 52 additions & 0 deletions src/merge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'use strict';

var hasOwn = Object.prototype.hasOwnProperty;
var toStr = Object.prototype.toString;

var isPlainObject = function isPlainObject(obj) {
if (!obj || toStr.call(obj) !== '[object Object]') {
return false;
}

var hasOwnConstructor = hasOwn.call(obj, 'constructor');
var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
// Not own constructor property must be Object
if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
return false;
}

// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
var key;
for (key in obj) {/**/}

return typeof key === 'undefined' || hasOwn.call(obj, key);
};

export function merge() {
var i, src, copy, clone, name,
result = {},
current = null,
length = arguments.length;

for (i=0; i < length; i++) {
current = arguments[i];
if (current == null) {
continue;
}

for (name in current) {
src = result[name];
copy = current[name];
if (result !== copy) {
if (copy && isPlainObject(copy)) {
clone = src && isPlainObject(src) ? src : {};
result[name] = merge(clone, copy);
} else if (typeof copy !== 'undefined') {
result[name] = copy;
}
}
}
}
return result;
}

0 comments on commit 9272907

Please sign in to comment.