Skip to content

Commit 1dfd99d

Browse files
pzrqdurran
authored andcommitted
* COMPASS-317 ⬆️ [email protected] (#630) * COMPASS-382 and COMPASS-383 - Improve RTSS error handling (#638) * COMPASS-382 and COMPASS-383 - Improve RTSS error handling * Update mongodb-data-service dependency to 2.2.0 * COMPASS 503 ⬆️ [email protected] && [email protected]
1 parent 4a3ff29 commit 1dfd99d

File tree

6 files changed

+119
-119
lines changed

6 files changed

+119
-119
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@
125125
"moment": "^2.10.6",
126126
"mongodb": "^2.2.8",
127127
"mongodb-collection-model": "^0.3.1",
128-
"mongodb-connection-model": "^6.3.3",
129-
"mongodb-data-service": "^2.1.6",
128+
"mongodb-connection-model": "^6.3.4",
129+
"mongodb-data-service": "^2.2.1",
130130
"mongodb-database-model": "^0.1.2",
131131
"mongodb-explain-plan-model": "^0.2.2",
132132
"mongodb-extended-json": "^1.8.0",

src/internal-packages/server-stats/lib/component/dberror-component.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ class DBErrorComponent extends React.Component {
2323
this.setState({ data: data });
2424
}
2525

26-
renderErrors() {
26+
renderErrors() { // TODO: display srcName
2727
const rows = this.state.data.map(function(row, i) {
2828
return (
2929
<li className="rt-errors__item" key={`list-item-${i}`}>
30-
<div className="rt-errors__operror"><text>&#9888; Command {row.ops} returned error: </text><text className="rt-errors__bold">{row.errorMsg}</text></div>
30+
<div className="rt-errors__operror"><text>&#9888; Command &#34;{row.ops}&#34; returned error </text><text className="rt-errors__bold">&#34;{row.errorMsg}&#34;</text></div>
3131
</li>
3232
);
3333
});

src/internal-packages/server-stats/lib/store/current-op-store.js

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const CurrentOpStore = Reflux.createStore({
3333
this.inOverlay = false;
3434
this.xLength = 60;
3535
this.starting = true;
36-
this.error = null;
36+
this.errored = [];
3737
},
3838

3939
pause: function() {
@@ -44,31 +44,50 @@ const CurrentOpStore = Reflux.createStore({
4444
mouseOver: function(index) {
4545
const startPause = Math.max(this.endPause - this.xLength, 0);
4646
const visOps = this.allOps.slice(startPause, this.endPause);
47+
const visErrors = this.errored.slice(startPause, this.endPause);
4748
if (index >= visOps.length) {
4849
index = visOps.length - 1;
4950
}
5051
this.overlayIndex = index;
5152
this.inOverlay = true;
52-
this.trigger(null, visOps[this.overlayIndex]);
53+
this.trigger(visErrors[this.overlayIndex], visOps[this.overlayIndex]);
5354
},
5455

5556
mouseOut: function() {
5657
this.inOverlay = false;
5758
const startPause = Math.max(this.endPause - this.xLength, 0);
5859
const visOps = this.allOps.slice(startPause, this.endPause);
59-
this.trigger(this.error, visOps[visOps.length - 1]);
60+
const visErrors = this.errored.slice(startPause, this.endPause);
61+
this.trigger(visErrors[this.overlayIndex], visOps[visOps.length - 1]);
6062
},
6163

6264
currentOp: function() {
6365
app.dataService.currentOp(false, (error, response) => {
66+
// Trigger error banner changes
67+
if (error === null && this.errored.length > 0 && this.errored[this.errored.length - 1] !== null) { // Trigger error removal
68+
Actions.dbError({'op': 'currentOp', 'error': null });
69+
} else if (error !== null) {
70+
Actions.dbError({'op': 'currentOp', 'error': error });
71+
}
72+
this.errored.push(error);
73+
74+
// Update op list if error
75+
if (error !== null || this.starting) {
76+
this.allOps.push([]);
77+
}
78+
79+
// Update op list if no error
6480
let totals = [];
65-
this.error = error;
66-
if (!error && response !== undefined && ('inprog' in response)) {
81+
if (error === null) {
82+
// If response is empty, send empty list
83+
let doc = [];
84+
if (response !== undefined && ('inprog' in response)) {
85+
doc = response.inprog;
86+
}
6787
if (this.starting) { // Skip first to match charts
68-
this.starting = false;
88+
this.starting = false; // TODO: skip first error as well?
6989
return;
7090
}
71-
const doc = response.inprog;
7291
for (let i = 0; i < doc.length; i++) {
7392
if (toNS(doc[i].ns).specialish) {
7493
continue;
@@ -100,17 +119,16 @@ const CurrentOpStore = Reflux.createStore({
100119
});
101120
// Add current state to all
102121
this.allOps.push(totals);
103-
if (this.isPaused) {
104-
totals = this.allOps[this.endPause];
105-
} else {
106-
this.endPause = this.allOps.length;
107-
}
108-
// This handled by mouseover function completely
109-
if (this.inOverlay) {
110-
return;
111-
}
112-
} else if (error) {
113-
Actions.dbError({'op': 'currentOp', 'error': error });
122+
}
123+
if (this.isPaused) {
124+
totals = this.allOps[this.endPause];
125+
error = this.errored[this.endPause];
126+
} else {
127+
this.endPause = this.allOps.length;
128+
}
129+
// This handled by mouseover function completely
130+
if (this.inOverlay) {
131+
return;
114132
}
115133
this.trigger(error, totals);
116134
});

src/internal-packages/server-stats/lib/store/dberror-store.js

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const Reflux = require('reflux');
22
const Actions = require('../action');
3+
const translate = require('mongodb-js-errors').translate;
34
// const debug = require('debug')('mongodb-compass:server-stats:dberror-store');
45

56
const DBErrorStore = Reflux.createStore({
@@ -11,27 +12,47 @@ const DBErrorStore = Reflux.createStore({
1112
},
1213

1314
restart: function() {
14-
this.ops = {'top': null, 'currentOp': null, 'serverStatus': null};
15-
this.errors = {};
15+
this.ops = {top: null, currentOp: null, serverStatus: null};
16+
this.srcName = {top: 'Hottest Collections', currentOp: 'Slowest Operations', serverStatus: 'Stats Charts'};
1617
},
1718

18-
dbError: function(data) {
19-
// New or different error
20-
const err = data.error.name + ': ' + data.error.message;
21-
if (this.ops[data.op] !== err) {
22-
this.ops[data.op] = err;
23-
if (err in this.errors) {
24-
this.errors[err] = this.errors[err] + ', ' + data.op;
25-
} else {
26-
this.errors[err] = data.op;
27-
}
28-
const msg = [];
29-
for (let key in this.errors) { // eslint-disable-line prefer-const
30-
if (this.errors.hasOwnProperty( key ) ) {
31-
msg.push({'errorMsg': key, 'ops': this.errors[key], 'type': this.errors});
19+
/**
20+
* Translates the error message to something human readable. From data-service.
21+
*
22+
* @param {Error} error - The error.
23+
*
24+
* @returns {Error} The error with message translated.
25+
*/
26+
_translateMessage(error) {
27+
const mapping = translate(error);
28+
if (mapping) {
29+
error.message = mapping.message;
30+
}
31+
return error;
32+
},
33+
34+
publish: function() {
35+
const msg = [];
36+
for (let key in this.ops) { // eslint-disable-line prefer-const
37+
if (this.ops.hasOwnProperty( key ) ) {
38+
if (this.ops[key] !== null) {
39+
msg.push({errorMsg: this._translateMessage(this.ops[key]).message, ops: key, type: this.ops[key].name, srcName: this.srcName[key]});
3240
}
3341
}
34-
this.trigger(msg);
42+
}
43+
this.trigger(msg);
44+
},
45+
46+
dbError: function(data) {
47+
// Remove previous error
48+
if (this.ops[data.op] !== null && data.error === null) {
49+
this.ops[data.op] = data.error;
50+
this.publish();
51+
}
52+
// New error
53+
if (data.error !== null && this.ops[data.op] !== data.error) {
54+
this.ops[data.op] = data.error;
55+
this.publish();
3556
}
3657
}
3758

src/internal-packages/server-stats/lib/store/server-stats-graphs-store.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ const ServerStatsStore = Reflux.createStore({
1818

1919
serverStats: function() {
2020
app.dataService.serverstats((error, doc) => {
21-
this.trigger(error, doc, this.isPaused);
22-
if (error) {
23-
Actions.dbError({ 'op': 'serverStatus', 'error': error });
21+
if (error === null && this.error !== null) { // Trigger error removal
22+
Actions.dbError({'op': 'serverStatus', 'error': null });
23+
} else if (error !== null) {
24+
Actions.dbError({'op': 'serverStatus', 'error': error });
2425
}
26+
this.trigger(error, doc, this.isPaused);
2527
});
2628
},
2729

src/internal-packages/server-stats/lib/store/top-store.js

Lines changed: 36 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ const TopStore = Reflux.createStore({
2727

2828
restart: function() {
2929
this.allOps = [];
30+
this.errored = [];
3031
this.isPaused = false;
3132
this.endPause = 0;
3233
this.overlayIndex = 0;
3334
this.inOverlay = false;
3435
this.xLength = 60;
3536
this.starting = true;
36-
this.error = null;
3737
this.t1s = {};
3838
},
3939

@@ -45,31 +45,49 @@ const TopStore = Reflux.createStore({
4545
mouseOver: function(index) {
4646
const startPause = Math.max(this.endPause - this.xLength, 0);
4747
const visOps = this.allOps.slice(startPause, this.endPause);
48+
const visErrors = this.errored.slice(startPause, this.endPause);
4849
if (index >= visOps.length) {
4950
index = visOps.length - 1;
5051
}
5152
this.overlayIndex = index;
5253
this.inOverlay = true;
53-
this.trigger(null, visOps[this.overlayIndex]);
54+
this.trigger(visErrors[this.overlayIndex], visOps[this.overlayIndex]);
5455
},
5556

5657
mouseOut: function() {
5758
this.inOverlay = false;
5859
const startPause = Math.max(this.endPause - this.xLength, 0);
5960
const visOps = this.allOps.slice(startPause, this.endPause);
60-
this.trigger(this.error, visOps[visOps.length - 1]);
61+
const visErrors = this.errored.slice(startPause, this.endPause);
62+
this.trigger(visErrors[this.overlayIndex], visOps[visOps.length - 1]);
6163
},
6264

6365
// Calculate list as current hottest collection (like Cloud and system top)
6466
top_delta: function() {
6567
app.dataService.top((error, response) => {
66-
const numCores = app.instance.host.cpu_cores;
67-
const cadence = 1000000; // Can safetly assume we're polling 1x/sec TODO
68-
const t2s = {};
68+
// Trigger error banner changes
69+
if (error === null && this.errored.length > 0 && this.errored[this.errored.length - 1] !== null) { // Trigger error removal
70+
Actions.dbError({'op': 'top', 'error': null });
71+
} else if (error !== null) {
72+
Actions.dbError({'op': 'top', 'error': error });
73+
}
74+
this.errored.push(error);
75+
// Update op list if error
76+
if (error !== null || this.starting) {
77+
this.allOps.push([]);
78+
}
79+
80+
// Update op list if no error
6981
let totals = [];
70-
this.error = error;
71-
if (!error && response !== undefined && ('totals' in response)) {
72-
const doc = response.totals;
82+
if (error === null) {
83+
// If response is empty, send empty list
84+
let doc = {};
85+
if (response !== undefined && ('totals' in response)) {
86+
doc = response.totals;
87+
}
88+
const numCores = app.instance.host.cpu_cores;
89+
const cadence = 1000000; // Can safetly assume we're polling 1x/sec TODO
90+
const t2s = {};
7391
for (let collname in doc) { // eslint-disable-line prefer-const
7492
// Ignore special collections
7593
if (!doc.hasOwnProperty(collname) || collname === 'note' || toNS(collname).specialish) {
@@ -119,75 +137,16 @@ const TopStore = Reflux.createStore({
119137
});
120138
// Add current state to all
121139
this.allOps.push(totals);
122-
if (this.isPaused) {
123-
totals = this.allOps[this.endPause];
124-
} else {
125-
this.endPause = this.allOps.length;
126-
}
127-
// This handled by mouseover function completely
128-
if (this.inOverlay) {
129-
return;
130-
}
131-
} else if (error) {
132-
Actions.dbError({ 'op': 'top', 'error': error });
133140
}
134-
this.trigger(error, totals);
135-
});
136-
},
137-
138-
// Calculate list as all-time hottest collections
139-
top: function() {
140-
app.dataService.top((error, response) => {
141-
let totals = [];
142-
this.error = error;
143-
if (!error && response !== undefined && ('totals' in response)) {
144-
if (this.starting) { // Skip first to match charts
145-
this.starting = false;
146-
return;
147-
}
148-
const doc = response.totals;
149-
let totalTime = 0;
150-
for (let collname in doc) { // eslint-disable-line prefer-const
151-
if (!doc.hasOwnProperty(collname) || collname === 'note' || toNS(collname).specialish) {
152-
continue;
153-
}
154-
const subdoc = doc[collname];
155-
if (!('readLock' in subdoc) || !('writeLock' in subdoc) || !('total' in subdoc)) {
156-
debug('Error: top response from DB missing fields', subdoc);
157-
}
158-
totals.push({
159-
'collectionName': collname,
160-
'loadPercentR': (subdoc.readLock.time / subdoc.total.time) * 100,
161-
'loadPerfectL': (subdoc.writeLock.time / subdoc.total.time) * 100,
162-
'loadPercent': subdoc.total.time
163-
});
164-
totalTime += subdoc.total.time;
165-
}
166-
for (let i = 0; i < totals.length; i++) {
167-
totals[i].loadPercent = _.round((totals[i].loadPercent / totalTime) * 100, 0);
168-
}
169-
for (let i = totals.length - 1; i >= 0; i--) {
170-
if (!totals[i].loadPercent) {
171-
totals.splice(i, 1);
172-
}
173-
}
174-
totals.sort(function(a, b) {
175-
const f = (b.loadPercent < a.loadPercent) ? -1 : 0;
176-
return (a.loadPercent < b.loadPercent) ? 1 : f;
177-
});
178-
// Add current state to all
179-
this.allOps.push(totals);
180-
if (this.isPaused) {
181-
totals = this.allOps[this.endPause];
182-
} else {
183-
this.endPause = this.allOps.length;
184-
}
185-
// This handled by mouseover function completely
186-
if (this.inOverlay) {
187-
return;
188-
}
189-
} else if (error) {
190-
Actions.dbError({ 'op': 'top', 'error': error });
141+
if (this.isPaused) {
142+
totals = this.allOps[this.endPause];
143+
error = this.errored[this.endPause];
144+
} else {
145+
this.endPause = this.allOps.length;
146+
}
147+
// This handled by mouseover function completely
148+
if (this.inOverlay) {
149+
return;
191150
}
192151
this.trigger(error, totals);
193152
});

0 commit comments

Comments
 (0)