YARN-5705. Show timeline data from ATS v2 in new web UI. Contributed by Akhil PB.
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/46d9c4ca Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/46d9c4ca Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/46d9c4ca Branch: refs/heads/trunk Commit: 46d9c4ca7aba04e96bea65d7b95cc84b50af6980 Parents: c80d3bc Author: Sunil G <sun...@apache.org> Authored: Sun May 21 18:09:13 2017 +0530 Committer: Sunil G <sun...@apache.org> Committed: Sun May 21 18:09:13 2017 +0530 ---------------------------------------------------------------------- .../webapp/app/adapters/yarn-app-attempt.js | 4 +- .../webapp/app/adapters/yarn-app-flowrun.js | 33 +++ .../webapp/app/adapters/yarn-app-timeline.js | 35 +++ .../main/webapp/app/adapters/yarn-container.js | 18 +- .../src/main/webapp/app/adapters/yarn-entity.js | 35 +++ .../webapp/app/adapters/yarn-flow-activity.js | 30 +++ .../webapp/app/adapters/yarn-flowrun-brief.js | 32 +++ .../main/webapp/app/adapters/yarn-flowrun.js | 38 +++ .../app/adapters/yarn-timeline-appattempt.js | 41 +++ .../app/adapters/yarn-timeline-container.js | 40 +++ .../main/webapp/app/components/nodes-heatmap.js | 18 +- .../webapp/app/components/simple-bar-chart.js | 206 +++++++++++++++ .../webapp/app/components/sunburst-chart.js | 261 +++++++++++++++++++ .../webapp/app/controllers/yarn-apps/apps.js | 1 - .../app/controllers/yarn-apps/services.js | 1 - .../app/controllers/yarn-flow-activity.js | 125 +++++++++ .../main/webapp/app/controllers/yarn-flow.js | 36 +++ .../webapp/app/controllers/yarn-flow/info.js | 66 +++++ .../webapp/app/controllers/yarn-flow/runs.js | 178 +++++++++++++ .../main/webapp/app/controllers/yarn-flowrun.js | 50 ++++ .../webapp/app/controllers/yarn-flowrun/info.js | 157 +++++++++++ .../app/controllers/yarn-flowrun/metrics.js | 126 +++++++++ .../webapp/app/controllers/yarn-services.js | 12 +- .../src/main/webapp/app/mixins/app-attempt.js | 66 +++++ .../main/webapp/app/models/yarn-app-attempt.js | 11 +- .../main/webapp/app/models/yarn-app-flowrun.js | 52 ++++ .../main/webapp/app/models/yarn-app-timeline.js | 105 ++++++++ .../main/webapp/app/models/yarn-container.js | 9 +- .../src/main/webapp/app/models/yarn-entity.js | 26 ++ .../webapp/app/models/yarn-flow-activity.js | 28 ++ .../webapp/app/models/yarn-flowrun-brief.js | 70 +++++ .../src/main/webapp/app/models/yarn-flowrun.js | 32 +++ .../app/models/yarn-timeline-appattempt.js | 143 ++++++++++ .../app/models/yarn-timeline-container.js | 63 +++++ .../src/main/webapp/app/router.js | 12 + .../main/webapp/app/routes/timeline-error.js | 29 +++ .../main/webapp/app/routes/yarn-app-attempt.js | 32 +-- .../main/webapp/app/routes/yarn-app-attempts.js | 13 +- .../src/main/webapp/app/routes/yarn-app.js | 18 +- .../webapp/app/routes/yarn-flow-activity.js | 37 +++ .../src/main/webapp/app/routes/yarn-flow.js | 53 ++++ .../main/webapp/app/routes/yarn-flow/info.js | 22 ++ .../main/webapp/app/routes/yarn-flow/runs.js | 22 ++ .../webapp/app/routes/yarn-flowrun-metric.js | 107 ++++++++ .../src/main/webapp/app/routes/yarn-flowrun.js | 58 +++++ .../main/webapp/app/routes/yarn-flowrun/info.js | 22 ++ .../webapp/app/routes/yarn-flowrun/metrics.js | 22 ++ .../webapp/app/serializers/yarn-app-flowrun.js | 64 +++++ .../webapp/app/serializers/yarn-app-timeline.js | 76 ++++++ .../src/main/webapp/app/serializers/yarn-app.js | 3 +- .../main/webapp/app/serializers/yarn-entity.js | 51 ++++ .../app/serializers/yarn-flow-activity.js | 54 ++++ .../app/serializers/yarn-flowrun-brief.js | 64 +++++ .../main/webapp/app/serializers/yarn-flowrun.js | 63 +++++ .../main/webapp/app/serializers/yarn-queue.js | 22 +- .../app/serializers/yarn-timeline-appattempt.js | 69 +++++ .../app/serializers/yarn-timeline-container.js | 71 +++++ .../src/main/webapp/app/styles/app.css | 83 ++++++ .../main/webapp/app/templates/application.hbs | 6 +- .../webapp/app/templates/timeline-error.hbs | 22 ++ .../webapp/app/templates/yarn-app-attempt.hbs | 46 ++-- .../webapp/app/templates/yarn-app-attempts.hbs | 7 +- .../src/main/webapp/app/templates/yarn-app.hbs | 51 +--- .../src/main/webapp/app/templates/yarn-apps.hbs | 4 +- .../webapp/app/templates/yarn-flow-activity.hbs | 45 ++++ .../src/main/webapp/app/templates/yarn-flow.hbs | 49 ++++ .../webapp/app/templates/yarn-flow/info.hbs | 53 ++++ .../webapp/app/templates/yarn-flow/runs.hbs | 131 ++++++++++ .../app/templates/yarn-flowrun-metric.hbs | 34 +++ .../main/webapp/app/templates/yarn-flowrun.hbs | 49 ++++ .../webapp/app/templates/yarn-flowrun/info.hbs | 128 +++++++++ .../app/templates/yarn-flowrun/metrics.hbs | 34 +++ .../main/webapp/app/templates/yarn-services.hbs | 2 +- .../src/main/webapp/app/utils/converter.js | 22 +- .../src/main/webapp/app/utils/error-utils.js | 58 +++++ .../src/main/webapp/config/default-config.js | 3 +- .../hadoop-yarn-ui/src/main/webapp/package.json | 1 + .../components/simple-bar-chart-test.js | 43 +++ .../unit/adapters/yarn-app-timeline-test.js | 30 +++ .../adapters/yarn-timeline-appattempt-test.js | 30 +++ .../adapters/yarn-timeline-container-test.js | 30 +++ .../unit/controllers/yarn-flow/info-test.js | 30 +++ .../unit/controllers/yarn-flow/runs-test.js | 30 +++ .../unit/controllers/yarn-flowrun/info-test.js | 30 +++ .../controllers/yarn-flowrun/metrics-test.js | 30 +++ .../tests/unit/mixins/app-attempt-test.js | 30 +++ .../webapp/tests/unit/mixins/charts-test.js | 30 --- .../tests/unit/models/yarn-app-timeline-test.js | 30 +++ .../models/yarn-timeline-appattempt-test.js | 30 +++ .../unit/models/yarn-timeline-container-test.js | 30 +++ .../tests/unit/routes/timeline-error-test.js | 29 +++ .../tests/unit/routes/yarn-flow/info-test.js | 29 +++ .../tests/unit/routes/yarn-flow/runs-test.js | 29 +++ .../tests/unit/routes/yarn-flowrun/info-test.js | 29 +++ .../unit/routes/yarn-flowrun/metrics-test.js | 29 +++ .../unit/serializers/yarn-app-timeline-test.js | 33 +++ .../yarn-timeline-appattempt-test.js | 33 +++ .../serializers/yarn-timeline-container-test.js | 33 +++ 98 files changed, 4408 insertions(+), 199 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js index 2389f16..d5f3d0c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js @@ -26,7 +26,9 @@ export default AbstractAdapter.extend({ urlForQuery(query/*, modelName*/) { var url = this._buildURL(); - return url + '/apps/' + query.appId + "/appattempts"; + var appId = query.appId; + delete query.appId; + return url + '/apps/' + appId + "/appattempts"; }, urlForFindRecord(id/*, modelName, snapshot*/) { http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.js new file mode 100644 index 0000000..23ecd1b --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.js @@ -0,0 +1,33 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQuery(query/*, modelName*/){ + var url = this._buildURL(); + var flowrunUid = query['flowrunUid']; + delete query.flowrunUid; + url = url + '/run-uid/' + flowrunUid + '/apps?fields=ALL'; + return url; + } +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-timeline.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-timeline.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-timeline.js new file mode 100644 index 0000000..831649c --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-timeline.js @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForFindRecord(id/*, modelName, snapshot*/) { + var url = this._buildURL(); + url = url + '/apps/' + id + '?fields=ALL'; + return url; + }, + + pathForType(/*modelName*/) { + return 'apps'; + } +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js index 348a805..476c9be 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js @@ -25,31 +25,17 @@ export default DS.JSONAPIAdapter.extend({ }, host: function() { - return undefined; + return this.get(`hosts.rmWebAddress`); }.property(), namespace: function() { - return undefined; + return this.get(`env.app.namespaces.cluster`); }.property(), urlForQuery(query/*, modelName*/) { - var rmHosts = this.get(`hosts.rmWebAddress`); - var tsHosts = this.get(`hosts.timelineWebAddress`); - var rmNamespaces = this.get(`env.app.namespaces.cluster`); - var tsNamespaces = this.get(`env.app.namespaces.timeline`); - - if (query.is_rm) { - this.set("host", rmHosts); - this.set("namespace", rmNamespaces); - } else { - this.set("host", tsHosts); - this.set("namespace", tsNamespaces); - } - var url = this._buildURL(); url = url + '/apps/' + Converter.attemptIdToAppId(query.app_attempt_id) + "/appattempts/" + query.app_attempt_id + "/containers"; - console.log(url); return url; }, http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.js new file mode 100644 index 0000000..3d7338f --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.js @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQuery(query/*, modelName*/){ + var url = this._buildURL(); + var appUid = query.app_uid; + var entityType = query.entity_type; + delete query.app_uid; + delete query.entity_type; + url = url + '/app-uid/' + appUid + '/entities/' + entityType + '?fields=INFO'; + return url; + } +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flow-activity.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flow-activity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flow-activity.js new file mode 100644 index 0000000..a8c436a --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flow-activity.js @@ -0,0 +1,30 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + pathForType(/*modelName*/) { + return 'flows'; // move to some common place, return path by modelname. + }, +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js new file mode 100644 index 0000000..ea9c6cb --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQuery(query/*, modelName*/){ + var url = this._buildURL(); + var flowuid = query['flowuid']; + delete query.flowuid; + return url + '/flow-uid/' + flowuid + '/runs?fields=ALL'; + }, +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.js new file mode 100644 index 0000000..9163c83 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.js @@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQueryRecord(query/*, modelName*/){ + var url = this._buildURL(); + var flowrunuid = query.flowrun_uid; + delete query.flowrun_uid; + url = url + '/run-uid/' + flowrunuid; + return url; + }, + + pathForType(/*modelName*/) { + return 'run-uid'; // move to some common place, return path by modelname. + } +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-appattempt.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-appattempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-appattempt.js new file mode 100644 index 0000000..2557a86 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-appattempt.js @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbstractAdapter from './abstract'; +import Converter from 'yarn-ui/utils/converter'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQuery(query/*, modelName*/) { + var url = this._buildURL(); + var appId = query.appId; + query.fields = 'ALL'; + delete query.appId; + return url + '/apps/' + appId + "/entities/YARN_APPLICATION_ATTEMPT"; + }, + + urlForFindRecord(id/*, modelName, snapshot*/) { + var url = this._buildURL(); + return url + '/apps/' + Converter.attemptIdToAppId(id) + + "/entities/YARN_APPLICATION_ATTEMPT/" + id + "?fields=ALL"; + } + +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.js new file mode 100644 index 0000000..f47335a --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.js @@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbstractAdapter from './abstract'; +import Converter from 'yarn-ui/utils/converter'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQuery(query/*, modelName*/){ + var url = this._buildURL(); + var app_attempt_id = query.app_attempt_id; + query.fields = 'ALL'; + delete query.app_attempt_id; + url = url + '/apps/' + Converter.attemptIdToAppId(app_attempt_id) + + '/entities/YARN_CONTAINER'; + return url; + }, + + pathForType(/*modelName*/) { + return ''; + } +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js index ef6e46e..3acc5de 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js @@ -52,7 +52,7 @@ export default BaseChartComponent.extend({ bindSelectCategory: function(element, i) { element.on("click", function() { - if (this.selectedCategory == i) { + if (this.selectedCategory === i) { // Remove selection for second click this.selectedCategory = 0; } else { @@ -76,7 +76,7 @@ export default BaseChartComponent.extend({ } var usage = node.get("usedMemoryMB") / - (node.get("usedMemoryMB") + node.get("availMemoryMB")) + (node.get("usedMemoryMB") + node.get("availMemoryMB")); var lowerLimit = (this.selectedCategory - 1) * 0.2; var upperLimit = this.selectedCategory * 0.2; if (lowerLimit <= usage && usage <= upperLimit) { @@ -116,6 +116,7 @@ export default BaseChartComponent.extend({ var sampleXOffset = (layout.x2 - layout.x1) / 2 - 2.5 * this.SAMPLE_CELL_WIDTH - 2 * this.CELL_MARGIN; var sampleYOffset = layout.margin * 2; + var text; for (i = 1; i <= 5; i++) { var ratio = i * 0.2 - 0.1; @@ -128,7 +129,7 @@ export default BaseChartComponent.extend({ .attr("height", this.SAMPLE_HEIGHT) .attr("class", "hyperlink"); this.bindSelectCategory(rect, i); - var text = g.append("text") + text = g.append("text") .text("" + (ratio * 100).toFixed(1) + "% Used") .attr("y", sampleYOffset + this.SAMPLE_HEIGHT / 2 + 5) .attr("x", sampleXOffset + this.SAMPLE_CELL_WIDTH / 2) @@ -137,8 +138,8 @@ export default BaseChartComponent.extend({ sampleXOffset += this.CELL_MARGIN + this.SAMPLE_CELL_WIDTH; } - if (this.selectedCategory != 0) { - var text = g.append("text") + if (this.selectedCategory !== 0) { + text = g.append("text") .text("Clear") .attr("y", sampleYOffset + this.SAMPLE_HEIGHT / 2 + 5) .attr("x", sampleXOffset + 20) @@ -149,7 +150,7 @@ export default BaseChartComponent.extend({ var chartXOffset = -1; for (i = 0; i < racksArray.length; i++) { - var text = g.append("text") + text = g.append("text") .text(racksArray[i]) .attr("y", yOffset + this.CELL_HEIGHT / 2 + 5) .attr("x", layout.margin) @@ -163,7 +164,6 @@ export default BaseChartComponent.extend({ for (var j = 0; j < data.length; j++) { var rack = data[j].get("rack"); - var host = data[j].get("nodeHostName"); if (rack === racksArray[i]) { this.addNode(g, xOffset, yOffset, colorFunc, data[j]); @@ -217,11 +217,11 @@ export default BaseChartComponent.extend({ href = `#/yarn-node/${node_id}/${node_addr}`; var a = g.append("a") .attr("href", href); - var text = a.append("text") + a.append("text") .text(data.get("nodeHostName")) .attr("y", yOffset + this.CELL_HEIGHT / 2 + 5) .attr("x", xOffset + this.CELL_WIDTH / 2) - .attr("class", this.isNodeSelected(data) ? "heatmap-cell" : "heatmap-cell-notselected") + .attr("class", this.isNodeSelected(data) ? "heatmap-cell" : "heatmap-cell-notselected"); if (this.isNodeSelected(data)) { this.bindTP(a, rect); } http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js new file mode 100644 index 0000000..8527e91 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js @@ -0,0 +1,206 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +export default Ember.Component.extend({ + data: [], + xAxisTickFormatter: null, + yAxisTickFormatter: null, + xAxisText: '', + yAxisText: '', + enableTooltip: true, + onBarChartClickCallback: Ember.K, + hideTootlipOnBarChartClick: true, + + initChart() { + this.height = 400; + this.barWidth = 30; + this.width = Math.max(500, 40 * this.data.length); + }, + + drawChart() { + var margin = {top: 20, right: 20, bottom: 100, left: 100}, + axisLabelPadding = 10, + width = this.width - margin.left - margin.right - axisLabelPadding, + height = this.height - margin.top - margin.bottom - axisLabelPadding, + xAxisText = this.xAxisText? this.xAxisText : '', + yAxisText = this.yAxisText? this.yAxisText : '', + data = this.data, + self = this; + + var xScale = d3.scale.ordinal().rangeRoundBands([0, width], 0.1); + var yScale = d3.scale.linear().range([height, 0]); + + var xAxis = d3.svg.axis() + .scale(xScale) + .orient("bottom") + .tickFormat(function(tick) { + if (self.isFunction(self.xAxisTickFormatter)) { + return self.xAxisTickFormatter(tick); + } else { + return tick; + } + }); + + var yAxis = d3.svg.axis() + .scale(yScale) + .orient("left") + .tickFormat(function(tick) { + if (self.isFunction(self.yAxisTickFormatter)) { + return self.yAxisTickFormatter(tick); + } else { + return tick; + } + }); + + var svg = d3.select(this.element) + .append("svg") + .attr("class", "simple-bar-chart") + .attr("width", width + margin.left + margin.right + axisLabelPadding) + .attr("height", height + margin.top + margin.bottom + axisLabelPadding) + .append("g") + .attr("transform", "translate("+(margin.left+axisLabelPadding)+","+(margin.top)+")"); + + xScale.domain(data.map(function(d) { return d.label; })); + yScale.domain([0, d3.max(data, function(d) { return d.value; })]); + + var gx = svg.append("g") + .attr("class", "x axis") + .attr("transform", "translate(0," + height + ")") + .call(xAxis); + + gx.selectAll("text") + .style("text-anchor", "end") + .attr("dx", "-.8em") + .attr("dy", "-.3em") + .attr("transform", "rotate(-60)"); + + gx.append("text") + .attr("transform", "translate("+(width/2)+","+(margin.bottom)+")") + .style("text-anchor", "middle") + .text(xAxisText); + + var gy = svg.append("g") + .attr("class", "y axis") + .call(yAxis); + + gy.append("text") + .attr("transform", "translate("+(-margin.left)+","+(height/2)+")rotate(-90)") + .style("text-anchor", "middle") + .text(yAxisText); + + var barWidth = this.barWidth; + var minBarWidth = Math.min(barWidth, xScale.rangeBand()); + var bars = svg.selectAll("bar") + .data(data) + .enter().append("rect") + .attr("x", function(d) { + var padding = 0; + var rangeBand = xScale.rangeBand(); + if ((rangeBand - barWidth) > 0) { + padding = (rangeBand - barWidth) / 2; + } + return xScale(d.label) + padding; + }) + .attr("width", minBarWidth) + .attr("y", function() { + return yScale(0); + }) + .attr("height", function() { + return height - yScale(0); + }) + .on('click', function(d) { + if (self.enableTooltip && self.hideTootlipOnBarChartClick) { + self.hideTootlip(); + } + if (self.isFunction(self.onBarChartClickCallback)) { + self.onBarChartClickCallback(d); + } + }); + + bars.transition() + .duration(1000) + .delay(100) + .attr("y", function(d) { + return yScale(d.value); + }) + .attr("height", function(d) { + return height - yScale(d.value); + }); + + if (this.enableTooltip) { + this.bindTooltip(bars); + } + }, + + bindTooltip(bars) { + var self = this; + var tooltip = this.tooltip; + if (tooltip) { + bars.on("mouseenter", function(d) { + tooltip.html(d.tooltip); + self.showTooltip(); + }).on("mousemove", function() { + tooltip.style("left", (d3.event.pageX + 5) + "px") + .style("top", (d3.event.pageY - 25) + "px"); + }).on("mouseout", function() { + self.hideTootlip(); + }); + } + }, + + initTooltip() { + this.tooltip = d3.select("body") + .append("div") + .attr("class", "tooltip simple-barchart-tooltip") + .style("opacity", 1); + + this.hideTootlip(); + }, + + hideTootlip() { + if (this.tooltip) { + this.tooltip.style("display", "none"); + } + }, + + showTooltip() { + if (this.tooltip) { + this.tooltip.style("display", "block"); + } + }, + + isFunction(func) { + return Ember.typeOf(func) === "function"; + }, + + didInsertElement() { + this.initChart(); + if (this.enableTooltip) { + this.initTooltip(); + } + this.drawChart(); + }, + + willDestroyElement() { + if (this.tooltip) { + this.tooltip.remove(); + } + } +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js new file mode 100644 index 0000000..3a2302a --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js @@ -0,0 +1,261 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +export default Ember.Component.extend({ + + didInsertElement: function() { + var json = buildHierarchy(this.get("arr")); + createVisualization(json); + }, + +}); +// Dimensions of sunburst. +var width = 1000; +var height = 750; +var radius = Math.min(width, height) / 2; +// Breadcrumb dimensions: width, height, spacing, width of tip/tail. +var b = { w: 225, h: 30, s: 3, t: 10 }; +// Total size of all segments; we set this later, after loading the data. +var totalSize = 0; +var vis = null; +var partition = null; +var arc = null; +var colors = d3.scale.category20c(); + +function colorMap(d) { + return colors(d.name); +} + +// Given a node in a partition layout, return an array of all of its ancestor +// nodes, highest first, but excluding the root. +function getAncestors(node) { + var path = []; + var current = node; + while (current.parent) { + path.unshift(current); + current = current.parent; + } + return path; +} + +// Main function to draw and set up the visualization, once we have the data. +function createVisualization(json) { + partition = d3.layout.partition() + .size([2 * Math.PI, radius * radius]) + .value(function(d) { return d.size; }); + arc = d3.svg.arc() + .startAngle(function(d) { return d.x; }) + .endAngle(function(d) { return d.x + d.dx; }) + .innerRadius(function(d) { return Math.sqrt(d.y); }) + .outerRadius(function(d) { return Math.sqrt(d.y + d.dy); }); + // Basic setup of page elements. + initializeBreadcrumbTrail(); + //drawLegend(); + //d3.select("#togglelegend").on("click", toggleLegend); + + // Bounding circle underneath the sunburst, to make it easier to detect + // when the mouse leaves the parent g. + vis = d3.select("#chart").append("svg:svg") + .attr("width", width) + .attr("height", height) + .append("svg:g") + .attr("id", "container") + .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); + vis.append("svg:circle").attr("r", radius) + .style("opacity", 0); + + // For efficiency, filter nodes to keep only those large enough to see. + var nodes = partition.nodes(json) + .filter(function(d) { + return (d.dx > 0.005); // 0.005 radians = 0.29 degrees + }); + + var path = vis.data([json]).selectAll("path") + .data(nodes) + .enter().append("svg:path") + .attr("display", function(d) { return d.depth ? null : "none"; }) + .attr("d", arc) + .attr("fill-rule", "evenodd") + .attr("fill", colorMap) + .style("opacity", 1) + .on("mouseover", mouseover); + // Add the mouseleave handler to the bounding circle. + d3.select("#container").on("mouseleave", mouseleave); + + // Get total size of the tree = value of root node from partition. + totalSize = path.node().__data__.value; +} + + // Take a 2-column CSV and transform it into a hierarchical structure suitable + // for a partition layout. The first column is a sequence of step names, from + // root to leaf, separated by hyphens. The second column is a count of how + // often that sequence occurred. +function buildHierarchy(csv) { + var root = {"name": "root", "children": []}; + for (var i = 0; i < csv.length; i++) { + var sequence = csv[i][0]; + var size = +csv[i][1]; + if (isNaN(size)) { // e.g. if this is a header row + continue; + } + var parts = sequence.split("-"); + var currentNode = root; + for (var j = 0; j < parts.length; j++) { + var children = currentNode["children"]; + var nodeName = parts[j]; + var childNode; + if (j + 1 < parts.length) { + // Not yet at the end of the sequence; move down the tree. + var foundChild = false; + for (var k = 0; k < children.length; k++) { + if (children[k]["name"] === nodeName) { + childNode = children[k]; + foundChild = true; + break; + } + } + // If we don't already have a child node for this branch, create it. + if (!foundChild) { + childNode = {"name": nodeName, "children": []}; + children.push(childNode); + } + currentNode = childNode; + } else { + // Reached the end of the sequence; create a leaf node. + childNode = {"name": nodeName, "size": size, "children": [], "sequence": sequence}; + children.push(childNode); + } + } + } + return root; +} + +// Fade all but the current sequence, and show it in the breadcrumb trail. +function mouseover(d) { + //var percentage = (100 * d.value / totalSize).toPrecision(3); + //var percentageString = percentage + "%"; + var percentageString = d.value; + + d3.select("#percentage").html('<p align="center" style="font-size: 150%;"><b>' + percentageString + + '</b></p><br/><p align="center">(' + d.name + ')</p>'); + d3.select("#explanation").style("visibility", ""); + + var sequenceArray = getAncestors(d); + updateBreadcrumbs(sequenceArray, percentageString); + + // Fade all the segments. + d3.selectAll("path").style("opacity", 0.2); + + // Then highlight only those that are an ancestor of the current segment. + vis.selectAll("path") + .filter(function(node) { + return (sequenceArray.indexOf(node) >= 0); + }) + .style("opacity", 1); +} + +// Restore everything to full opacity when moving off the visualization. +function mouseleave() { + // Hide the breadcrumb trail + d3.select("#trail").style("visibility", "hidden"); + + // Deactivate all segments during transition. + d3.selectAll("path").on("mouseover", null); + + // Transition each segment to full opacity and then reactivate it. + d3.selectAll("path") + .transition() + .duration(1000) + .style("opacity", 1) + .each("end", function() { + d3.select(this).on("mouseover", mouseover); + }); + + d3.select("#explanation") + .style("visibility", "hidden"); +} + +function initializeBreadcrumbTrail() { + // Add the svg area. + var trail = d3.select("#sequence").append("svg:svg") + .attr("width", width) + .attr("height", 50) + .attr("id", "trail"); + // Add the label at the end, for the percentage. + trail.append("svg:text") + .attr("id", "endlabel") + .style("fill", "#000"); +} + +// Generate a string that describes the points of a breadcrumb polygon. +function breadcrumbPoints(d, i) { + var points = []; + points.push("0,0"); + points.push(b.w + ",0"); + points.push(b.w + b.t + "," + (b.h / 2)); + points.push(b.w + "," + b.h); + points.push("0," + b.h); + if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex. + points.push(b.t + "," + (b.h / 2)); + } + return points.join(" "); +} + +// Update the breadcrumb trail to show the current sequence and percentage. +function updateBreadcrumbs(nodeArray, percentageString) { + // Data join; key function combines name and depth (= position in sequence). + var g = d3.select("#trail") + .selectAll("g") + .data(nodeArray, function(d) { return d.name + d.depth; }); + + // Add breadcrumb and label for entering nodes. + var entering = g.enter().append("svg:g"); + + entering.append("svg:polygon") + .attr("points", breadcrumbPoints) + .attr("fill", colorMap); + + entering.append("svg:text") + .attr("x", (b.w + b.t) / 2) + .attr("y", b.h / 2) + .attr("dy", "0.35em") + .attr("text-anchor", "middle") + .text(function(d) { return d.name; }); + + // Set position for entering and updating nodes. + g.attr("transform", function(d, i) { + return "translate(" + i * (b.w + b.s) + ", 0)"; + }); + + // Remove exiting nodes. + g.exit().remove(); + + // Now move and update the percentage at the end. + d3.select("#trail").select("#endlabel") + .attr("x", (nodeArray.length + 0.5) * (b.w + b.s)) + .attr("y", b.h / 2) + .attr("dy", "0.35em") + .attr("text-anchor", "middle") + .text(percentageString); + + // Make the breadcrumb trail visible, if it's hidden. + d3.select("#trail") + .style("visibility", ""); +} http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js index 44a7c1c..fffaf17 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js @@ -17,7 +17,6 @@ */ import Ember from 'ember'; -import ColumnDef from 'em-table/utils/column-definition'; import TableDefinition from 'em-table/utils/table-definition'; import AppTableController from '../app-table-columns'; http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js index 44a7c1c..fffaf17 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js @@ -17,7 +17,6 @@ */ import Ember from 'ember'; -import ColumnDef from 'em-table/utils/column-definition'; import TableDefinition from 'em-table/utils/table-definition'; import AppTableController from '../app-table-columns'; http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js new file mode 100644 index 0000000..61e7823 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js @@ -0,0 +1,125 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; +import TableDef from 'em-table/utils/table-definition'; +import ColumnDef from 'em-table/utils/column-definition'; +import lodash from 'lodash/lodash'; + +function _createColumns() { + var columns = []; + columns.push({ + id: 'flowName', + headerTitle: 'Flow Name', + contentPath: 'flowName', + observePath: true, + }, { + id: 'user', + headerTitle: 'User', + contentPath: 'user', + observePath: true + }, { + id: 'uid', + headerTitle: 'Flow ID', + contentPath: 'uid', + observePath: true, + cellComponentName: 'em-table-linked-cell', + minWidth: "300px", + getCellContent: function (row) { + return { + routeName: 'yarn-flow.info', + id: row.get('uid'), + displayText: row.get('uid') + }; + } + }, { + id: 'lastExecDate', + headerTitle: 'Last Execution Date', + contentPath: 'lastExecDate', + observePath: true + }); + return ColumnDef.make(columns); +} + +function _getAggregatedFlowsData(flows) { + var aggregatedFlows = []; + flows = flows? flows.get('content') : []; + + var aggregated = lodash.groupBy(flows, function(flow) { + return flow.getRecord().get('uid'); + }); + + lodash.forIn(aggregated, function(flows) { + let flowsInAsc = lodash.sortBy(flows, function(flow) { + return flow.getRecord().get('lastExecDate'); + }); + let flowsInDesc = flowsInAsc.reverse(); + aggregatedFlows.push(flowsInDesc[0].getRecord()); + }); + + return aggregatedFlows; +} + +function _createRows(flows) { + var data = [], + aggregatedFlows = null, + row = null; + + aggregatedFlows = _getAggregatedFlowsData(flows); + + aggregatedFlows.forEach(function(flow) { + row = Ember.Object.create({ + user: flow.get('user'), + flowName: flow.get('flowName'), + uid: flow.get('uid'), + lastExecDate: flow.get('lastExecDate') + }); + data.push(row); + }); + + return Ember.A(data); +} + +export default Ember.Controller.extend({ + breadcrumbs: [{ + text: "Home", + routeName: 'application' + }, { + text: "Flow Activities", + routeName: 'yarn-flow-activity', + }], + + columns: _createColumns(), + + rows: Ember.computed('model', function() { + return _createRows(this.get('model')); + }), + + tableDefinition: TableDef.create({ + sortColumnId: 'lastExecDate', + sortOrder: 'desc' + }), + + getLastFlowExecutionInfoByFlowUid: function(uid) { + var aggregatedFlows = _getAggregatedFlowsData(this.get('model')); + var recent = aggregatedFlows.find(function(flow) { + return flow.get('uid') === uid; + }); + return recent; + } +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow.js new file mode 100644 index 0000000..216ab11 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow.js @@ -0,0 +1,36 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +export default Ember.Controller.extend({ + breadcrumbs: Ember.computed("model.flowUid", function() { + var flowUid = this.get('model.flowUid'); + return [{ + text: "Home", + routeName: 'application' + }, { + text: "Flow Activities", + routeName: 'yarn-flow-activity' + }, { + text: `Flow Info [${flowUid}]`, + routeName: 'yarn-flow.info', + model: flowUid + }]; + }) +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js new file mode 100644 index 0000000..fc4dd23 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; +import Converter from 'yarn-ui/utils/converter'; + +export default Ember.Controller.extend({ + flowUid: function() { + return this.get('model.flowUid'); + }.property('model.flowUid'), + + flowLastExecutionDate: function() { + if (this.get('model.lastFlowExecutionInfo')) { + return this.get('model.lastFlowExecutionInfo').get('lastExecDate'); + } else { + return ''; + } + }.property('model.lastFlowExecutionInfo'), + + flowInfo: function() { + var info = {}; + var firstRunObj = this.get('model.flowRuns').get('firstObject'); + info.flowUid = this.get('flowUid'); + info.flowName = firstRunObj.get('flowName'); + info.user = firstRunObj.get('user'); + info.lastExecutionDate = this.get('flowLastExecutionDate'); + info.firstRunStarted = this.get('earliestStartTime'); + info.lastRunFinished = this.get('latestFinishTime'); + return info; + }.property('model.flowRuns', 'flowLastExecutionDate'), + + earliestStartTime: function() { + var earliestStart = Number.MAX_VALUE; + this.get('model.flowRuns').forEach(function(flowrun) { + if (flowrun.get('createTimeRaw') < earliestStart) { + earliestStart = flowrun.get('createTimeRaw'); + } + }); + return Converter.timeStampToDate(earliestStart); + }.property('model.flowRuns'), + + latestFinishTime: function() { + var latestFinish = 0; + this.get('model.flowRuns').forEach(function(flowrun) { + if (flowrun.get('endTimeRaw') > latestFinish) { + latestFinish = flowrun.get('endTimeRaw'); + } + }); + return Converter.timeStampToDate(latestFinish); + }.property('model.flowRuns') +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js new file mode 100644 index 0000000..def4c12 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js @@ -0,0 +1,178 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; +import TableDef from 'em-table/utils/table-definition'; +import ColumnDef from 'em-table/utils/column-definition'; +import Converter from 'yarn-ui/utils/converter'; + +function createColumn() { + var columns = []; + + // Generate columns + columns.push({ + id: 'runid', + headerTitle: 'Run ID', + contentPath: 'runid', + cellComponentName: 'em-table-linked-cell', + minWidth: "300px", + getCellContent: function (row) { + return { + routeName: 'yarn-flowrun.info', + id: row.get('uid'), + displayText: row.get('shownid') + }; + } + }); + + columns.push({ + id: 'runDurationTs', + headerTitle: 'Run Duration', + contentPath: 'runDurationTs', + getCellContent: function(row) { + return Converter.msToElapsedTimeUnit(row.get('runDurationTs')); + } + }); + + columns.push({ + id: 'cpuVCores', + headerTitle: 'CPU VCores', + contentPath: 'cpuVCores', + getCellContent: function(row) { + if (row.get('cpuVCores') > -1) { + return row.get('cpuVCores'); + } + return 'N/A'; + } + }); + + columns.push({ + id: 'memoryUsed', + headerTitle: 'Memory Used', + contentPath: 'memoryUsed', + getCellContent: function(row) { + if (row.get('memoryUsed') > -1) { + return Converter.memoryBytesToMB(row.get('memoryUsed')); + } + return 'N/A'; + } + }); + + columns.push({ + id: 'createTime', + headerTitle: 'Creation Time', + contentPath: 'createTime' + }); + + columns.push({ + id: 'endTime', + headerTitle: 'End Time', + contentPath: 'endTime' + }); + + return ColumnDef.make(columns); +} + +export default Ember.Controller.extend({ + vizWidgets: { + runDuration: true, + cpuVcores: false, + memoryUsed: false + }, + + actions: { + addVizWidget(widget) { + Ember.set(this.vizWidgets, widget, true); + }, + + removeVizWidget(widget) { + Ember.set(this.vizWidgets, widget, false); + } + }, + + columns: createColumn(), + + tableDefinition: TableDef.create({ + sortColumnId: 'createTime', + sortOrder: 'desc' + }), + + elapsedTimeVizData: function() { + var data = []; + this.get('model.flowRuns').forEach(function(run) { + var vizData = run.getElapsedTimeVizDataForBarChart(); + if (vizData.value > 0) { + data.push(vizData); + } + }); + data = this.getSortedVizDataInDesc(data); + return this.getRefactoredVizData(data); + }.property('model.flowRuns'), + + elapsedTimeFormatter: function(tick) { + return Converter.msToElapsedTimeUnit(tick, true); + }, + + cpuVCoresVizData: function() { + var data = []; + this.get('model.flowRuns').forEach(function(run) { + var vizData = run.getCpuVCoresVizDataForBarChart(); + if (vizData.value > 0) { + data.push(vizData); + } + }); + data = this.getSortedVizDataInDesc(data); + return this.getRefactoredVizData(data); + }.property('model.flowRuns'), + + memoryVizData: function() { + var data = []; + this.get('model.flowRuns').forEach(function(run) { + var vizData = run.getMemoryVizDataForBarChart(); + if (vizData.value > 0) { + data.push(vizData); + } + }); + data = this.getSortedVizDataInDesc(data); + return this.getRefactoredVizData(data); + }.property('model.flowRuns'), + + memoryFormatter: function(tick) { + return Converter.memoryBytesToMB(tick); + }, + + onBarChartClick: function() { + var self = this; + return function(data) { + self.transitionToRoute('yarn-flowrun.info', data.flowrunUid); + }; + }.property(), + + getSortedVizDataInDesc: function(data) { + return data.sort(function(d1, d2) { + return d2.value - d1.value; + }); + }, + + getRefactoredVizData: function(data) { + data.forEach(function(viz, idx) { + viz.label = "Run " + (++idx); + }, this); + return data; + } +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js new file mode 100644 index 0000000..6af87ab --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js @@ -0,0 +1,50 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +export default Ember.Controller.extend({ + breadcrumbs: Ember.computed('model.flowrun_uid', 'model.parentFlowUid', function() { + var flowRunId = this.get('model.flowrun_uid'); + var parentFlowUid = this.get('model.parentFlowUid'); + var crumbs = [{ + text: "Home", + routeName: 'application' + }, { + text: "Flow Activities", + routeName: 'yarn-flow-activity' + }]; + if (parentFlowUid) { + crumbs.push({ + text: `Flow Info [${parentFlowUid}]`, + routeName: 'yarn-flow.info', + model: parentFlowUid + }, { + text: `Flow Runs [${parentFlowUid}]`, + routeName: 'yarn-flow.runs', + model: parentFlowUid + }); + } + crumbs.push({ + text: `Run Info [${flowRunId}]`, + routeName: 'yarn-flowrun.info', + model: flowRunId + }); + return crumbs; + }) +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js new file mode 100644 index 0000000..df2f87e --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js @@ -0,0 +1,157 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; +import ColumnDef from 'em-table/utils/column-definition'; +import Converter from 'yarn-ui/utils/converter'; + +function createColumn() { + var columns = []; + + // Generate columns + columns.push({ + id: 'appId', + headerTitle: 'Application ID', + contentPath: 'appId', + cellComponentName: 'em-table-linked-cell', + minWidth: "300px", + getCellContent: function (row) { + return { + routeName: 'yarn-app', + id: row.get('appId'), + displayText: row.get('appId') + }; + } + }); + + columns.push({ + id: 'appType', + headerTitle: 'Application Type', + contentPath: 'type' + }); + + columns.push({ + id: 'state', + headerTitle: 'State', + contentPath: 'state', + cellComponentName: 'em-table-status-cell', + }); + + columns.push({ + id: 'elapsedTs', + headerTitle: 'Elapsed Time', + contentPath: 'elapsedTs', + getCellContent: function(row) { + return Converter.msToElapsedTimeUnit(row.get('elapsedTs')); + } + }); + + columns.push({ + id: 'cpuVCores', + headerTitle: 'CPU VCores', + contentPath: 'cpuVCores', + getCellContent: function(row) { + if (row.get('cpuVCores') > -1) { + return row.get('cpuVCores'); + } + return 'N/A'; + } + }); + + columns.push({ + id: 'memoryUsed', + headerTitle: 'Memory Used', + contentPath: 'memoryUsed', + getCellContent: function(row) { + if (row.get('memoryUsed') > -1) { + return Converter.memoryBytesToMB(row.get('memoryUsed')); + } + return 'N/A'; + } + }); + + return ColumnDef.make(columns); +} + +export default Ember.Controller.extend({ + vizWidgets: { + cpuVcores: true, + memoryUsed: false + }, + + actions: { + addVizWidget(widget) { + Ember.set(this.vizWidgets, widget, true); + }, + + removeVizWidget(widget) { + Ember.set(this.vizWidgets, widget, false); + } + }, + + columns: createColumn(), + + cpuVCoresVizData: function() { + var data = []; + this.get('model.apps').forEach(function(app) { + var vizData = app.getCpuVCoresVizDataForBarChart(); + if (vizData.value > 0) { + data.push(vizData); + } + }); + data = this.getSortedVizDataInDesc(data); + return this.getRefactoredVizData(data); + }.property('model.apps'), + + memoryVizData: function() { + var data = []; + this.get('model.apps').forEach(function(app) { + var vizData = app.getMemoryVizDataForBarChart(); + if (vizData.value > 0) { + data.push(vizData); + } + }); + data = this.getSortedVizDataInDesc(data); + return this.getRefactoredVizData(data); + }.property('model.apps'), + + memoryFormatter: function(tick) { + return Converter.memoryBytesToMB(tick); + }, + + onBarChartClick: function() { + var self = this; + return function(data) { + self.transitionToRoute('yarn-app', data.appId); + }; + }.property(), + + getSortedVizDataInDesc: function(data) { + return data.sort(function(d1, d2) { + return d2.value - d1.value; + }); + }, + + getRefactoredVizData: function(data) { + data.forEach(function(viz, idx) { + viz.appId = viz.label; + viz.label = "App " + (++idx); + }, this); + return data; + } +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js new file mode 100644 index 0000000..97b1e07 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js @@ -0,0 +1,126 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; +import ColumnDef from 'em-table/utils/column-definition'; + +function _createColumns() { + var columns = []; + + columns.push({ + id: 'name', + headerTitle: 'Name', + contentPath: 'name', + observePath: true, + cellComponentName: 'em-table-html-cell', + getCellContent: function(row) { + var plainName = row.name; + if (plainName.indexOf('MAP:') > -1 || plainName.indexOf('REDUCE:') > -1) { + plainName = plainName.substring(plainName.indexOf(':') + 1); + } + return `<span>${plainName}</span>`; + } + }, { + id: 'value', + headerTitle: 'Value', + contentPath: 'value', + observePath: true + }); + + return ColumnDef.make(columns); +} + +export default Ember.Controller.extend({ + mapMetrics: null, + reduceMetrics: null, + generalMetrics: null, + + columns: Ember.computed(function() { + return _createColumns(this.get('model.flowrun_uid')); + }), + + metricsObserver: Ember.observer('model.flowrun', function() { + var metrics = this.get('model.flowrun.metrics'); + var mapConfigs = [], + reduceConfigs = [], + generalConfigs = []; + + metrics.forEach(function(metric) { + let id = metric.id; + if (id.startsWith('MAP:')) { + mapConfigs.push(metric); + } else if (id.startsWith('REDUCE:')) { + reduceConfigs.push(metric); + } else { + generalConfigs.push(metric); + } + }, this); + + this.set('mapMetrics', mapConfigs); + this.set('reduceMetrics', reduceConfigs); + this.set('generalMetrics', generalConfigs); + }), + + mapConfigRows: Ember.computed('mapMetrics', function() { + var row = null, + data = []; + + this.get('mapMetrics').forEach(function(map) { + let value = map.values[Object.keys(map.values)[0]]; + row = Ember.Object.create({ + name: map.id, + value: value + }); + data.push(row); + }, this); + + return Ember.A(data); + }), + + reduceConfigRows: Ember.computed('reduceMetrics', function() { + var row = null, + data = []; + + this.get('reduceMetrics').forEach(function(map) { + let value = map.values[Object.keys(map.values)[0]]; + row = Ember.Object.create({ + name: map.id, + value: value + }); + data.push(row); + }, this); + + return Ember.A(data); + }), + + generalConfigRows: Ember.computed('generalMetrics', function() { + var row = null, + data = []; + + this.get('generalMetrics').forEach(function(map) { + let value = map.values[Object.keys(map.values)[0]]; + row = Ember.Object.create({ + name: map.id, + value: value + }); + data.push(row); + }, this); + + return Ember.A(data); + }) +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js index eeb6205..a2c80f7 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js @@ -18,9 +18,19 @@ import Ember from 'ember'; import AppTableController from './app-table-columns'; - +import TableDefinition from 'em-table/utils/table-definition'; export default AppTableController.extend({ + queryParams: ['searchText', 'sortColumnId', 'sortOrder', 'pageNum', 'rowCount'], + tableDefinition: TableDefinition.create({ + sortColumnId: 'stTime', + sortOrder: 'desc' + }), + searchText: Ember.computed.alias('tableDefinition.searchText'), + sortColumnId: Ember.computed.alias('tableDefinition.sortColumnId'), + sortOrder: Ember.computed.alias('tableDefinition.sortOrder'), + pageNum: Ember.computed.alias('tableDefinition.pageNum'), + rowCount: Ember.computed.alias('tableDefinition.rowCount'), breadcrumbs: [{ text: "Home", http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/mixins/app-attempt.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/mixins/app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/mixins/app-attempt.js new file mode 100644 index 0000000..a90bf36 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/mixins/app-attempt.js @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +export default Ember.Mixin.create({ + fetchAppInfoFromRMorATS(appId, store) { + return new Ember.RSVP.Promise(function(resolve, reject) { + store.find('yarn-app', appId).then(function(rmApp) { + resolve(rmApp); + }, function() { + store.find('yarn-app-timeline', appId).then(function(atsApp) { + resolve(atsApp); + }, function() { + console.error('Error:', 'Application not found in RM or ATS for appId: ' + appId); + reject(null); + }); + }); + }); + }, + + fetchAttemptInfoFromRMorATS(attemptId, store) { + return new Ember.RSVP.Promise(function(resolve, reject) { + store.findRecord('yarn-app-attempt', attemptId, {reload: true}).then(function(rmAttempt) { + resolve(rmAttempt); + }, function() { + store.findRecord('yarn-timeline-appattempt', attemptId, {reload: true}).then(function(atsAttempt) { + resolve(atsAttempt); + }, function() { + console.error('Error:', 'Application attempt not found in RM or ATS for attemptId: ' + attemptId); + reject(null); + }); + }); + }); + }, + + fetchAttemptListFromRMorATS(appId, store) { + return new Ember.RSVP.Promise(function(resolve, reject) { + store.query('yarn-app-attempt', {appId: appId}).then(function(rmAttempts) { + resolve(rmAttempts); + }, function() { + store.query('yarn-timeline-appattempt', {appId: appId}).then(function(atsAttempts) { + resolve(atsAttempts); + }, function() { + console.error('Error:', 'Application attempts not found in RM or ATS for appId: ' + appId); + reject(null); + }); + }); + }); + } +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js index c83eb2e..dd95765 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js @@ -74,7 +74,7 @@ export default DS.Model.extend({ if (!this.get("containerId")) { return this.get("id"); } - return "attempt_" + + return "attempt_" + parseInt(Converter.containerIdToAttemptId(this.get("containerId")).split("_")[3]); }.property("containerId"), @@ -119,13 +119,12 @@ export default DS.Model.extend({ if (elapsedMs <= 0) { elapsedMs = Date.now() - this.get("startTs"); } - - return Converter.msToElapsedTime(elapsedMs); + return Converter.msToElapsedTimeUnit(elapsedMs); }.property(), tooltipLabel: function() { - return "<p>Id:" + this.get("id") + - "</p><p>ElapsedTime:" + + return "<p>Id:" + this.get("id") + + "</p><p>ElapsedTime:" + String(this.get("elapsedTime")) + "</p>"; }.property(), @@ -141,4 +140,4 @@ export default DS.Model.extend({ return this.get("state"); }.property(), -}); \ No newline at end of file +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.js new file mode 100644 index 0000000..a8a7471 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.js @@ -0,0 +1,52 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; +import Converter from 'yarn-ui/utils/converter'; + +export default DS.Model.extend({ + appId: DS.attr('string'), + type: DS.attr('string'), + uid: DS.attr('string'), + metrics: DS.attr('array'), + startedTs: DS.attr('number'), + finishedTs: DS.attr('number'), + state: DS.attr('string'), + cpuVCores: DS.attr('number'), + memoryUsed: DS.attr('number'), + + elapsedTs: function() { + return this.get('finishedTs') - this.get('startedTs'); + }.property('startedTs', 'finishedTs'), + + getCpuVCoresVizDataForBarChart: function() { + return { + label: this.get('appId'), + value: this.get('cpuVCores'), + tooltip: this.get("appId") + "<br>" + 'CPU VCores: ' + this.get('cpuVCores') + }; + }, + + getMemoryVizDataForBarChart: function() { + return { + label: this.get('appId'), + value: this.get('memoryUsed'), + tooltip: this.get("appId") + "<br>" + 'Memory Used: ' + Converter.memoryBytesToMB(this.get('memoryUsed')) + }; + } +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-timeline.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-timeline.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-timeline.js new file mode 100644 index 0000000..fa5223f --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-timeline.js @@ -0,0 +1,105 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; +import Converter from 'yarn-ui/utils/converter'; + +export default DS.Model.extend({ + appName: DS.attr('string'), + user: DS.attr('string'), + queue: DS.attr('string'), + state: DS.attr('string'), + startTime: DS.attr('string'), + elapsedTime: DS.attr('string'), + finalStatus: DS.attr('string'), + finishedTime: DS.attr('finishedTime'), + progress: DS.attr('number'), + diagnostics: DS.attr('string'), + amContainerLogs: DS.attr('string'), + amHostHttpAddress: DS.attr('string'), + logAggregationStatus: DS.attr('string'), + unmanagedApplication: DS.attr('string'), + amNodeLabelExpression: DS.attr('string'), + applicationTags: DS.attr('string'), + applicationType: DS.attr('string'), + priority: DS.attr('number'), + allocatedMB: DS.attr('number'), + allocatedVCores: DS.attr('number'), + runningContainers: DS.attr('number'), + memorySeconds: DS.attr('number'), + vcoreSeconds: DS.attr('number'), + preemptedResourceMB: DS.attr('number'), + preemptedResourceVCores: DS.attr('number'), + numNonAMContainerPreempted: DS.attr('number'), + numAMContainerPreempted: DS.attr('number'), + clusterUsagePercentage: DS.attr('number'), + queueUsagePercentage: DS.attr('number'), + currentAppAttemptId: DS.attr('string'), + + isFailed: function() { + return this.get('finalStatus') === "FAILED"; + }.property("finalStatus"), + + validatedFinishedTs: function() { + if (this.get("finishedTime") < this.get("startTime")) { + return ""; + } + return this.get("finishedTime"); + }.property("finishedTime"), + + formattedElapsedTime: function() { + return Converter.msToElapsedTimeUnit(this.get('elapsedTime')); + }.property('elapsedTime'), + + allocatedResource: function() { + return Converter.resourceToString(this.get("allocatedMB"), this.get("allocatedVCores")); + }.property("allocatedMB", "allocatedVCores"), + + preemptedResource: function() { + return Converter.resourceToString(this.get("preemptedResourceMB"), this.get("preemptedResourceVCores")); + }.property("preemptedResourceMB", "preemptedResourceVCores"), + + aggregatedResourceUsage: function() { + return Converter.resourceToString(this.get("memorySeconds"), this.get("vcoreSeconds")) + " (Ã Secs)"; + }.property("memorySeconds", "vcoreSeconds"), + + progressStyle: function() { + return "width: " + this.get("progress") + "%"; + }.property("progress"), + + runningContainersNumber: function() { + if(this.get("runningContainers") < 0) { + return 0; + } + return this.get("runningContainers"); + }.property("progress"), + + finalStatusStyle: function() { + var style = "default"; + var finalStatus = this.get("finalStatus"); + if (finalStatus === "KILLED") { + style = "warning"; + } else if (finalStatus === "FAILED") { + style = "danger"; + } else { + style = "success"; + } + + return "label label-" + style; + }.property("finalStatus") +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-container.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-container.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-container.js index bd9cea7..7f39345 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-container.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-container.js @@ -52,13 +52,12 @@ export default DS.Model.extend({ if (elapsedMs <= 0) { elapsedMs = Date.now() - this.get("startTs"); } - - return Converter.msToElapsedTime(elapsedMs); + return Converter.msToElapsedTimeUnit(elapsedMs); }.property(), tooltipLabel: function() { - return "<p>Id:" + this.get("id") + - "</p><p>ElapsedTime:" + + return "<p>Id:" + this.get("id") + + "</p><p>ElapsedTime:" + String(this.get("elapsedTime")) + "</p>"; }.property(), -}); \ No newline at end of file +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-entity.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-entity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-entity.js new file mode 100644 index 0000000..a06d6ab --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-entity.js @@ -0,0 +1,26 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; + +export default DS.Model.extend({ + entityId: DS.attr('string'), + type: DS.attr('string'), + uid: DS.attr('string'), + metrics: DS.attr('array') +}); http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flow-activity.js ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flow-activity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flow-activity.js new file mode 100644 index 0000000..1095cfe --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flow-activity.js @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; + +export default DS.Model.extend({ + cluster: DS.attr('string'), + flowName: DS.attr('string'), + lastExecDate: DS.attr('string'), + user: DS.attr('string'), + flowruns: DS.attr('string'), + uid: DS.attr('string') +}); --------------------------------------------------------------------- To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org For additional commands, e-mail: common-commits-h...@hadoop.apache.org