1
0
mirror of https://github.com/ascribe/onion.git synced 2024-06-30 21:52:08 +02: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 "react/wrap-multilines": 1
}, },
"globals": { "globals": {
"Raven": true,
"Intercom": true, "Intercom": true,
"fetch": true "fetch": true,
} "require": true
},
"plugins": [ "plugins": [
"react" "react"
], ],

View File

@ -51,9 +51,6 @@
ga('create', 'UA-60614729-2', 'auto'); ga('create', 'UA-60614729-2', 'auto');
</script> </script>
<!-- Logging for sentry -->
<script src="//cdn.ravenjs.com/1.1.19/raven.min.js"></script>
<!-- Intercom library --> <!-- Intercom library -->
<script> <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; (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); this.actions.updateApplications(res.applications);
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.logGlobal(err);
}); });
} }
refreshApplicationToken(applicationName) { refreshApplicationToken(applicationName) {
@ -26,7 +26,7 @@ class ApplicationActions {
this.actions.updateApplications(res.applications); this.actions.updateApplications(res.applications);
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.logGlobal(err);
}); });
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -53,7 +53,8 @@ class PieceListActions {
.fetchRequestActions() .fetchRequestActions()
.then((res) => { .then((res) => {
this.actions.updatePieceListRequestActions(res.piece_ids); 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]); this.actions.updateCurrentUser(res.users[0]);
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.logGlobal(err);
this.actions.updateCurrentUser({}); this.actions.updateCurrentUser({});
}); });
} }
@ -28,7 +28,7 @@ class UserActions {
this.actions.deleteCurrentUser(); this.actions.deleteCurrentUser();
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.logGlobal(err);
}); });
} }
} }

View File

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

View File

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

View File

@ -14,6 +14,9 @@ import getRoutes from './routes';
import requests from './utils/requests'; import requests from './utils/requests';
import { getSubdomainSettings } from './utils/constants_utils'; import { getSubdomainSettings } from './utils/constants_utils';
import { initLogging } from './utils/error_utils';
initLogging();
let headers = { let headers = {
'Accept': 'application/json', 'Accept': 'application/json',
@ -25,18 +28,10 @@ requests.defaults({
http: { http: {
headers: headers, headers: headers,
credentials: 'include' 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 { class AppGateway {
@ -52,12 +47,13 @@ class AppGateway {
} catch(err) { } catch(err) {
// if there are no matching subdomains, we're routing // if there are no matching subdomains, we're routing
// to the default frontend // to the default frontend
console.logGlobal(err);
this.load('default'); this.load('default');
} }
} }
load(type) { load(type) {
Router.run(getRoutes(type), Router.HistoryLocation, (App, state) => { Router.run(getRoutes(type), Router.HistoryLocation, (App) => {
if (window.ga) { if (window.ga) {
window.ga('send', 'pageview'); window.ga('send', 'pageview');
} }
@ -71,3 +67,4 @@ class AppGateway {
let ag = new AppGateway(); let ag = new AppGateway();
ag.start(); ag.start();

View File

@ -117,7 +117,7 @@ let AccordionListItem = React.createClass({
getLicences() { getLicences() {
// convert this to acl_view_licences later // 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 ( return (
<span> <span>
<span>, </span> <span>, </span>

View File

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

View File

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

View File

@ -53,6 +53,11 @@ let GlobalNotification = React.createClass({
onChange(state) { onChange(state) {
let notification = this.extractFirstElem(state.notificationQue); 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) { if(notification.show) {
this.setState(notification); this.setState(notification);
} else { } else {

View File

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

View File

@ -142,7 +142,7 @@ let RegisterPiece = React.createClass( {
}, },
getSpecifyEditions() { 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 ( return (
<PropertyCollapsible <PropertyCollapsible
name="num_editions" name="num_editions"

View File

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

View File

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

View File

@ -87,7 +87,7 @@ class EditionListStore {
this.editionList[pieceId].pageSize = prevEditionListPageSize; this.editionList[pieceId].pageSize = prevEditionListPageSize;
}) })
.catch((err) => { .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. * Takes a list of object and merges their keys to one object.
* Uses mergeOptions for two objects. * Uses mergeOptions for two objects.
* @param {[type]} l [description] * @param {[type]} l [description]

View File

@ -1,11 +1,8 @@
'use strict'; 'use strict';
import { argsToQueryParams, getCookie } from '../utils/fetch_api_utils'; import { argsToQueryParams, getCookie } from '../utils/fetch_api_utils';
import AppConstants from '../constants/application_constants';
class UrlMapError extends Error {} import AppConstants from '../constants/application_constants';
class ServerError extends Error {}
class APIError extends Error {}
class Requests { class Requests {
@ -22,39 +19,47 @@ class Requests {
unpackResponse(response) { unpackResponse(response) {
if (response.status >= 500) { if (response.status >= 500) {
throw new ServerError(); throw new Error(response.status + ' - ' + response.statusText + ' - on URL:' + response.url);
} else if(response.status === 403) {
Raven.captureException('csrftoken error');
} }
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) { handleError(err) {
// If the responses' body does not contain any data, if (err instanceof TypeError) {
// fetch will resolve responseText to the string 'None'. throw new Error('Server did not respond to the request. (Not even displayed a 500)');
// If this is the case, we can not try to parse it as JSON.
if(responseText !== 'None') {
return JSON.parse(responseText);
} else { } 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) { getUrl(url) {
// Handle case, that the url string is not defined at all // Handle case, that the url string is not defined at all
if (!url) { if (!url) {
@ -65,7 +70,7 @@ class Requests {
if (!url.match(/^http/)) { if (!url.match(/^http/)) {
url = this.urlMap[url]; url = this.urlMap[url];
if (!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.headers['X-CSRFToken'] = csrftoken;
} }
merged.method = verb; merged.method = verb;
return fetch(url, merged) return fetch(url, merged)
.then(this.unpackResponse) .then(this.unpackResponse)
.then(this.customJSONparse) .catch(this.handleError);
.catch(this.handleFatalError.bind(this))
.then(this.handleAPIError);
} }
get(url, params) { get(url, params) {
@ -143,7 +147,6 @@ class Requests {
defaults(options) { defaults(options) {
this.httpOptions = options.http || {}; this.httpOptions = options.http || {};
this.urlMap = options.urlMap || {}; this.urlMap = options.urlMap || {};
this.fatalErrorHandler = options.fatalErrorHandler || (() => {});
} }
} }

View File

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

View File

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