Skip to content
This repository has been archived by the owner on Nov 17, 2021. It is now read-only.

Commit

Permalink
Report graph data request error with Sentry and...
Browse files Browse the repository at this point in the history
- Add support for out-of-boundary errors.
- Consistently use wrapped raven.

This resolves #199.
  • Loading branch information
Zodiase committed May 26, 2018
1 parent 8c58657 commit 08b16f8
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 26 deletions.
5 changes: 2 additions & 3 deletions meteor-app/imports/ui/components/appbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import {
connect,
} from 'react-redux';
import Raven from 'raven-js';
import AppBar from 'material-ui/AppBar';
import IconButton from 'material-ui/IconButton';
import IconMenu from 'material-ui/IconMenu';
Expand All @@ -15,8 +14,8 @@ import NoNotificationIcon from 'material-ui/svg-icons/social/notifications-none'
import CodeIcon from 'material-ui/svg-icons/action/code';
import EmailIcon from 'material-ui/svg-icons/communication/email';

import Raven from '/imports/startup/client/sentry';
import { actions } from '/imports/ui/redux-store';

import SafeLink from '/imports/ui/components/SafeLink';

import {
Expand Down Expand Up @@ -215,7 +214,7 @@ export default connect(

document.body.removeChild(anchorElement);
})((anchorElement) => {
Raven.captureException('Contact', {
Raven.captureMessage('Contact', {
logger: 'contact',
extra: {
reduxState: state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ import {
List,
} from 'material-ui/List';

import Raven from '/imports/startup/client/sentry';
import {
DatasetChartIcon,
PanToolIcon,
PointToolIcon,
BoxToolIcon,
} from '/imports/ui/consts';

import {
buildGeoJsonWithGeometry,
PatheticDataRequester,
Expand Down Expand Up @@ -105,7 +105,7 @@ class AnalyticsTabContent extends React.Component {
}

onDataReady = (data) => {
console.log('onDataReady', data);
console.log('AnalyticsTabContent.onDataReady', data);

this.setState({
isLoadingTimeSeriesData: false,
Expand All @@ -117,34 +117,76 @@ class AnalyticsTabContent extends React.Component {
});
};

onDataError = (reason) => {
console.error('request error', reason);
onDataError = (error) => {
console.error('AnalyticsTabContent.onDataError', error);

const rawErrorMessage = error.message;
// Prepare a more friendly error message. If this always returns a valid value then the raw error will never be displayed.
const {
level: reportLevel,
message: niceErrorMessage,
} = (() => {
switch (true) {
case objectPath.get(error, 'originalError.message') === 'network':
return {
level: 'error',
message: 'Can not connect to the data service for the selected variable due to a network error.',
};
case objectPath.get(error, 'originalError.response.data.message').indexOf('exceeded time limit of') > -1:
return {
level: 'warn',
message: 'The server took too long to respond. Please try again or select a smaller area.',
};
case objectPath.get(error, 'originalError.response.data.message') === 'Coordinates are outside region covered by the dataset':
return {
level: 'info',
message: 'Please select a point or area within the dataset boundary.',
};
default:
return {
level: 'error',
};
}
})();

if (reportLevel === 'error') {
// Report critical error.
Raven.captureMessage('Time-series data request error', {
extra: {
message: error.message,
request: error.request,
originalError: error.originalError,
originalResponse: error.originalResponse,
},
});
} else {
// Report abnormal event.
Raven.captureMessage('Time-series data request abnormal event', {
level: reportLevel,
extra: {
niceErrorMessage,
request: error.request,
originalError: error.originalError,
originalResponse: error.originalResponse,
},
});
}

this.setState({
isLoadingTimeSeriesData: false,
isTimeSeriesDataLoaded: false,
timeSeriesData: null,
timeSeriesDataRequestError: {
raw: reason.message,
// Prepare a more friendly error message. If this always returns a valid value then the raw error will never be displayed.
nice: (() => {
switch (true) {
case reason.response && reason.response.data && reason.response.data.status === 400 && reason.response.data.message.indexOf('exceeded time limit of') > -1:
return 'The server took too long to respond. Please try again or select a smaller area.';
case reason.message === 'network':
return 'Can not connect to the data service for the selected variable due to a network error.';
default:
return undefined;
}
})(),
raw: rawErrorMessage,
nice: niceErrorMessage,
},
timeSeriesDataResponseDate: new Date(),
isPendingTimeSeriesChartRender: false,
});
};

onChartRenderStart = () => {
console.log('onChartRenderStart');
console.log('AnalyticsTabContent.onChartRenderStart');

this.setState({
isPendingTimeSeriesChartRender: false,
Expand All @@ -154,7 +196,7 @@ class AnalyticsTabContent extends React.Component {
};

onChartRenderEnd = () => {
console.log('onChartRenderEnd');
console.log('AnalyticsTabContent.onChartRenderEnd');

this.setState({
isRenderingTimeSeriesChart: false,
Expand Down Expand Up @@ -209,7 +251,7 @@ class AnalyticsTabContent extends React.Component {
* @param {Function} reject - Reject the request with a reason.
*/
requestData = (payload, resolve, reject) => {
console.log('requestData', payload);
console.log('AnalyticsTabContent.requestData', payload);

// Clear existing data.
this.setState({
Expand All @@ -222,6 +264,7 @@ class AnalyticsTabContent extends React.Component {
});

if (!(payload.variableName && payload.boundaryGeometry && payload.dateRange)) {
console.log('Dependencies not met');
return;
}

Expand Down Expand Up @@ -252,7 +295,7 @@ class AnalyticsTabContent extends React.Component {
requestBody,
);

console.log('requestData', 'requesting', remoteUrl, requestBody);
console.log('AnalyticsTabContent.requestData', 'requesting', remoteUrl, requestBody);

this.setState({
isLoadingTimeSeriesData: true,
Expand All @@ -263,6 +306,14 @@ class AnalyticsTabContent extends React.Component {
timeSeriesDataResponseDate: null,
});

const exception = new Error('Unexpected error');

exception.request = {
method: 'post',
url: remoteUrl,
data: requestBody,
};

HTTP.post(
remoteUrl,
{
Expand All @@ -271,12 +322,16 @@ class AnalyticsTabContent extends React.Component {
},
(error, response) => {
if (error) {
reject(error);
exception.message = 'Error when requesting data';
exception.originalError = error;
reject(exception);
return;
}

if (response.statusCode !== 200) {
reject(response);
exception.message = 'Data not OK';
exception.originalResponse = response;
reject(exception);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion meteor-app/imports/ui/redux-store/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import PropTypes from 'prop-types';
import { createStore } from 'redux';
import { reducer as reduxFormReducer } from 'redux-form';
import Raven from 'raven-js';

import Raven from '/imports/startup/client/sentry';
import {
appSettings,
} from '/package.json';
Expand Down

0 comments on commit 08b16f8

Please sign in to comment.