You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tez.apache.org by sr...@apache.org on 2016/06/25 12:20:57 UTC
tez git commit: TEZ-3288. Tez UI: Display more details in the error
bar (sree)
Repository: tez
Updated Branches:
refs/heads/master 1264d5d01 -> 2c22e23a7
TEZ-3288. Tez UI: Display more details in the error bar (sree)
Project: http://git-wip-us.apache.org/repos/asf/tez/repo
Commit: http://git-wip-us.apache.org/repos/asf/tez/commit/2c22e23a
Tree: http://git-wip-us.apache.org/repos/asf/tez/tree/2c22e23a
Diff: http://git-wip-us.apache.org/repos/asf/tez/diff/2c22e23a
Branch: refs/heads/master
Commit: 2c22e23a738a7764aa8d53ca7e2bcba7d7053337
Parents: 1264d5d
Author: Sreenath Somarajapuram <sr...@apache.org>
Authored: Sat Jun 25 17:49:55 2016 +0530
Committer: Sreenath Somarajapuram <sr...@apache.org>
Committed: Sat Jun 25 17:49:55 2016 +0530
----------------------------------------------------------------------
CHANGES.txt | 1 +
tez-ui/src/main/webapp/app/adapters/abstract.js | 67 ++++++--
tez-ui/src/main/webapp/app/adapters/loader.js | 3 +-
.../src/main/webapp/app/components/error-bar.js | 51 +------
.../src/main/webapp/app/initializers/jquery.js | 4 -
.../src/main/webapp/app/styles/error-bar.less | 17 ++-
.../app/templates/components/error-bar.hbs | 18 ++-
tez-ui/src/main/webapp/package.json | 2 +-
.../integration/components/error-bar-test.js | 86 ++++++++++-
.../webapp/tests/unit/adapters/abstract-test.js | 151 +++++++++++++++++++
.../webapp/tests/unit/adapters/loader-test.js | 2 +
11 files changed, 328 insertions(+), 74 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tez/blob/2c22e23a/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index bb130ef..640d957 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -58,6 +58,7 @@ ALL CHANGES:
TEZ-3281. Tez UI: Swimlane improvements
TEZ-3264. Tez UI: UI discrepancies
TEZ-3292. Tez UI: UTs breaking with timezone change
+ TEZ-3288. Tez UI: Display more details in the error bar
Release 0.8.4: Unreleased
http://git-wip-us.apache.org/repos/asf/tez/blob/2c22e23a/tez-ui/src/main/webapp/app/adapters/abstract.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/adapters/abstract.js b/tez-ui/src/main/webapp/app/adapters/abstract.js
index 121d4ee..9a7dcae 100644
--- a/tez-ui/src/main/webapp/app/adapters/abstract.js
+++ b/tez-ui/src/main/webapp/app/adapters/abstract.js
@@ -53,18 +53,63 @@ export default LoaderAdapter.extend({
return path;
},
- normalizeErrorResponse: function(status, headers, payload) {
- var response;
-
- if(payload && payload.exception && !payload.errors) {
- payload = `${payload.exception}\n${payload.message}\n${payload.javaClassName}`;
- response = this._super(status, headers, payload);
- }
- else {
- response = this._super(status, headers, payload);
- Ember.set(response, '0.title', this.get("outOfReachMessage"));
+ normalizeErrorResponse: function (status, headers, payload) {
+ var title;
+ switch(typeof payload) {
+ case "object":
+ title = payload.message;
+ break;
+ case "string":
+ let html = Ember.$(payload.bold());
+ html.find('script').remove();
+ html.find('style').remove();
+ payload = html.text().trim();
+ break;
}
- return response;
+ return [{
+ title: title,
+ status: status,
+ headers: headers,
+ detail: payload
+ }];
+ },
+
+ _loaderAjax: function (url, queryParams, namespace) {
+ var requestInfo = {
+ adapterName: this.get("name"),
+ url: url
+ },
+ that = this;
+
+ return this._super(url, queryParams, namespace).catch(function (error) {
+ var message = `${error.message} �`,
+ status = Ember.get(error, "errors.0.status");
+
+ if(status === 0) {
+ let outOfReachMessage = that.get("outOfReachMessage");
+ message = `${message} ${outOfReachMessage}`;
+ }
+ else {
+ let title = Ember.get(error, "errors.0.title") || `Error accessing ${url}`;
+ message = `${message} ${status}: ${title}`;
+ }
+
+ requestInfo.responseHeaders = Ember.get(error, "errors.0.headers");
+ if(queryParams) {
+ requestInfo.queryParams = queryParams;
+ }
+ if(namespace) {
+ requestInfo.namespace = namespace;
+ }
+
+ Ember.setProperties(error, {
+ message: message,
+ details: Ember.get(error, "errors.0.detail"),
+ requestInfo: requestInfo
+ });
+
+ throw(error);
+ });
}
});
http://git-wip-us.apache.org/repos/asf/tez/blob/2c22e23a/tez-ui/src/main/webapp/app/adapters/loader.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/adapters/loader.js b/tez-ui/src/main/webapp/app/adapters/loader.js
index f63bd07..5000bea 100644
--- a/tez-ui/src/main/webapp/app/adapters/loader.js
+++ b/tez-ui/src/main/webapp/app/adapters/loader.js
@@ -18,10 +18,11 @@
*/
import DS from 'ember-data';
+import NameMixin from '../mixins/name';
var MoreString = more.String;
-export default DS.RESTAdapter.extend({
+export default DS.RESTAdapter.extend(NameMixin, {
_isLoader: true,
buildURL: function(modelName, id, snapshot, requestType, query, params) {
http://git-wip-us.apache.org/repos/asf/tez/blob/2c22e23a/tez-ui/src/main/webapp/app/components/error-bar.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/components/error-bar.js b/tez-ui/src/main/webapp/app/components/error-bar.js
index 1086010..d562614 100644
--- a/tez-ui/src/main/webapp/app/components/error-bar.js
+++ b/tez-ui/src/main/webapp/app/components/error-bar.js
@@ -26,57 +26,21 @@ export default Ember.Component.extend({
visible: false,
detailsAvailable: false,
+ showDetails: false,
+ displayTimerId: 0,
classNames: ['error-bar'],
classNameBindings: ['visible', 'detailsAvailable'],
- code: null,
message: null,
- details: null,
- stack: null,
- showDetails: false,
-
- displayTimerId: 0,
-
- _errorObserver: Ember.observer("error", function () {
- var error = this.get("error"),
-
- code = Ember.get(error, "errors.0.status"),
- title = Ember.get(error, "errors.0.title"),
- message = error.message || "Error",
- details = Ember.get(error, "errors.0.detail") || "",
- stack = error.stack,
- lineEndIndex = Math.min(message.indexOf('\n'), message.indexOf('<br'));
-
- if(code === "0") {
- code = "";
- }
-
- if(title) {
- message += ". " + title;
- }
-
- if(lineEndIndex > 0) {
- if(details) {
- details = "\n" + details;
- }
- details = message.substr(lineEndIndex) + details;
- message = message.substr(0, lineEndIndex);
- }
-
- if(details) {
- details += "\n";
- }
+ _errorObserver: Ember.on("init", Ember.observer("error", function () {
+ var error = this.get("error");
if(error) {
this.setProperties({
- code: code,
- message: message,
- details: details,
- stack: stack,
-
- detailsAvailable: !!(details || stack),
+ message: error.message || "Error",
+ detailsAvailable: !!(error.details || error.requestInfo || error.stack),
visible: true
});
@@ -86,7 +50,7 @@ export default Ember.Component.extend({
else {
this.close();
}
- }),
+ })),
clearTimer: function () {
clearTimeout(this.get("displayTimerId"));
@@ -105,5 +69,4 @@ export default Ember.Component.extend({
this.close();
}
}
-
});
http://git-wip-us.apache.org/repos/asf/tez/blob/2c22e23a/tez-ui/src/main/webapp/app/initializers/jquery.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/initializers/jquery.js b/tez-ui/src/main/webapp/app/initializers/jquery.js
index 2c34b1d..37ebc4d 100644
--- a/tez-ui/src/main/webapp/app/initializers/jquery.js
+++ b/tez-ui/src/main/webapp/app/initializers/jquery.js
@@ -24,10 +24,6 @@ export function initialize(/* application */) {
tooltipClass: 'generic-tooltip'
});
- Ember.$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
- jqXHR.requestOptions = originalOptions;
- });
-
Ember.$.ajaxSetup({
cache: false
});
http://git-wip-us.apache.org/repos/asf/tez/blob/2c22e23a/tez-ui/src/main/webapp/app/styles/error-bar.less
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/styles/error-bar.less b/tez-ui/src/main/webapp/app/styles/error-bar.less
index dec2100..56d2b88 100644
--- a/tez-ui/src/main/webapp/app/styles/error-bar.less
+++ b/tez-ui/src/main/webapp/app/styles/error-bar.less
@@ -44,22 +44,31 @@
color: @text-red;
.message, .details {
- overflow: scroll;
- max-height: 100px;
-
+ max-height: 150px;
text-align: left;
}
+ .message {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ margin-right: 30px;
+ }
+
.details {
display: none;
visibility: hidden;
+ overflow: scroll;
margin-bottom: 10px;
border-top: 1px @border-lite solid;
.force-scrollbar;
- white-space: pre-line;
+
+ p {
+ white-space: pre-wrap;
+ }
&.visible {
display: block;
http://git-wip-us.apache.org/repos/asf/tez/blob/2c22e23a/tez-ui/src/main/webapp/app/templates/components/error-bar.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/components/error-bar.hbs b/tez-ui/src/main/webapp/app/templates/components/error-bar.hbs
index a21bba0..fe5d44d 100644
--- a/tez-ui/src/main/webapp/app/templates/components/error-bar.hbs
+++ b/tez-ui/src/main/webapp/app/templates/components/error-bar.hbs
@@ -18,14 +18,22 @@
<div class="message" {{action "toggleDetailsDisplay"}}>
<i class="fa fa-exclamation-circle"></i>
- {{#if code}}
- <b>{{code}}</b> :
- {{/if}}
{{message}}
<i class="show-details fa {{if showDetails 'fa-minus-circle' 'fa-plus-circle'}}"></i>
</div>
-<div class="details {{if showDetails "visible"}}">{{{details}}}{{#if stack}}<b>Stack:</b>
- {{stack}}
+
+<div class="details {{if showDetails "visible"}}">
+ {{#if error.details}}
+ <b>Details:</b>
+ <p>{{txt error.details type="json"}}</p>
+ {{/if}}
+ {{#if error.requestInfo}}
+ <b>Request:</b>
+ <p>{{txt error.requestInfo type="json"}}</p>
+ {{/if}}
+ {{#if error.stack}}
+ <b>Stack:</b>
+ <p>{{error.stack}}</p>
{{/if}}
</div>
<i class="close-button fa fa-arrow-circle-down" {{action "close"}}></i>
http://git-wip-us.apache.org/repos/asf/tez/blob/2c22e23a/tez-ui/src/main/webapp/package.json
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/package.json b/tez-ui/src/main/webapp/package.json
index 15a77e4..e5c3279 100644
--- a/tez-ui/src/main/webapp/package.json
+++ b/tez-ui/src/main/webapp/package.json
@@ -57,7 +57,7 @@
"phantomjs": "1.9.19"
},
"dependencies": {
- "em-helpers": "0.5.10",
+ "em-helpers": "0.5.13",
"em-table": "0.3.14",
"em-tgraph": "0.0.5"
}
http://git-wip-us.apache.org/repos/asf/tez/blob/2c22e23a/tez-ui/src/main/webapp/tests/integration/components/error-bar-test.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/tests/integration/components/error-bar-test.js b/tez-ui/src/main/webapp/tests/integration/components/error-bar-test.js
index 10c6c7d..f736b45 100644
--- a/tez-ui/src/main/webapp/tests/integration/components/error-bar-test.js
+++ b/tez-ui/src/main/webapp/tests/integration/components/error-bar-test.js
@@ -19,15 +19,13 @@
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
+import wait from 'ember-test-helpers/wait';
+
moduleForComponent('error-bar', 'Integration | Component | error bar', {
integration: true
});
test('Basic creation test', function(assert) {
-
- // Set any properties with this.set('myProperty', 'value');
- // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
-
this.render(hbs`{{error-bar}}`);
assert.equal(this.$().text().trim(), '');
@@ -41,3 +39,83 @@ test('Basic creation test', function(assert) {
assert.equal(this.$().text().trim(), '');
});
+
+test('Plain Object test', function(assert) {
+ Function.prototype.bind = function () {};
+
+ this.set("error", {});
+ this.render(hbs`{{error-bar error=error}}`);
+
+ return wait().then(() => {
+ assert.equal(this.$().text().trim(), 'Error');
+ });
+});
+
+test('Message test', function(assert) {
+ var testMessage = "Test Message";
+
+ Function.prototype.bind = function () {};
+
+ this.set("error", {
+ message: testMessage
+ });
+ this.render(hbs`{{error-bar error=error}}`);
+
+ return wait().then(() => {
+ assert.equal(this.$().text().trim(), testMessage);
+ });
+});
+
+test('details test', function(assert) {
+ var testMessage = "Test Message",
+ testDetails = "details";
+
+ Function.prototype.bind = function () {};
+
+ this.set("error", {
+ message: testMessage,
+ details: testDetails
+ });
+ this.render(hbs`{{error-bar error=error}}`);
+
+ return wait().then(() => {
+ assert.equal(this.$(".message").text().trim(), testMessage);
+ assert.equal(this.$(".details p").text().trim(), testDetails);
+ });
+});
+
+test('requestInfo test', function(assert) {
+ var testMessage = "Test Message",
+ testInfo = "info";
+
+ Function.prototype.bind = function () {};
+
+ this.set("error", {
+ message: testMessage,
+ requestInfo: testInfo
+ });
+ this.render(hbs`{{error-bar error=error}}`);
+
+ return wait().then(() => {
+ assert.equal(this.$(".message").text().trim(), testMessage);
+ assert.equal(this.$(".details p").text().trim(), testInfo);
+ });
+});
+
+test('stack test', function(assert) {
+ var testMessage = "Test Message",
+ testStack = "stack";
+
+ Function.prototype.bind = function () {};
+
+ this.set("error", {
+ message: testMessage,
+ stack: testStack
+ });
+ this.render(hbs`{{error-bar error=error}}`);
+
+ return wait().then(() => {
+ assert.equal(this.$(".message").text().trim(), testMessage);
+ assert.equal(this.$(".details p").text().trim(), testStack);
+ });
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/2c22e23a/tez-ui/src/main/webapp/tests/unit/adapters/abstract-test.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/tests/unit/adapters/abstract-test.js b/tez-ui/src/main/webapp/tests/unit/adapters/abstract-test.js
index 5ff39e7..24ba624 100644
--- a/tez-ui/src/main/webapp/tests/unit/adapters/abstract-test.js
+++ b/tez-ui/src/main/webapp/tests/unit/adapters/abstract-test.js
@@ -16,6 +16,8 @@
* limitations under the License.
*/
+import Ember from 'ember';
+
import { moduleFor, test } from 'ember-qunit';
moduleFor('adapter:abstract', 'Unit | Adapter | abstract', {
@@ -35,6 +37,9 @@ test('Basic creation test', function(assert) {
assert.ok(adapter.ajaxOptions);
assert.ok(adapter.pathForType);
+
+ assert.ok(adapter.normalizeErrorResponse);
+ assert.ok(adapter._loaderAjax);
});
test('host, namespace & pathTypeHash test', function(assert) {
@@ -108,3 +113,149 @@ test('pathForType test', function(assert) {
adapter.pathForType("noType");
});
});
+
+test('normalizeErrorResponse test', function(assert) {
+ let adapter = this.subject(),
+ status = "200",
+ testTitle = "title",
+ strPayload = "StringPayload",
+ objPayload = {x: 1, message: testTitle},
+ testHeaders = {},
+ response;
+
+ response = adapter.normalizeErrorResponse(status, testHeaders, strPayload);
+ assert.equal(response[0].title, undefined);
+ assert.equal(response[0].status, status);
+ assert.equal(response[0].detail, strPayload);
+ assert.equal(response[0].headers, testHeaders);
+
+ response = adapter.normalizeErrorResponse(status, testHeaders, objPayload);
+ assert.equal(response[0].title, testTitle);
+ assert.equal(response[0].status, status);
+ assert.deepEqual(response[0].detail, objPayload);
+ assert.equal(response[0].headers, testHeaders);
+});
+
+test('normalizeErrorResponse html payload test', function(assert) {
+ let adapter = this.subject(),
+ status = "200",
+ htmlPayload = "StringPayload <b>boldText</b> <script>scriptText</script> <style>styleText</style>",
+ testHeaders = {},
+ response;
+
+ response = adapter.normalizeErrorResponse(status, testHeaders, htmlPayload);
+ assert.equal(response[0].detail, "StringPayload boldText");
+});
+
+test('_loaderAjax resolve test', function(assert) {
+ let result = {},
+ adapter = this.subject({
+ ajax: function () {
+ assert.ok(1);
+ return Ember.RSVP.resolve(result);
+ }
+ });
+
+ assert.expect(1 + 1);
+
+ adapter._loaderAjax().then(function (val) {
+ assert.equal(val.data, result);
+ });
+});
+
+test('_loaderAjax reject, without title test', function(assert) {
+ let errorInfo = {
+ status: "500",
+ detail: "testDetails"
+ },
+ msg = "Msg",
+ testUrl = "http://foo.bar",
+ testQuery = {},
+ testNS = "namespace",
+ adapter = this.subject({
+ outOfReachMessage: "OutOfReach",
+ ajax: function () {
+ assert.ok(1);
+ return Ember.RSVP.reject({
+ message: msg,
+ errors:[errorInfo]
+ });
+ }
+ });
+
+ assert.expect(1 + 7);
+
+ adapter._loaderAjax(testUrl, testQuery, testNS).catch(function (val) {
+ assert.equal(val.message, `${msg} � ${errorInfo.status}: Error accessing ${testUrl}`);
+ assert.equal(val.details, errorInfo.detail);
+ assert.equal(val.requestInfo.adapterName, "abstract");
+ assert.equal(val.requestInfo.url, testUrl);
+
+ assert.equal(val.requestInfo.queryParams, testQuery);
+ assert.equal(val.requestInfo.namespace, testNS);
+
+ assert.ok(val.requestInfo.hasOwnProperty("responseHeaders"));
+ });
+});
+
+test('_loaderAjax reject, with title test', function(assert) {
+ let errorInfo = {
+ status: "500",
+ title: "Server Error",
+ detail: "testDetails"
+ },
+ msg = "Msg",
+ testUrl = "url",
+ adapter = this.subject({
+ outOfReachMessage: "OutOfReach",
+ ajax: function () {
+ assert.ok(1);
+ return Ember.RSVP.reject({
+ message: msg,
+ errors:[errorInfo]
+ });
+ }
+ });
+
+ assert.expect(1 + 5);
+
+ adapter._loaderAjax(testUrl).catch(function (val) {
+ assert.equal(val.message, `${msg} � ${errorInfo.status}: ${errorInfo.title}`);
+ assert.equal(val.details, errorInfo.detail);
+ assert.equal(val.requestInfo.adapterName, "abstract");
+ assert.equal(val.requestInfo.url, testUrl);
+
+ assert.ok(val.requestInfo.hasOwnProperty("responseHeaders"));
+ });
+});
+
+test('_loaderAjax reject, status 0 test', function(assert) {
+ let errorInfo = {
+ status: 0,
+ title: "Server Error",
+ detail: "testDetails"
+ },
+ msg = "Msg",
+ testUrl = "url",
+ adapter = this.subject({
+ outOfReachMessage: "OutOfReach",
+ ajax: function () {
+ assert.ok(1);
+ return Ember.RSVP.reject({
+ message: msg,
+ errors:[errorInfo]
+ });
+ }
+ });
+
+ assert.expect(1 + 5);
+
+ adapter._loaderAjax(testUrl).catch(function (val) {
+ assert.equal(val.message, `${msg} � ${adapter.outOfReachMessage}`);
+ assert.equal(val.details, errorInfo.detail);
+ assert.equal(val.requestInfo.adapterName, "abstract");
+ assert.equal(val.requestInfo.url, testUrl);
+
+ assert.ok(val.requestInfo.hasOwnProperty("responseHeaders"));
+ });
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/2c22e23a/tez-ui/src/main/webapp/tests/unit/adapters/loader-test.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/tests/unit/adapters/loader-test.js b/tez-ui/src/main/webapp/tests/unit/adapters/loader-test.js
index 7b4a2df..e8e0428 100644
--- a/tez-ui/src/main/webapp/tests/unit/adapters/loader-test.js
+++ b/tez-ui/src/main/webapp/tests/unit/adapters/loader-test.js
@@ -34,6 +34,8 @@ test('Basic creation', function(assert) {
assert.ok(adapter._loaderAjax);
assert.ok(adapter.queryRecord);
assert.ok(adapter.query);
+
+ assert.equal(adapter.get("name"), "loader");
});
test('buildURL test', function(assert) {