1
0
mirror of https://github.com/ascribe/onion.git synced 2024-11-15 01:25:17 +01:00

Merged in AD-586-implement-logging-for-whole-app (pull request #12)

Ad 586 implement logging for whole app
This commit is contained in:
Alberto Granzotto 2015-07-17 18:25:56 +02:00
commit 658a4b3372
30 changed files with 133 additions and 76 deletions

View File

@ -32,10 +32,10 @@
"react/wrap-multilines": 1
},
"globals": {
"Raven": true,
"Intercom": true,
"fetch": true
}
"fetch": true,
"require": true
},
"plugins": [
"react"
],

View File

@ -51,9 +51,6 @@
ga('create', 'UA-60614729-2', 'auto');
</script>
<!-- Logging for sentry -->
<script src="//cdn.ravenjs.com/1.1.19/raven.min.js"></script>
<!-- Intercom library -->
<script>
(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;

View File

@ -17,7 +17,7 @@ class ApplicationActions {
this.actions.updateApplications(res.applications);
})
.catch((err) => {
console.log(err);
console.logGlobal(err);
});
}
refreshApplicationToken(applicationName) {
@ -26,7 +26,7 @@ class ApplicationActions {
this.actions.updateApplications(res.applications);
})
.catch((err) => {
console.log(err);
console.logGlobal(err);
});
}
}

View File

@ -17,7 +17,7 @@ class CoaActions {
this.actions.updateCoa(res.coa);
})
.catch((err) => {
console.log(err);
console.logGlobal(err);
});
}
create(edition) {
@ -26,7 +26,7 @@ class CoaActions {
this.actions.updateCoa(res.coa);
})
.catch((err) => {
console.log(err);
console.logGlobal(err);
});
}
}

View File

@ -17,7 +17,7 @@ class EditionActions {
this.actions.updateEdition(res.edition);
})
.catch((err) => {
console.log(err);
console.logGlobal(err);
});
}
}

View File

@ -45,7 +45,6 @@ class EditionListActions {
})
.catch((err) => {
reject(err);
//console.log(err);
});
});

View File

@ -17,7 +17,7 @@ class LicenseActions {
this.actions.updateLicenses(res.licenses);
})
.catch((err) => {
console.log(err);
console.logGlobal(err);
});
}
}

View File

@ -32,7 +32,7 @@ class LoanContractActions {
}
})
.catch((err) => {
console.error(err);
console.logGlobal(err);
this.actions.updateLoanContract({
contractKey: null,
contractUrl: null,

View File

@ -18,7 +18,7 @@ class PieceActions {
this.actions.updatePiece(res.piece);
})
.catch((err) => {
console.log(err);
console.logGlobal(err);
});
}
}

View File

@ -53,7 +53,8 @@ class PieceListActions {
.fetchRequestActions()
.then((res) => {
this.actions.updatePieceListRequestActions(res.piece_ids);
});
})
.catch((err) => console.logGlobal(err));
}
}

View File

@ -18,7 +18,7 @@ class UserActions {
this.actions.updateCurrentUser(res.users[0]);
})
.catch((err) => {
console.log(err);
console.logGlobal(err);
this.actions.updateCurrentUser({});
});
}
@ -28,7 +28,7 @@ class UserActions {
this.actions.deleteCurrentUser();
})
.catch((err) => {
console.log(err);
console.logGlobal(err);
});
}
}

View File

@ -17,7 +17,7 @@ class WalletSettingsActions {
this.actions.updateWalletSettings(res.wallet_settings);
})
.catch((err) => {
console.log(err);
console.logGlobal(err);
});
}
}

View File

@ -14,10 +14,14 @@ class WhitelabelActions {
fetchWhitelabel() {
WhitelabelFetcher.fetch()
.then((res) => {
this.actions.updateWhitelabel(res.whitelabel);
if(res && res.whitelabel) {
this.actions.updateWhitelabel(res.whitelabel);
} else {
this.actions.updateWhitelabel({});
}
})
.catch((err) => {
console.log(err);
console.logGlobal(err);
});
}
}

View File

@ -14,6 +14,9 @@ import getRoutes from './routes';
import requests from './utils/requests';
import { getSubdomainSettings } from './utils/constants_utils';
import { initLogging } from './utils/error_utils';
initLogging();
let headers = {
'Accept': 'application/json',
@ -25,18 +28,10 @@ requests.defaults({
http: {
headers: headers,
credentials: 'include'
},
fatalErrorHandler: (err) => {
console.log(err);
}
});
Raven.config('https://0955da3388c64ab29bd32c2a429f9ef4@app.getsentry.com/48351', {
// pass along the version of your application
release: '1.0.0'
}).install();
window.onerror = Raven.process;
class AppGateway {
@ -52,12 +47,13 @@ class AppGateway {
} catch(err) {
// if there are no matching subdomains, we're routing
// to the default frontend
console.logGlobal(err);
this.load('default');
}
}
load(type) {
Router.run(getRoutes(type), Router.HistoryLocation, (App, state) => {
Router.run(getRoutes(type), Router.HistoryLocation, (App) => {
if (window.ga) {
window.ga('send', 'pageview');
}
@ -71,3 +67,4 @@ class AppGateway {
let ag = new AppGateway();
ag.start();

View File

@ -117,7 +117,7 @@ let AccordionListItem = React.createClass({
getLicences() {
// convert this to acl_view_licences later
if (this.state.whitelabel.name === 'Creative Commons France') {
if (this.state.whitelabel && this.state.whitelabel.name === 'Creative Commons France') {
return (
<span>
<span>, </span>

View File

@ -80,6 +80,7 @@ let Form = React.createClass({
this.setState({edited: false, submitted: false});
},
handleError(err){
console.log(err);
if (err.json) {
for (var input in err.json.errors){
if (this.refs && this.refs[input] && this.refs[input].state) {
@ -90,7 +91,7 @@ let Form = React.createClass({
}
}
else {
console.error(err);
console.logGlobal(err);
this.setState({errors: [getLangText('Something went wrong, please try again later')]});
}
this.setState({submitted: false});

View File

@ -1,6 +1,7 @@
'use strict';
import React from 'react/addons';
import Raven from 'raven-js';
import { getCookie } from '../../utils/fetch_api_utils';
import { getLangText } from '../../utils/lang_utils';
@ -270,7 +271,7 @@ var ReactS3FineUploader = React.createClass({
})
.catch((err) => {
defer.failure(err);
console.error(err);
console.logGlobal(err);
});
return defer;
},

View File

@ -53,6 +53,11 @@ let GlobalNotification = React.createClass({
onChange(state) {
let notification = this.extractFirstElem(state.notificationQue);
// error handling for notifications
if(notification.message && notification.type === 'danger') {
console.logGlobal(new Error(notification.message.message));
}
if(notification.show) {
this.setState(notification);
} else {

View File

@ -2,6 +2,7 @@
import React from 'react';
import Router from 'react-router';
import Raven from 'raven-js';
import UserActions from '../actions/user_actions';
import UserStore from '../stores/user_store';
@ -59,14 +60,14 @@ let Header = React.createClass({
<span>ascribe </span>
<span className="glyph-ascribe-spool-chunked ascribe-color"></span>
</span>);
if (this.state.whitelabel.logo){
if (this.state.whitelabel && this.state.whitelabel.logo){
logo = <img className="img-brand" src={this.state.whitelabel.logo} />;
}
return logo;
},
getPoweredBy(){
if (this.state.whitelabel.logo) {
if (this.state.whitelabel && this.state.whitelabel.logo) {
return (
<li>
<a className="pull-right" href="https://www.ascribe.io/" target="_blank">

View File

@ -142,7 +142,7 @@ let RegisterPiece = React.createClass( {
},
getSpecifyEditions() {
if(this.state.whitelabel.acl_editions || Object.keys(this.state.whitelabel).length === 0) {
if(this.state.whitelabel && this.state.whitelabel.acl_editions || Object.keys(this.state.whitelabel).length === 0) {
return (
<PropertyCollapsible
name="num_editions"

View File

@ -14,6 +14,7 @@ let constants = {
'acl_loan', 'acl_share', 'acl_transfer', 'acl_unconsign', 'acl_unshare', 'acl_view',
'acl_withdraw_transfer'],
'version': 0.1,
'csrftoken': 'csrftoken2',
'subdomains': [
{
@ -47,7 +48,10 @@ let constants = {
],
// in case of whitelabel customization, we store stuff here
'whitelabel': {}
'whitelabel': {},
'raven': {
'url': 'https://0955da3388c64ab29bd32c2a429f9ef4@app.getsentry.com/48351'
}
};
export default constants;

View File

@ -11,9 +11,9 @@ let EditionListFetcher = {
*/
fetch(pieceId, page, pageSize, orderBy, orderAsc) {
let ordering = generateOrderingQueryParams(orderBy, orderAsc);
return requests.get('editions_list', {
return requests.get('editions_list', {
'piece_id': pieceId,
page,
page,
pageSize,
ordering
});

View File

@ -87,7 +87,7 @@ class EditionListStore {
this.editionList[pieceId].pageSize = prevEditionListPageSize;
})
.catch((err) => {
console.error(err);
console.logGlobal(err);
});
}

39
js/utils/error_utils.js Normal file
View File

@ -0,0 +1,39 @@
'use strict';
import Raven from 'raven-js';
import AppConstants from '../constants/application_constants';
/**
* Logs an error in to the console but also sends it to
* Sentry.
* Optionally, a comment can be defined.
* @param {Error} error a Javascript error
* @param {boolean} ignoreSentry Defines whether or not the error should be submitted to Sentry
* @param {string} comment Will also be submitted to Sentry, but will not be logged
*/
function logGlobal(error, ignoreSentry, comment) {
console.error(error);
if(!ignoreSentry) {
if(comment) {
Raven.captureException(error, {extra: { comment }});
} else {
Raven.captureException(error);
}
}
}
export function initLogging() {
// Initialize Raven for logging on Sentry
Raven.config(AppConstants.raven.url, {
release: AppConstants.version
}).install();
window.onerror = Raven.process;
console.logGlobal = logGlobal;
}

View File

@ -114,6 +114,10 @@ export function mergeOptions(...l) {
}
/**
* Merges a number of objects even if there're having duplicates.
*
* DOES NOT RETURN AN ERROR!
*
* Takes a list of object and merges their keys to one object.
* Uses mergeOptions for two objects.
* @param {[type]} l [description]

View File

@ -1,11 +1,8 @@
'use strict';
import { argsToQueryParams, getCookie } from '../utils/fetch_api_utils';
import AppConstants from '../constants/application_constants';
class UrlMapError extends Error {}
class ServerError extends Error {}
class APIError extends Error {}
import AppConstants from '../constants/application_constants';
class Requests {
@ -22,39 +19,47 @@ class Requests {
unpackResponse(response) {
if (response.status >= 500) {
throw new ServerError();
} else if(response.status === 403) {
Raven.captureException('csrftoken error');
throw new Error(response.status + ' - ' + response.statusText + ' - on URL:' + response.url);
}
return response.text();
return new Promise((resolve, reject) => {
response.text()
.then((responseText) => {
// If the responses' body does not contain any data,
// fetch will resolve responseText to the string 'None'.
// If this is the case, we can not try to parse it as JSON.
if(responseText !== 'None') {
let body = JSON.parse(responseText);
if(body && body.errors) {
let error = new Error('Form Error');
error.json = body;
reject(error);
} else {
resolve(body);
}
} else {
if(response.status >= 400) {
reject(new Error(response.status + ' - ' + response.statusText + ' - on URL:' + response.url));
} else {
resolve({});
}
}
}).catch((err) => {
reject(err);
});
});
}
customJSONparse(responseText) {
// If the responses' body does not contain any data,
// fetch will resolve responseText to the string 'None'.
// If this is the case, we can not try to parse it as JSON.
if(responseText !== 'None') {
return JSON.parse(responseText);
handleError(err) {
if (err instanceof TypeError) {
throw new Error('Server did not respond to the request. (Not even displayed a 500)');
} else {
return {};
throw err;
}
}
handleFatalError(err) {
this.fatalErrorHandler(err);
throw new ServerError(err);
}
handleAPIError(json) {
if (json.success === false) {
let error = new APIError();
error.json = json;
//console.error(new Error('The \'success\' property is missing in the server\'s response.'));
throw error;
}
return json;
}
getUrl(url) {
// Handle case, that the url string is not defined at all
if (!url) {
@ -65,7 +70,7 @@ class Requests {
if (!url.match(/^http/)) {
url = this.urlMap[url];
if (!url) {
throw new UrlMapError(`Cannot find a mapping for "${name}"`);
throw new Error(`Cannot find a mapping for "${name}"`);
}
}
@ -107,11 +112,10 @@ class Requests {
merged.headers['X-CSRFToken'] = csrftoken;
}
merged.method = verb;
return fetch(url, merged)
.then(this.unpackResponse)
.then(this.customJSONparse)
.catch(this.handleFatalError.bind(this))
.then(this.handleAPIError);
.catch(this.handleError);
}
get(url, params) {
@ -143,7 +147,6 @@ class Requests {
defaults(options) {
this.httpOptions = options.http || {};
this.urlMap = options.urlMap || {};
this.fatalErrorHandler = options.fatalErrorHandler || (() => {});
}
}

View File

@ -69,6 +69,7 @@
"jest-cli": "^0.4.0",
"lodash": "^3.9.3",
"object-assign": "^2.0.0",
"raven-js": "^1.1.19",
"react": "^0.13.2",
"react-bootstrap": "~0.22.6",
"react-datepicker": "~0.8.0",

View File

@ -21,7 +21,7 @@ $BASE_URL: '<%= BASE_URL %>';
@import 'ascribe_media_player';
@import 'ascribe_uploader';
@import 'ascribe_footer';
@import 'ascribe-global-notification';
@import 'ascribe_global_notification';
@import 'ascribe_piece_register';
@import 'offset_right';
@import 'ascribe_settings';