├── .gitignore ├── README.md ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | react-native-trackjs 2 | ==================== 3 | 4 | Reports javascript exceptions in React Native to the TrackJS server, by wrapping the trackjs js distribution. 5 | 6 | Usage 7 | ----- 8 | 9 | To use, add this code to your index.ios.js and index.android.js (or some library included by both). 10 | 11 | ``` 12 | import trackjs from 'react-native-trackjs'; 13 | trackjs.init({token: myTrackJsToken}); 14 | ``` 15 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { 4 | Dimensions, 5 | Platform, 6 | } from 'react-native'; 7 | 8 | class FakeImage { 9 | set src(url) { 10 | // fetch() tries to process the actual data and return it. 11 | // But trackjs returns nothing, and causes console warnings. 12 | // So let's just call out to XMLHttpRequest here, 13 | // even though it's strange to be doing so from a React Native app. 14 | // Update: Though hm....seems these give errors too from the React Native layer: 15 | // [RCTNetworking.m:330] Received data was not a string, or was not a recognised encoding. 16 | var xhr = new XMLHttpRequest(); 17 | xhr.open('GET', url, true); 18 | xhr.send(); 19 | } 20 | }; 21 | 22 | var FakeDocument = { 23 | get documentElement() { 24 | var window = Dimensions.get('window'); 25 | return { 26 | clientWidth: window.width, 27 | clientHeight: window.height, 28 | }; 29 | }, 30 | }; 31 | 32 | function initialize() { 33 | try { 34 | // Try accessing the useragent (which will work from the Chrome debugger): 35 | window.navigator.userAgent[0]; 36 | // We are running in a Chrome debugger. Let them continue as-is. 37 | // In theory, this shouldn't ever happen because we don't run in __DEV__ mode. 38 | } catch (e) { 39 | // If it fails, pollyfill it with our stubbed versions. 40 | window.navigator.userAgent = 'React-Native ' + Platform.OS + ', Version ' + Platform.Version; 41 | window.location = 'react-native-app'; 42 | } 43 | 44 | XMLHttpRequest.prototype.withCredentials = true; 45 | 46 | global.document = window.document = FakeDocument; 47 | global.Image = FakeImage; 48 | } 49 | 50 | function wrap(wrappedFunc) { 51 | // This ensures that TrackJS uses XMLHttpRequest 52 | // Because TrackJS expects too much when it sees addEventListener, hide it during load time. 53 | var addEventListener = window.addEventListener; 54 | window.addEventListener = undefined; 55 | try { 56 | wrappedFunc(); 57 | } finally { 58 | window.addEventListener = addEventListener; 59 | } 60 | } 61 | 62 | function init(config) { 63 | // Check if trackJs enabled is set 64 | if (typeof config.enabled === 'undefined') { 65 | // Disable trackJs in development using the variable set up by react-native's packager 66 | // Don't send exceptions from __DEV__, it's way too noisy! 67 | // Live reloading and hot reloading in particular lead to tons of noise... 68 | config.enabled = !__DEV__; 69 | } 70 | 71 | // If we've already set ourselves up, early-return 72 | if (window.trackJs) { 73 | return; 74 | } 75 | 76 | // Set up the magical config. 77 | window._trackJs = config; 78 | 79 | // TODO: maybe want to override fetch() to log our own events for the server?? 80 | // (ie search for 'watchNetworkObject', and do something similar for fetch() API) 81 | // Though really, this should be done inside trackJs, since fetch() is 82 | // a WHATWG standard, being supported by more and more browsers: 83 | // http://caniuse.com/#search=fetch 84 | 85 | // TrackJS will wrap these for its tracking events, if they exist: 86 | // onDocumentClicked: null, 87 | // onInputChanged: null, 88 | // addEventListener: null, 89 | // attachEvent: null, 90 | // But Redux state-based apps are becoming more and more common 91 | // in the React Native world, and combining them with their existing "logging" 92 | // will obviate the need for this kind of tracking. Though I'm sure it will be 93 | // useful for some people still who don't want to log internal state to the console 94 | // but do what to log it to TrackJS. But that's a TBD. 95 | 96 | initialize(); 97 | 98 | // Here's the main magic! Initialize everything with our monkey patching 99 | wrap(() => require('trackjs/tracker')) 100 | 101 | // Sometimes this will be empty, if we have any problems initializing 102 | // in the require('trackjs') above (and don't initialize the windowWatcher). 103 | if (window.onerror) { 104 | var originalHandler = global.ErrorUtils.getGlobalHandler(); 105 | var onError = function(e) { 106 | // Surround this one "just in case" window.onerror changes. 107 | if (window.onerror) { 108 | // window.onerror = function(message, source, lineno, colno, error) { ... } 109 | window.onerror(e.message, null, null, null, e); 110 | } 111 | // Again, just in case. Don't want to error in our error handler! 112 | if (originalHandler) { 113 | // And then re-throw the exception with the original handler 114 | originalHandler(e); 115 | } 116 | //window.trackJs.windowWatcher.onError('window', e); 117 | }; 118 | global.ErrorUtils.setGlobalHandler(onError); 119 | } 120 | } 121 | 122 | module.exports = { 123 | init, 124 | } 125 | 126 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-trackjs", 3 | "version": "0.1.2", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "dependencies": { 10 | "trackjs": "^2.3.1" 11 | }, 12 | "files": [ 13 | "index.js" 14 | ], 15 | "bugs": { 16 | "url": "https://github.com/mikelambert/react-native-trackjs/issues" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git+ssh://git@github.com/mikelambert/react-native-trackjs.git" 21 | }, 22 | "maintainers": [ 23 | { 24 | "email": "mlambert@gmail.com", 25 | "name": "Mike Lambert" 26 | } 27 | ], 28 | "keywords": [ 29 | "react-native", 30 | "react-component", 31 | "react-native-component", 32 | "react", 33 | "mobile", 34 | "ios", 35 | "android", 36 | "trackjs" 37 | ], 38 | "author": "Mike Lambert", 39 | "license": "ISC" 40 | } 41 | --------------------------------------------------------------------------------