Return-Path: X-Original-To: apmail-incubator-ambari-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-ambari-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id CEDA510B83 for ; Tue, 11 Jun 2013 23:56:50 +0000 (UTC) Received: (qmail 17430 invoked by uid 500); 11 Jun 2013 23:56:50 -0000 Delivered-To: apmail-incubator-ambari-commits-archive@incubator.apache.org Received: (qmail 17381 invoked by uid 500); 11 Jun 2013 23:56:50 -0000 Mailing-List: contact ambari-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@incubator.apache.org Delivered-To: mailing list ambari-commits@incubator.apache.org Received: (qmail 17325 invoked by uid 99); 11 Jun 2013 23:56:50 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 11 Jun 2013 23:56:50 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 11 Jun 2013 23:56:46 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 5F29123889ED; Tue, 11 Jun 2013 23:56:24 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1492013 [1/2] - in /incubator/ambari/branches/branch-1.4.0: ambari-server/src/main/java/org/apache/ambari/eventdb/db/ ambari-server/src/main/java/org/apache/ambari/eventdb/model/ ambari-server/src/main/java/org/apache/ambari/eventdb/webser... Date: Tue, 11 Jun 2013 23:56:22 -0000 To: ambari-commits@incubator.apache.org From: srimanth@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130611235624.5F29123889ED@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: srimanth Date: Tue Jun 11 23:56:21 2013 New Revision: 1492013 URL: http://svn.apache.org/r1492013 Log: AMBARI-2332. Support Jobs display for Tez and MR2 in Ambari. (billie via srimanth) Added: incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/Apps.java (with props) incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/ incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0001.json incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0003.json incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0004.json incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/pig_f9957a11-a902-4f01-ac53-9679ce3a4b13.json incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/runs2.json incubator/ambari/branches/branch-1.4.0/ambari-web/app/classes/app_class.js (with props) incubator/ambari/branches/branch-1.4.0/ambari-web/app/mappers/apps_mapper.js (with props) incubator/ambari/branches/branch-1.4.0/ambari-web/app/models/apps.js (with props) incubator/ambari/branches/branch-1.4.0/ambari-web/app/templates/main/apps/item/app.hbs incubator/ambari/branches/branch-1.4.0/ambari-web/app/utils/app_graph.js (with props) incubator/ambari/branches/branch-1.4.0/ambari-web/app/views/main/apps/item/app_view.js (with props) Modified: incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/db/DBConnector.java incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/db/PostgresConnector.java incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/WorkflowContext.java incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/Workflows.java incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/webservice/WorkflowJsonService.java incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql incubator/ambari/branches/branch-1.4.0/ambari-web/app/classes/run_class.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/controllers/main/apps/item_controller.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/controllers/main/apps_controller.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/initialize.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/mappers/runs_mapper.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/messages.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/models.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/models/run.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/routes/main.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/styles/apps.less incubator/ambari/branches/branch-1.4.0/ambari-web/app/templates/main/apps.hbs incubator/ambari/branches/branch-1.4.0/ambari-web/app/templates/main/apps/list_row.hbs incubator/ambari/branches/branch-1.4.0/ambari-web/app/views.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/views/main/apps/item_view.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/views/main/apps_view.js incubator/ambari/branches/branch-1.4.0/ambari-web/app/views/main/menu.js Modified: incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/db/DBConnector.java URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/db/DBConnector.java?rev=1492013&r1=1492012&r2=1492013&view=diff ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/db/DBConnector.java (original) +++ incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/db/DBConnector.java Tue Jun 11 23:56:21 2013 @@ -19,11 +19,8 @@ package org.apache.ambari.eventdb.db; import java.io.IOException; import java.util.List; -import org.apache.ambari.eventdb.model.DataTable; +import org.apache.ambari.eventdb.model.*; import org.apache.ambari.eventdb.model.Jobs.JobDBEntry; -import org.apache.ambari.eventdb.model.TaskAttempt; -import org.apache.ambari.eventdb.model.WorkflowContext; -import org.apache.ambari.eventdb.model.Workflows; import org.apache.ambari.eventdb.model.Workflows.WorkflowDBEntry.WorkflowFields; public interface DBConnector { @@ -37,9 +34,11 @@ public interface DBConnector { public DataTable fetchWorkflows(int offset, int limit, String searchTerm, int echo, WorkflowFields field, boolean sortAscending, String searchWorkflowId, String searchWorkflowName, String searchWorkflowType, String searchUserName, int minJobs, int maxJobs, long minInputBytes, long maxInputBytes, - long minOutputBytes, long maxOutputBytes, long minDuration, long maxDuration, long minStartTime, long maxStartTime, long minFinishTime, long maxFinishTime) - throws IOException; - + long minOutputBytes, long maxOutputBytes, long minDuration, long maxDuration, long minStartTime, long maxStartTime, long minFinishTime, + long maxFinishTime, String tagSearchTerm) throws IOException; + + public List fetchAppDetails(String workflowId) throws IOException; + public List fetchJobDetails(String workflowID) throws IOException; public List fetchJobDetails(long minFinishTime, long maxStartTime) throws IOException; Modified: incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/db/PostgresConnector.java URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/db/PostgresConnector.java?rev=1492013&r1=1492012&r2=1492013&view=diff ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/db/PostgresConnector.java (original) +++ incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/db/PostgresConnector.java Tue Jun 11 23:56:21 2013 @@ -27,20 +27,18 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; -import org.apache.ambari.eventdb.model.DataTable; +import org.apache.ambari.eventdb.model.*; import org.apache.ambari.eventdb.model.DataTable.AvgData; import org.apache.ambari.eventdb.model.DataTable.Summary; import org.apache.ambari.eventdb.model.DataTable.Summary.SummaryFields; import org.apache.ambari.eventdb.model.DataTable.Times; import org.apache.ambari.eventdb.model.Jobs.JobDBEntry; import org.apache.ambari.eventdb.model.Jobs.JobDBEntry.JobFields; -import org.apache.ambari.eventdb.model.TaskAttempt; import org.apache.ambari.eventdb.model.TaskAttempt.TaskAttemptFields; -import org.apache.ambari.eventdb.model.WorkflowContext; -import org.apache.ambari.eventdb.model.Workflows; import org.apache.ambari.eventdb.model.Workflows.WorkflowDBEntry; import org.apache.ambari.eventdb.model.Workflows.WorkflowDBEntry.WorkflowFields; import org.apache.commons.lang.NotImplementedException; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.jackson.JsonParseException; @@ -50,6 +48,7 @@ import org.codehaus.jackson.map.ObjectMa public class PostgresConnector implements DBConnector { private static Log LOG = LogFactory.getLog(PostgresConnector.class); private static final String WORKFLOW_TABLE_NAME = "workflow"; + private static final String APP_TABLE_NAME = "application"; private static final String JOB_TABLE_NAME = "job"; private static final String TASK_ATTEMPT_TABLE_NAME = "taskattempt"; public static final String SORT_ASC = "ASC"; @@ -75,6 +74,7 @@ public class PostgresConnector implement + getAvg(WorkflowFields.DURATION, SummaryFields.avgDuration, SummaryFields.minDuration, SummaryFields.maxDuration) + ", min(" + WorkflowFields.STARTTIME + ") as " + SummaryFields.youngest + ", max(" + WorkflowFields.STARTTIME + ") as " + SummaryFields.oldest + " FROM " + WORKFLOW_TABLE_NAME), + FAD_PS("SELECT " + Apps.AppDBEntry.APP_FIELDS + " FROM " + APP_TABLE_NAME + " WHERE " + Apps.AppDBEntry.AppFields.WORKFLOWID.toString() + " = ?"), FJD_PS("SELECT " + JobDBEntry.JOB_FIELDS + " FROM " + JOB_TABLE_NAME + " WHERE " + JobFields.WORKFLOWID.toString() + " = ?"), FJD_TIMERANGE_PS("SELECT " + JobDBEntry.JOB_FIELDS + " FROM " + JOB_TABLE_NAME + " WHERE " + JobFields.FINISHTIME.toString() + " >= ? AND " + JobFields.SUBMITTIME.toString() + " <= ? ORDER BY " + JobFields.WORKFLOWID + ", " + JobFields.JOBID), @@ -213,6 +213,7 @@ public class PostgresConnector implement w.setOutputBytes(WorkflowFields.OUTPUTBYTES.getLong(rs)); w.setNumJobsCompleted(WorkflowFields.NUMJOBSCOMPLETED.getInt(rs)); w.setWorkflowContext(jsonMapper.readValue(WorkflowFields.WORKFLOWCONTEXT.getString(rs), WorkflowContext.class)); + w.setWorkflowTags(WorkflowFields.WORKFLOWTAGS.getString(rs)); return w; } @@ -227,8 +228,8 @@ public class PostgresConnector implement @Override public DataTable fetchWorkflows(int offset, int limit, String searchTerm, int echo, WorkflowFields col, boolean sortAscending, String searchWorkflowId, String searchWorkflowName, String searchWorkflowType, String searchUserName, int minJobs, int maxJobs, long minInputBytes, long maxInputBytes, - long minOutputBytes, long maxOutputBytes, long minDuration, long maxDuration, long minStartTime, long maxStartTime, long minFinishTime, long maxFinishTime) - throws IOException { + long minOutputBytes, long maxOutputBytes, long minDuration, long maxDuration, long minStartTime, long maxStartTime, long minFinishTime, + long maxFinishTime, String tagSearchTerm) throws IOException { int total = 0; PreparedStatement ps = getPS(Statements.FW_COUNT_PS); ResultSet rs = null; @@ -248,7 +249,8 @@ public class PostgresConnector implement } String searchClause = buildSearchClause(searchTerm, searchWorkflowId, searchWorkflowName, searchWorkflowType, searchUserName, minJobs, maxJobs, - minInputBytes, maxInputBytes, minOutputBytes, maxOutputBytes, minDuration, maxDuration, minStartTime, maxStartTime, minFinishTime, maxFinishTime); + minInputBytes, maxInputBytes, minOutputBytes, maxOutputBytes, minDuration, maxDuration, minStartTime, maxStartTime, minFinishTime, maxFinishTime, + tagSearchTerm); List workflows = fetchWorkflows(getQualifiedPS(Statements.FW_PS, searchClause, col, sortAscending, offset, limit)); Summary summary = fetchSummary(getQualifiedPS(Statements.FW_SUMMARY_PS, searchClause)); DataTable table = new DataTable(); @@ -266,7 +268,54 @@ public class PostgresConnector implement table.setSummary(summary); return table; } - + + private static Apps.AppDBEntry getAppDBEntry(ResultSet rs) throws SQLException { + Apps.AppDBEntry a = new Apps.AppDBEntry(); + a.setWorkflowId(Apps.AppDBEntry.AppFields.WORKFLOWID.getString(rs)); + a.setWorkflowEntityName(Apps.AppDBEntry.AppFields.WORKFLOWENTITYNAME.getString(rs)); + a.setAppId(Apps.AppDBEntry.AppFields.APPID.getString(rs)); + a.setAppName(Apps.AppDBEntry.AppFields.APPNAME.getString(rs)); + a.setAppType(Apps.AppDBEntry.AppFields.APPTYPE.getString(rs)); + a.setFinishTime(Apps.AppDBEntry.AppFields.FINISHTIME.getLong(rs)); + a.setLaunchTime(Apps.AppDBEntry.AppFields.LAUNCHTIME.getLong(rs)); + a.setQueue(Apps.AppDBEntry.AppFields.QUEUE.getString(rs)); + String[] stageStrings = StringUtils.split(Apps.AppDBEntry.AppFields.APPINFO.getString(rs), "-"); + List stages = new ArrayList(); + for (String s : stageStrings) + stages.add(Integer.parseInt(s)); + a.setStages(stages); + a.setStatus(Apps.AppDBEntry.AppFields.STATUS.getString(rs)); + a.setSubmitTime(Apps.AppDBEntry.AppFields.SUBMITTIME.getLong(rs)); + a.setUserName(Apps.AppDBEntry.AppFields.USERNAME.getString(rs)); + return a; + } + + @Override + public List fetchAppDetails(String workflowId) throws IOException { + PreparedStatement ps = getPS(Statements.FAD_PS); + List apps = new ArrayList(); + ResultSet rs = null; + try { + ps.setString(1, workflowId); + rs = ps.executeQuery(); + while (rs.next()) { + apps.add(getAppDBEntry(rs)); + } + rs.close(); + } catch (SQLException e) { + throw new IOException(e); + } finally { + if (rs != null) + try { + rs.close(); + } catch (SQLException e) { + LOG.error("Exception while closing ResultSet", e); + } + + } + return apps; + } + private static JobDBEntry getJobDBEntry(ResultSet rs) throws SQLException { JobDBEntry j = new JobDBEntry(); j.setConfPath(JobFields.CONFPATH.getString(rs)); @@ -288,7 +337,7 @@ public class PostgresConnector implement j.setWorkflowId(JobFields.WORKFLOWID.getString(rs)); return j; } - + @Override public List fetchJobDetails(String workflowId) throws IOException { PreparedStatement ps = getPS(Statements.FJD_PS); @@ -310,11 +359,11 @@ public class PostgresConnector implement } catch (SQLException e) { LOG.error("Exception while closing ResultSet", e); } - + } return jobs; } - + @Override public List fetchJobDetails(long minFinishTime, long maxStartTime) throws IOException { PreparedStatement ps = getPS(Statements.FJD_TIMERANGE_PS); @@ -547,7 +596,7 @@ public class PostgresConnector implement private static String buildSearchClause(String searchTerm, String searchWorkflowId, String searchWorkflowName, String searchWorkflowType, String searchUserName, int minJobs, int maxJobs, long minInputBytes, long maxInputBytes, long minOutputBytes, long maxOutputBytes, long minDuration, - long maxDuration, long minStartTime, long maxStartTime, long minFinishTime, long maxFinishTime) { + long maxDuration, long minStartTime, long maxStartTime, long minFinishTime, long maxFinishTime, String searchTags) { StringBuilder sb = new StringBuilder(); sb.append(WHERE); if (searchTerm != null && searchTerm.length() > 0) { @@ -567,6 +616,8 @@ public class PostgresConnector implement append(sb, startsWith(WorkflowFields.WORKFLOWID, searchWorkflowType)); if (searchUserName != null) append(sb, equals(WorkflowFields.USERNAME, searchUserName)); + if (searchTags != null) + append(sb, like(WorkflowFields.WORKFLOWTAGS, searchTags)); addRangeSearch(sb, WorkflowFields.NUMJOBSTOTAL, minJobs, maxJobs); addRangeSearch(sb, WorkflowFields.INPUTBYTES, minInputBytes, maxInputBytes); addRangeSearch(sb, WorkflowFields.OUTPUTBYTES, minOutputBytes, maxOutputBytes); Added: incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/Apps.java URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/Apps.java?rev=1492013&view=auto ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/Apps.java (added) +++ incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/Apps.java Tue Jun 11 23:56:21 2013 @@ -0,0 +1,193 @@ +/** + * 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. + */ +package org.apache.ambari.eventdb.model; + +import org.apache.commons.lang.StringUtils; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class Apps { + List apps; + + public static class AppDBEntry { + public static enum AppFields { + APPID, + APPNAME, + APPTYPE, + STATUS, + USERNAME, + QUEUE, + SUBMITTIME, + LAUNCHTIME, + FINISHTIME, + APPINFO, + WORKFLOWID, + WORKFLOWENTITYNAME; + + public String getString(ResultSet rs) throws SQLException { + return rs.getString(this.toString()); + } + + public int getInt(ResultSet rs) throws SQLException { + return rs.getInt(this.toString()); + } + + public long getLong(ResultSet rs) throws SQLException { + return rs.getLong(this.toString()); + } + + public static String join() { + String[] tmp = new String[AppFields.values().length]; + for (int i = 0; i < tmp.length; i++) + tmp[i] = AppFields.values()[i].toString(); + return StringUtils.join(tmp, ","); + } + } + + @XmlTransient + public static final String APP_FIELDS = AppFields.join(); + + private String appId; + private String appName; + private String appType; + private String status; + private String userName; + private String queue; + private long submitTime; + private long launchTime; + private long finishTime; + private List stages; + private String workflowId; + private String workflowEntityName; + + public AppDBEntry() { + /* Required by JAXB. */ + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getAppType() { + return appType; + } + + public void setAppType(String appType) { + this.appType = appType; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getQueue() { + return queue; + } + + public void setQueue(String queue) { + this.queue = queue; + } + + public long getSubmitTime() { + return submitTime; + } + + public void setSubmitTime(long submitTime) { + this.submitTime = submitTime; + } + + public long getLaunchTime() { + return launchTime; + } + + public void setLaunchTime(long launchTime) { + this.launchTime = launchTime; + } + + public long getFinishTime() { + return finishTime; + } + + public void setFinishTime(long finishTime) { + this.finishTime = finishTime; + } + + public List getStages() { + return stages; + } + + public void setStages(List stages) { + this.stages = stages; + } + + public String getWorkflowId() { + return workflowId; + } + + public void setWorkflowId(String workflowId) { + this.workflowId = workflowId; + } + + public String getWorkflowEntityName() { + return workflowEntityName; + } + + public void setWorkflowEntityName(String workflowEntityName) { + this.workflowEntityName = workflowEntityName; + } + } + + public List getApps() { + return apps; + } + + public void setApps(List apps) { + this.apps = apps; + } +} Propchange: incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/Apps.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/WorkflowContext.java URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/WorkflowContext.java?rev=1492013&r1=1492012&r2=1492013&view=diff ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/WorkflowContext.java (original) +++ incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/WorkflowContext.java Tue Jun 11 23:56:21 2013 @@ -29,6 +29,7 @@ public class WorkflowContext { private String workflowId; private String workflowName; private String workflowEntityName; + private String workflowTags; private WorkflowDag workflowDag; @@ -51,6 +52,10 @@ public class WorkflowContext { return this.workflowEntityName; } + public String getWorkflowTags() { + return workflowTags; + } + public WorkflowDag getWorkflowDag() { return this.workflowDag; } @@ -72,6 +77,10 @@ public class WorkflowContext { this.workflowEntityName = wfEntityName; } + public void setWorkflowTags(String workflowTags) { + this.workflowTags = workflowTags; + } + public void setWorkflowDag(WorkflowDag wfDag) { this.workflowDag = wfDag; } Modified: incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/Workflows.java URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/Workflows.java?rev=1492013&r1=1492012&r2=1492013&view=diff ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/Workflows.java (original) +++ incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/model/Workflows.java Tue Jun 11 23:56:21 2013 @@ -47,7 +47,8 @@ public class Workflows { INPUTBYTES, OUTPUTBYTES, PARENTWORKFLOWID, - WORKFLOWCONTEXT; + WORKFLOWCONTEXT, + WORKFLOWTAGS; public String getString(ResultSet rs) throws SQLException { return rs.getString(this.toString()); @@ -83,6 +84,7 @@ public class Workflows { private int numJobsCompleted; private String parentWorkflowId; private WorkflowContext workflowContext; + private String workflowTags; public WorkflowDBEntry() { /* Required by JAXB. */ @@ -124,6 +126,10 @@ public class Workflows { return workflowContext; } + public String getWorkflowTags() { + return workflowTags; + } + public void setWorkflowId(String workflowId) { this.workflowId = workflowId; } @@ -160,6 +166,10 @@ public class Workflows { this.workflowContext = workflowContext; } + public void setWorkflowTags(String workflowTags) { + this.workflowTags = workflowTags; + } + public long getInputBytes() { return inputBytes; } Modified: incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/webservice/WorkflowJsonService.java URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/webservice/WorkflowJsonService.java?rev=1492013&r1=1492012&r2=1492013&view=diff ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/webservice/WorkflowJsonService.java (original) +++ incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/java/org/apache/ambari/eventdb/webservice/WorkflowJsonService.java Tue Jun 11 23:56:21 2013 @@ -36,15 +36,10 @@ import javax.ws.rs.core.MediaType; import org.apache.ambari.eventdb.db.MySQLConnector; import org.apache.ambari.eventdb.db.OracleConnector; import org.apache.ambari.eventdb.db.PostgresConnector; -import org.apache.ambari.eventdb.model.DataTable; -import org.apache.ambari.eventdb.model.Jobs; +import org.apache.ambari.eventdb.model.*; import org.apache.ambari.eventdb.model.Jobs.JobDBEntry; -import org.apache.ambari.eventdb.model.TaskAttempt; -import org.apache.ambari.eventdb.model.TaskData; import org.apache.ambari.eventdb.model.TaskData.Point; -import org.apache.ambari.eventdb.model.TaskLocalityData; import org.apache.ambari.eventdb.model.TaskLocalityData.DataPoint; -import org.apache.ambari.eventdb.model.Workflows; import org.apache.ambari.eventdb.model.Workflows.WorkflowDBEntry; import org.apache.ambari.eventdb.model.Workflows.WorkflowDBEntry.WorkflowFields; import org.apache.ambari.server.configuration.Configuration; @@ -67,6 +62,7 @@ public class WorkflowJsonService { private static final Workflows EMPTY_WORKFLOWS = new Workflows(); private static final List EMPTY_JOBS = Collections.emptyList(); + private static final List EMPTY_APPS = Collections.emptyList(); { List emptyWorkflows = Collections.emptyList(); EMPTY_WORKFLOWS.setWorkflows(emptyWorkflows); @@ -138,7 +134,8 @@ public class WorkflowJsonService { @DefaultValue("-1") @QueryParam("minOutputBytes") long minOutputBytes, @DefaultValue("-1") @QueryParam("maxOutputBytes") long maxOutputBytes, @DefaultValue("-1") @QueryParam("minDuration") long minDuration, @DefaultValue("-1") @QueryParam("maxDuration") long maxDuration, @DefaultValue("-1") @QueryParam("minStartTime") long minStartTime, @DefaultValue("-1") @QueryParam("maxStartTime") long maxStartTime, - @DefaultValue("-1") @QueryParam("minFinishTime") long minFinishTime, @DefaultValue("-1") @QueryParam("maxFinishTime") long maxFinishTime) { + @DefaultValue("-1") @QueryParam("minFinishTime") long minFinishTime, @DefaultValue("-1") @QueryParam("maxFinishTime") long maxFinishTime, + @QueryParam("tagSearch") String tagSearchTerm) { if (start < 0) start = 0; @@ -163,22 +160,25 @@ public class WorkflowJsonService { case 3: // userName field = WorkflowFields.USERNAME; break; - case 4: // numJobsTotal + case 4: // tags + field = WorkflowFields.WORKFLOWTAGS; + break; + case 5: // numJobsTotal field = WorkflowFields.NUMJOBSTOTAL; break; - case 5: // inputBytes + case 6: // inputBytes field = WorkflowFields.INPUTBYTES; break; - case 6: // outputBytes + case 7: // outputBytes field = WorkflowFields.OUTPUTBYTES; break; - case 7: // duration + case 8: // duration field = WorkflowFields.DURATION; break; - case 8: // startTime + case 9: // startTime field = WorkflowFields.STARTTIME; break; - case 9: // lastUpdateTime + case 10: // lastUpdateTime field = WorkflowFields.LASTUPDATETIME; break; default: @@ -190,7 +190,8 @@ public class WorkflowJsonService { try { conn = getConnector(); table = conn.fetchWorkflows(start, amount, searchTerm, echo, field, sortAscending, workflowId, workflowName, workflowType, userName, minJobs, maxJobs, - minInputBytes, maxInputBytes, minOutputBytes, maxOutputBytes, minDuration, maxDuration, minStartTime, maxStartTime, minFinishTime, maxFinishTime); + minInputBytes, maxInputBytes, minOutputBytes, maxOutputBytes, minDuration, maxDuration, minStartTime, maxStartTime, minFinishTime, maxFinishTime, + tagSearchTerm); } catch (IOException e) { LOG.error("Error interacting with RCA database ", e); } finally { @@ -200,7 +201,28 @@ public class WorkflowJsonService { } return table; } - + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/app") + public Apps getApps(@QueryParam("workflowId") String workflowId) { + Apps apps = new Apps(); + apps.setApps(EMPTY_APPS); + PostgresConnector conn = null; + try { + conn = getConnector(); + if (workflowId != null) + apps.setApps(conn.fetchAppDetails(workflowId)); + } catch (IOException e) { + LOG.error("Error interacting with RCA database ", e); + } finally { + if (conn != null) { + conn.close(); + } + } + return apps; + } + @GET @Produces(MediaType.APPLICATION_JSON) @Path("/job") @@ -224,7 +246,7 @@ public class WorkflowJsonService { } return jobs; } - + @GET @Produces(MediaType.APPLICATION_JSON) @Path("/task") Modified: incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql?rev=1492013&r1=1492012&r2=1492013&view=diff ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql (original) +++ incubator/ambari/branches/branch-1.4.0/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql Tue Jun 11 23:56:21 2013 @@ -198,13 +198,28 @@ CREATE TABLE workflow ( startTime BIGINT, lastUpdateTime BIGINT, numJobsTotal INTEGER, numJobsCompleted INTEGER, inputBytes BIGINT, outputBytes BIGINT, - duration BIGINT, + duration BIGINT, workflowTags TEXT, PRIMARY KEY (workflowId), FOREIGN KEY (parentWorkflowId) REFERENCES workflow(workflowId) ); GRANT ALL PRIVILEGES ON TABLE workflow TO "mapred"; +CREATE TABLE application ( + appId TEXT, + workflowId TEXT, + appName TEXT, + workflowEntityName TEXT, + userName TEXT, queue TEXT, + submitTime BIGINT, launchTime BIGINT, finishTime BIGINT, + appType TEXT, + status TEXT, + appInfo TEXT, + PRIMARY KEY(appId), FOREIGN KEY(workflowId) REFERENCES workflow(workflowId) +); + +GRANT ALL PRIVILEGES ON TABLE application TO "mapred"; + CREATE TABLE job ( jobId TEXT, workflowId TEXT, jobName TEXT, workflowEntityName TEXT, userName TEXT, queue TEXT, acls TEXT, confPath TEXT, Added: incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0001.json URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0001.json?rev=1492013&view=auto ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0001.json (added) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0001.json Tue Jun 11 23:56:21 2013 @@ -0,0 +1,16 @@ +{ + "apps": [ + { + "appId": "job_201301280808_0001", + "appName": "word count", + "appType": "MAPREDUCE", + "status": "SUCCESS", + "userName": "ambari_qa", + "submitTime": 1359378637135, + "finishTime": 1359378667350, + "stages": [1,1], + "workflowId": "mapreduce_201301280808_0001", + "workflowEntityName": "1" + } + ] +} Added: incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0003.json URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0003.json?rev=1492013&view=auto ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0003.json (added) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0003.json Tue Jun 11 23:56:21 2013 @@ -0,0 +1,16 @@ +{ + "apps": [ + { + "appId": "job_201301280808_0003", + "appName": "oozie:launcher:T\\=map-reduce:W\\=map-reduce-wf:A\\=mr-node:ID\\=0000000-130128081151371-oozie-oozi-W", + "appType": "MAPREDUCE", + "status": "SUCCESS", + "userName": "ambari_qa", + "submitTime": 1359378907927, + "finishTime": 1359378927213, + "stages": [1,0], + "workflowId": "mapreduce_201301280808_0003", + "workflowEntityName": "3" + } + ] +} Added: incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0004.json URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0004.json?rev=1492013&view=auto ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0004.json (added) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/mapreduce_201301280808_0004.json Tue Jun 11 23:56:21 2013 @@ -0,0 +1,40 @@ +{ + "apps": [ + { + "appId": "job_201301280808_0002", + "appName": "oozie:action:T\\=map-reduce:W\\=map-reduce-wf:A\\=mr-node:ID\\=0000000-130128081151371-oozie-oozi-W", + "appType": "MAPREDUCE", + "status": "SUCCESS", + "userName": "ambari_qa", + "submitTime": 1359378922503, + "finishTime": 1359378949583, + "stages": [1,1], + "workflowId": "mapreduce_201301280808_0002", + "workflowEntityName": "2" + }, + { + "appId": "job_201301280808_0004", + "appName": "oozie:action:T\\=map-reduce:W\\=map-reduce-wf:A\\=mr-node:ID\\=0000000-130128081151371-oozie-oozi-W", + "appType": "MAPREDUCE", + "status": "SUCCESS", + "userName": "ambari_qa", + "submitTime": 1359378922503, + "finishTime": 1359378949583, + "stages": [1,1], + "workflowId": "mapreduce_201301280808_0004", + "workflowEntityName": "4" + }, + { + "appId": "job_201301280808_0003", + "appName": "oozie:action:T\\=map-reduce:W\\=map-reduce-wf:A\\=mr-node:ID\\=0000000-130128081151371-oozie-oozi-W", + "appType": "MAPREDUCE", + "status": "SUCCESS", + "userName": "ambari_qa", + "submitTime": 1359378922503, + "finishTime": 1359378949583, + "stages": [1,1], + "workflowId": "mapreduce_201301280808_0003", + "workflowEntityName": "3" + } + ] +} Added: incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/pig_f9957a11-a902-4f01-ac53-9679ce3a4b13.json URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/pig_f9957a11-a902-4f01-ac53-9679ce3a4b13.json?rev=1492013&view=auto ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/pig_f9957a11-a902-4f01-ac53-9679ce3a4b13.json (added) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/apps/pig_f9957a11-a902-4f01-ac53-9679ce3a4b13.json Tue Jun 11 23:56:21 2013 @@ -0,0 +1,16 @@ +{ + "apps": [ + { + "appId": "job_201301280808_0002", + "appName": "PigLatin:pigSmoke\\.sh", + "appType": "MAPREDUCE", + "status": "SUCCESS", + "userName": "ambari_qa", + "submitTime": 1359378741973, + "finishTime": 1359378760098, + "stages": [1,0], + "workflowId": "pig_f9957a11-a902-4f01-ac53-9679ce3a4b13", + "workflowEntityName": "scope-5" + } + ] +} Added: incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/runs2.json URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/runs2.json?rev=1492013&view=auto ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/runs2.json (added) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/assets/data/apps/runs2.json Tue Jun 11 23:56:21 2013 @@ -0,0 +1,130 @@ +{ + "sEcho": 0, + "iTotalRecords": 4, + "iTotalDisplayRecords": 4, + "startIndex": 0, + "endIndex": 3, + "aaData": [ + { + "workflowId": "mapreduce_201301280808_0001", + "workflowName": "word count", + "userName": "ambari_qa", + "startTime": 1359378637135, + "elapsedTime": 30215, + "inputBytes": 0, + "outputBytes": 0, + "numJobsTotal": 1, + "numJobsCompleted": 1, + "workflowTags": "tag", + "workflowContext": { + "workflowDag": { + "entries": [ + { + "source": "1", + "targets": [ + + ] + } + ] + } + } + }, + { + "workflowId": "mapreduce_201301280808_0003", + "workflowName": "oozie:launcher:T\\=map-reduce:W\\=map-reduce-wf:A\\=mr-node:ID\\=0000000-130128081151371-oozie-oozi-W", + "userName": "ambari_qa", + "startTime": 1359378907927, + "elapsedTime": 19186, + "inputBytes": 0, + "outputBytes": 0, + "numJobsTotal": 1, + "numJobsCompleted": 1, + "workflowContext": { + "workflowDag": { + "entries": [ + { + "source": "3", + "targets": [ + + ] + } + ] + } + } + }, + { + "workflowId": "mapreduce_201301280808_0004", + "workflowName": "oozie:action:T\\=map-reduce:W\\=map-reduce-wf:A\\=mr-node:ID\\=0000000-130128081151371-oozie-oozi-W", + "userName": "ambari_qa", + "startTime": 1359378922503, + "elapsedTime": 27080, + "inputBytes": 0, + "outputBytes": 0, + "numJobsTotal": 3, + "numJobsCompleted": 1, + "workflowTags": "tag", + "workflowContext": { + "workflowDag": { + "entries": [ + { + "source": "4", + "targets": [ + + ] + } + ] + } + } + }, + { + "workflowId": "pig_f9957a11-a902-4f01-ac53-9679ce3a4b13", + "workflowName": "\/tmp\/pigSmoke.sh", + "userName": "ambari_qa", + "startTime": 1359378741973, + "elapsedTime": 18125, + "inputBytes": 0, + "outputBytes": 0, + "numJobsTotal": 1, + "numJobsCompleted": 1, + "workflowContext": { + "workflowDag": { + "entries": [ + { + "source": "scope-5", + "targets": [ + + ] + } + ] + } + } + } + ], + "summary": { + "numRows": 4, + "jobs": { + "avg": 1, + "min": 1, + "max": 1 + }, + "input": { + "avg": 0, + "min": 0, + "max": 0 + }, + "output": { + "avg": 0, + "min": 0, + "max": 0 + }, + "duration": { + "avg": 23651.5, + "min": 18125, + "max": 30215 + }, + "times": { + "oldest": 1359378922503, + "youngest": 1359378637135 + } + } +} Added: incubator/ambari/branches/branch-1.4.0/ambari-web/app/classes/app_class.js URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/classes/app_class.js?rev=1492013&view=auto ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/classes/app_class.js (added) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/classes/app_class.js Tue Jun 11 23:56:21 2013 @@ -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. + */ + + +var App = require('app'); +var date = require('utils/date'); +var misc = require('utils/misc'); + +App.App2 = Ember.Object.extend({ + + app_id: "", //string + app_name: "", //string + app_type: "", //string + workflow_entity_name: "", //string + user_name: "", //string + queue: "", //string + submit_time: 0, //number + launch_time: 0, //number + finish_time: 0, //number + num_stages: 0, //number + stages: [], //number + status: "", //string +}); Propchange: incubator/ambari/branches/branch-1.4.0/ambari-web/app/classes/app_class.js ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: incubator/ambari/branches/branch-1.4.0/ambari-web/app/classes/run_class.js URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/classes/run_class.js?rev=1492013&r1=1492012&r2=1492013&view=diff ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/classes/run_class.js (original) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/classes/run_class.js Tue Jun 11 23:56:21 2013 @@ -32,6 +32,7 @@ App.Run2 = Ember.Object.extend({ workflowContext: null, //string input: 0, //number output: 0, //number + tags: null, //string /** * Will set to true when we load all jobs related to this run @@ -95,9 +96,9 @@ App.Run2 = Ember.Object.extend({ if (this.get('id').indexOf('hive_') === 0) { return 'Hive'; } - if (this.get('id').indexOf('mr_') === 0) { + if (this.get('id').indexOf('mr_') === 0 || this.get('id').indexOf('mapreduce_') === 0) { return 'MapReduce'; } return 'Undefined'; }.property('id') -}); \ No newline at end of file +}); Modified: incubator/ambari/branches/branch-1.4.0/ambari-web/app/controllers/main/apps/item_controller.js URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/controllers/main/apps/item_controller.js?rev=1492013&r1=1492012&r2=1492013&view=diff ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/controllers/main/apps/item_controller.js (original) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/controllers/main/apps/item_controller.js Tue Jun 11 23:56:21 2013 @@ -17,6 +17,7 @@ */ var App = require('app'); +var stringUtils = require('utils/string_utils'); App.MainAppsItemController = Em.Controller.extend({ name:'mainAppsItemController', @@ -39,16 +40,29 @@ App.MainAppsItemController = Em.Controll this.set('lastJobId', currentId); var self = this; - var url = App.testMode ? '/data/apps/jobs/'+ currentId +'.json' : - App.apiPrefix + "/jobhistory/job?workflowId=" + currentId; - - var mapper = App.jobsMapper; - mapper.set('controller', this); - App.HttpClient.get(url, mapper,{ - complete:function(jqXHR, textStatus) { - self.set('content.loadAllJobs', true); - } - }); + if (!App.testMode && stringUtils.compareVersions(App.get('currentStackVersionNumber'), "2.0") === -1) { + var url = App.testMode ? '/data/apps/jobs/'+ currentId +'.json' : + App.apiPrefix + "/jobhistory/job?workflowId=" + currentId; + + var mapper = App.jobsMapper; + mapper.set('controller', this); + App.HttpClient.get(url, mapper,{ + complete:function(jqXHR, textStatus) { + self.set('content.loadAllJobs', true); + } + }); + } else { + var url = App.testMode ? '/data/apps/apps/'+ currentId +'.json' : + App.apiPrefix + "/jobhistory/app?workflowId=" + currentId; + + var mapper = App.appsMapper; + mapper.set('controller', this); + App.HttpClient.get(url, mapper,{ + complete:function(jqXHR, textStatus) { + self.set('content.loadAllJobs', true); + } + }); + } }.observes('content') }) Modified: incubator/ambari/branches/branch-1.4.0/ambari-web/app/controllers/main/apps_controller.js URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/controllers/main/apps_controller.js?rev=1492013&r1=1492012&r2=1492013&view=diff ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/controllers/main/apps_controller.js (original) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/controllers/main/apps_controller.js Tue Jun 11 23:56:21 2013 @@ -19,6 +19,7 @@ var App = require('app'); var misc = require('utils/misc'); var date = require('utils/date'); +var stringUtils = require('utils/string_utils'); App.MainAppsController = Em.ArrayController.extend({ @@ -48,7 +49,7 @@ App.MainAppsController = Em.ArrayControl var self = this; //var runsUrl = App.testMode ? "/data/apps/runs.json" : App.apiPrefix + "/jobhistory/workflow?orderBy=startTime&sortDir=DESC&limit=" + App.maxRunsForAppBrowser; - var runsUrl = App.testMode ? "/data/apps/runs.json" : App.apiPrefix + this.get("runUrl"); + var runsUrl = App.testMode ? "/data/apps/runs2.json" : App.apiPrefix + this.get("runUrl"); App.HttpClient.get(runsUrl, App.runsMapper, { complete:function (jqXHR, textStatus) { @@ -101,6 +102,7 @@ App.MainAppsController = Em.ArrayControl iDisplayStart:"", iSortCol_0:"", sSortDir_0:"", + tagSearch:"", allFilterActivated:false, filteredDisplayRecords:null, @@ -114,7 +116,10 @@ App.MainAppsController = Em.ArrayControl runType:"", onRunTypeChange:function(){ if(this.runType == "MapReduce"){ - this.set("sSearch_2","mr"); + if (!App.testMode && stringUtils.compareVersions(App.get('currentStackVersionNumber'), "2.0") === -1) + this.set("sSearch_2","mr"); + else + this.set("sSearch_2","mapreduce"); }else if(this.runType == "Hive"){ this.set("sSearch_2","hive"); }else if(this.runType == "Pig"){ @@ -323,7 +328,7 @@ App.MainAppsController = Em.ArrayControl "maxJobs", "minInputBytes", "maxInputBytes", "minOutputBytes", "maxOutputBytes", "minDuration", "maxDuration", "minStartTime", "maxStartTime", "sSearch", "iDisplayLength", "iDisplayStart", - "iSortCol_0", "sSortDir_0" + "iSortCol_0", "sSortDir_0", "tagSearch" ]; for (var n=0; n{{view view.nameFilterView}} {{view view.typeFilterView}} {{view view.userFilterView}} + {{view view.tagFilterView}} {{view view.jobsFilterView}} {{view view.inputFilterView}} {{view view.outputFilterView}} Added: incubator/ambari/branches/branch-1.4.0/ambari-web/app/templates/main/apps/item/app.hbs URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/templates/main/apps/item/app.hbs?rev=1492013&view=auto ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/templates/main/apps/item/app.hbs (added) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/templates/main/apps/item/app.hbs Tue Jun 11 23:56:21 2013 @@ -0,0 +1,70 @@ +{{! +* 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. +}} +
+ +
+
    +
  • Unfinished Job
  • +
  • + + + + # + Map Stage with # Tasks
  • +
  • Finished Job
  • +
  • + + + + # + Reduce Stage with # Tasks
  • +
+
+ + + + + {{#view view.sortView contentBinding="controller.content.jobs"}} + {{#if view.parentView.hasManyJobs}}{{view view.parentView.nameSort}}{{/if}} + {{view view.parentView.idSort}} + {{view view.parentView.typeSort}} + {{view view.parentView.statusSort}} + {{view view.parentView.numStagesSort}} + {{view view.parentView.stagesSort}} + {{view view.parentView.durationSort}} + {{/view}} + + + + {{#if view.loaded}} + {{#each job in view.jobs}} + + {{#if view.hasManyJobs}}{{/if}} + + + + + + + + {{/each}} + {{/if}} + +
{{job.entityName}}{{job.name}}{{job.type}}{{job.status}}{{job.numStages}}{{job.stages}}{{job.elapsedTime}}
+ + Modified: incubator/ambari/branches/branch-1.4.0/ambari-web/app/templates/main/apps/list_row.hbs URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/templates/main/apps/list_row.hbs?rev=1492013&r1=1492012&r2=1492013&view=diff ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/templates/main/apps/list_row.hbs (original) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/templates/main/apps/list_row.hbs Tue Jun 11 23:56:21 2013 @@ -20,6 +20,7 @@ {{unbound run.appName}} {{unbound run.type}} {{unbound run.userName}} +{{unbound run.tags}} {{unbound run.numJobsTotal}} {{unbound run.inputFormatted}} {{unbound run.outputFormatted}} Added: incubator/ambari/branches/branch-1.4.0/ambari-web/app/utils/app_graph.js URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/utils/app_graph.js?rev=1492013&view=auto ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/utils/app_graph.js (added) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/utils/app_graph.js Tue Jun 11 23:56:21 2013 @@ -0,0 +1,455 @@ +/** + * 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. + */ + + +module.exports = { + create:function(domId, wfData, jobData, svgw, svgh, nodeHeight, labelFontSize, maxLabelWidth, axisPadding, stageFontSize) { + // initialize variables + var nodes = new Array(); + var links = new Array(); + var numNodes = 0; + var id = domId; + var formatDuration = this.formatDuration; + + // create map from entity names to nodes + var existingNodes = new Array(); + var jobData = (jobData) ? jobData : new Array(); + var minStartTime = 0; + if (jobData.length > 0) + minStartTime = jobData[0].submitTime; + var maxFinishTime = 0; + // iterate through job data + for (var i = 0; i < jobData.length; i++) { + jobData[i].info = "jobId:"+jobData[i].name+" \n"+ + "nodeName:"+jobData[i].entityName+" \n"+ + "status:"+jobData[i].status+" \n"+ + "startTime:"+(new Date(jobData[i].submitTime).toUTCString())+" \n"+ + "duration:"+formatDuration(jobData[i].finishTime - jobData[i].submitTime); +console.log("info "+jobData[i].info); + jobData[i].state = jobData[i].status.substr(0,4)=="SUCC"; + minStartTime = Math.min(minStartTime, jobData[i].submitTime); + maxFinishTime = Math.max(maxFinishTime, jobData[i].finishTime); + // add a node to the nodes array and to a provided map of entity names to nodes + existingNodes[jobData[i].entityName] = jobData[i]; + nodes.push(jobData[i]); + numNodes++; + } + var dag = eval('(' + wfData + ')').dag; + var sourceMarker = new Array(); + var targetMarker = new Array(); + var sourceMap = new Array(); + // for each source node in the context, create links between it and its target nodes + for (var source in dag) { + var sourceNode = null; + if (source in existingNodes) + sourceNode = existingNodes[source]; + for (var i = 0; i < dag[source].length; i++) { + var targetNode = null; + if (dag[source][i] in existingNodes) + targetNode = existingNodes[dag[source][i]]; + // add a link between sourceNode and targetNode + // if source or target is null, add marker indicating unsubmitted job and return + if (sourceNode==null) { + if (targetNode==null) + continue; + sourceMarker.push(targetNode); + continue; + } + if (targetNode==null) { + targetMarker.push(sourceNode); + continue; + } + // add link between nodes + var state = false; + if (sourceNode.state && targetNode.state) + state = true; + links.push({"source":sourceNode, "target":targetNode, "state":state, "value":sourceNode.output}); + // add source to map of targets to sources + if (!(targetNode.name in sourceMap)) + sourceMap[targetNode.name] = new Array(); + sourceMap[targetNode.name].push(sourceNode); + } + } + + // display the graph + // rules of thumb: nodeHeight = 20, labelFontSize = 14, maxLabelWidth = 180 + // nodeHeight = 15, labelFontSize = 10, maxLabelWidth = 120 + // nodeHeight = 40, labelFontSize = 20, maxLabelWidth = 260 + // nodeHeight = 30, labelFontSize = 16 + var nodeHeight = nodeHeight || 26; + var labelFontSize = labelFontSize || 14; + var maxLabelWidth = maxLabelWidth || 165; + var axisPadding = axisPadding || 30; + var stageFontSize = stageFontSize || 16; + + // draw timeline graph + var margin = {"vertical":10, "horizontal":50}; + var w = svgw - 2*margin.horizontal; + + var startTime = minStartTime; + var elapsedTime = maxFinishTime - minStartTime; + var x = d3.time.scale.utc() + .domain([startTime, startTime+elapsedTime]) + .range([0, w]); + var xrel = d3.time.scale() + .domain([0, elapsedTime]) + .range([0, w]); + + // process nodes and determine their x and y positions, width and height + var minNodeSpacing = nodeHeight/2; + var ends = new Array(); + var maxIndex = 0; + nodes.sort(function(a,b){return a.name.localeCompare(b.name);}); + for (var i = 0; i < numNodes; i++) { + var d = nodes[i]; + d.x = x(d.submitTime); + d.w = x(d.finishTime) - x(d.submitTime); + if (d.w < d.stages.length*(nodeHeight-4)) { + d.w = d.stages.length*(nodeHeight-4); + if (d.x + d.w > w) + d.x = w - d.w; + } + var effectiveX = d.x + var effectiveWidth = d.w; + if (d.w < maxLabelWidth) { + effectiveWidth = maxLabelWidth; + if (d.x + effectiveWidth > w) + effectiveX = w - effectiveWidth; + else if (d.x > 0) + effectiveX = d.x+(d.w-maxLabelWidth)/2; + } + // select "lane" (slot for y-position) for this node + // starting at the slot above the node's closest source node (or 0, if none exists) + // and moving down until a slot is found that has no nodes within minNodeSpacing of this node + // excluding slots that contain more than one source of this node + var index = 0; + var rejectIndices = new Array(); + if (d.name in sourceMap) { + var sources = sourceMap[d.name]; + var closestSource = sources[0]; + var indices = new Array(); + for (var j = 0; j < sources.length; j++) { + if (sources[j].index in indices) + rejectIndices[sources[j].index] = true; + indices[sources[j].index] = true; + if (sources[j].submitTime + sources[j].elapsedTime > closestSource.submitTime + closestSource.elapsedTime) + closestSource = sources[j]; + } + index = Math.max(0, closestSource.index-1); + } + while ((index in ends) && ((index in rejectIndices) || (ends[index]+minNodeSpacing >= effectiveX))) { + index++ + } + ends[index] = Math.max(effectiveX + effectiveWidth); + maxIndex = Math.max(maxIndex, index); + d.y = index*2*nodeHeight + axisPadding; + d.h = nodeHeight; + d.index = index; + } + + var h = 2*axisPadding + 2*nodeHeight*(maxIndex+1); + var realh = svgh - 2*margin.vertical; + var scale = 1; + if (h > realh) + scale = realh / h; + svgh = Math.min(svgh, h + 2*margin.vertical); + var svg = d3.select("div#" + id).append("svg:svg") + .attr("width", svgw+"px") + .attr("height", svgh+"px"); + + var svgg = svg.append("g") + .attr("transform", "translate("+margin.horizontal+","+margin.vertical+") scale("+scale+")"); + + // add an untranslated white rectangle below everything + // so mouse doesn't have to be over nodes for panning/zooming + svgg.append("svg:rect") + .attr("x", 0) + .attr("y", 0) + .attr("width", svgw) + .attr("height", svgh/scale) + .attr("style", "fill:white;stroke:none"); + + // create axes + var topAxis = d3.svg.axis() + .scale(x) + .orient("bottom"); + var bottomAxis = d3.svg.axis() + .scale(xrel) + .orient("top") + .tickFormat(function(x) { return formatDuration(x.getTime()); }); + var topg = svgg.append("g") + .attr("class", "x axis top") + .call(topAxis); + topg.append("svg:text") + .attr("class", "axislabel") + .attr("x", -9) + .attr("y", 13) + .text("Time"); + var botg = svgg.append("g") + .attr("class", "x axis bottom") + .call(bottomAxis) + .attr("transform", "translate(0,"+h+")") + botg.append("svg:text") + .attr("class", "axislabel") + .attr("x", -9) + .attr("y", -19) + .text("Elapsed"); + botg.append("svg:text") + .attr("class", "axislabel") + .attr("x", -9) + .attr("y", -4) + .text("Time"); + + + // create a rectangle for each node + var boxes = svgg.append("svg:g").selectAll("rect") + .data(nodes) + .enter().append("svg:rect") + .attr("x", function(d) { return d.x; } ) + .attr("y", function(d) { return d.y; } ) + .attr("width", function(d) { return d.w; } ) + .attr("height", function(d) { return d.h; } ) + .attr("class", function (d) { + return "node " + (d.state ? " finished" : ""); + }) + .attr("id", function (d) { + return d.name; + }) + .append("title") + .text(function(d) { return d.info; }); + + // defs for arrowheads marked as to whether they link finished jobs or not + svgg.append("svg:defs").selectAll("arrowmarker") + .data(["finished", "unfinished", "stage"]) + .enter().append("svg:marker") + .attr("id", String) + .attr("viewBox", "0 -5 10 10") + .attr("markerWidth", 6) + .attr("markerHeight", 6) + .attr("refX", function(d) { return (d==="stage") ? 5 : 3 }) + .attr("orient", "auto") + .append("svg:path") + .attr("d", function(d) { return (d==="stage") ? "M0,-2L6,0L0,2" : "M0,-3L8,0L0,3" }); + // defs for unsubmitted node marker + svgg.append("svg:defs").selectAll("circlemarker") + .data(["circle"]) + .enter().append("svg:marker") + .attr("id", String) + .attr("viewBox", "-2 -2 18 18") + .attr("markerWidth", 10) + .attr("markerHeight", 10) + .attr("refX", 10) + .attr("refY", 5) + .attr("orient", "auto") + .append("svg:circle") + .attr("cx", 5) + .attr("cy", 5) + .attr("r", 5); + + // create dangling links representing unsubmitted jobs + var markerWidth = nodeHeight/2; + var sourceMarker = svgg.append("svg:g").selectAll("line") + .data(sourceMarker) + .enter().append("svg:line") + .attr("x1", function(d) { return d.x - markerWidth; } ) + .attr("x2", function(d) { return d.x; } ) + .attr("y1", function(d) { return d.y; } ) + .attr("y2", function(d) { return d.y + 3; } ) + .attr("class", "source mark") + .attr("marker-start", "url(#circle)"); + var targetMarker = svgg.append("svg:g").selectAll("line") + .data(targetMarker) + .enter().append("svg:line") + .attr("x1", function(d) { return d.x + d.w + markerWidth; } ) + .attr("x2", function(d) { return d.x + d.w; } ) + .attr("y1", function(d) { return d.y + d.h; } ) + .attr("y2", function(d) { return d.y + d.h - 3; } ) + .attr("class", "target mark") + .attr("marker-start", "url(#circle)"); + + // create links between the nodes + var lines = svgg.append("svg:g").selectAll("path") + .data(links) + .enter().append("svg:path") + .attr("d", function(d) { + var s = d.source; + var t = d.target; + var x1 = s.x + s.w; + var x2 = t.x; + var y1 = s.y; + var y2 = t.y; + if (y1==y2) { + y1 += s.h/2; + y2 += t.h/2; + } else if (y1 < y2) { + y1 += s.h; + } else { + y2 += t.h; + } + return "M "+x1+" "+y1+" L "+((x2+x1)/2)+" "+((y2+y1)/2)+" L "+x2+" "+y2; + } ) + .attr("class", function (d) { + return "link" + (d.state ? " finished" : ""); + }) + .attr("marker-mid", function (d) { + return "url(#" + (d.state ? "finished" : "unfinished") + ")"; + }); + + // create text group for each node label + var text = svgg.append("svg:g").selectAll("g") + .data(nodes) + .enter().append("svg:g"); + + // add a shadow copy of the node label (will have a lighter color and thicker + // stroke for legibility) + text.append("svg:text") + .attr("x", function(d) { + var goal = d.x + d.w/2; + var halfLabel = maxLabelWidth/2; + if (goal < halfLabel) return halfLabel; + else if (goal > w-halfLabel) return w-halfLabel; + return goal; + } ) + .attr("y", function(d) { return d.y + d.h + labelFontSize; } ) + .attr("class", "joblabel shadow") + .attr("style", "font: "+labelFontSize+"px sans-serif") + .text(function (d) { + return d.name; + }); + + // add the main node label + text.append("svg:text") + .attr("x", function(d) { + var goal = d.x + d.w/2; + var halfLabel = maxLabelWidth/2; + if (goal < halfLabel) return halfLabel; + else if (goal > w-halfLabel) return w-halfLabel; + return goal; + } ) + .attr("y", function(d) { return d.y + d.h + labelFontSize; } ) + .attr("class", "joblabel") + .attr("style", "font: "+labelFontSize+"px sans-serif") + .text(function (d) { + return d.name; + }); + + // add node stage information + var topstageg = svgg.append("svg:g"); + var mouseg = svgg.append("svg:g"); + var allstageg = topstageg.selectAll("g") + .data(nodes) + .enter().append("svg:g"); + var stageg = allstageg.selectAll("g") + .data(function(d,i) { + var stagedata = new Array(d.stages.length); + var cr = d.h / 2 - 2; + var cy = d.y + cr + 2; + var cxSpacing = d.w / stagedata.length; + if (cxSpacing < 2*cr) + cxSpacing = 2*cr; + var cxBase = d.x + cxSpacing / 2; + for (var j = 0; j < stagedata.length; j++) + stagedata[j] = {"data": d.stages[j], + "index": i, + "num": stagedata.length, + "cr": cr, + "cy": cy, + "cx":cxBase+j*cxSpacing, + "cxSpacing":cxSpacing}; + return stagedata; + }) + .enter().append("svg:g"); + var path = stageg.append("svg:path") + .attr("class", function(d,i) { + if (i==d.num-1 || d.cxSpacing==2*d.cr) { + return "nopath"; + } else { + return "link stage"; + } + }); + stageg.selectAll(".nopath").remove(); + path.attr("d", function(d,i) { + var x1 = d.cx + d.cr; + var x2 = d.cx + d.cxSpacing - d.cr; + return "M "+x1+" "+d.cy+" L "+((x1+x2)/2)+" "+d.cy+" L "+x2+" "+d.cy; + } ) + .attr("marker-end", function (d) { + return "url(#stage)"; + }); + stageg.append("svg:circle") + .attr("class", function(d,i) { return (i==0) ? "stage first" : "stage" }) + .attr("r", function(d) { return d.cr }) + .attr("cx", function(d) { return d.cx }) + .attr("cy", function(d) { return d.cy }) + .append("title") + .text(function(d,i) { + var t = "stage with "+d.data+" task"; + if (d.data!=1) + t = t+"s"; + if (i==0) + t = "Map "+t; + else + t = "Reduce "+t; + return t; + }); + + stageg.append("svg:text") + .attr("class", "stagelabel") + .attr("x", function(d) { return d.cx }) + .attr("y", function(d) { return d.cy }) + .text(function(d) { return d.data }) + .attr("style", function(d) { + var fontSize = stageFontSize; + if (d.data > 9) fontSize = fontSize - 2; + if (d.data > 99) fontSize = fontSize - 4; + if (d.data > 999) fontSize = fontSize - 2; + if (d.data > 9999) fontSize = fontSize - 1; + return "font: "+fontSize+"px sans-serif"; + }); + + svg.call(d3.behavior.zoom().on("zoom", function() { + var left = Math.min(Math.max(d3.event.translate[0]+margin.horizontal, margin.horizontal-w*d3.event.scale*scale), margin.horizontal+w); + var top = Math.min(Math.max(d3.event.translate[1]+margin.vertical, margin.vertical-h*d3.event.scale*scale), margin.vertical+h); + svgg.attr("transform", "translate("+left+","+top+") scale("+(d3.event.scale*scale)+")"); + })); + }, + formatDuration:function(d) { + if (d==0) { return "0" } + var seconds = Math.floor(parseInt(d) / 1000); + if ( seconds < 60 ) + return seconds + "s"; + var minutes = Math.floor(seconds / 60); + if ( minutes < 60 ) { + var x = seconds - 60*minutes; + return minutes + "m" + (x==0 ? "" : " " + x + "s"); + } + var hours = Math.floor(minutes / 60); + if ( hours < 24 ) { + var x = minutes - 60*hours; + return hours + "h" + (x==0 ? "" : " " + x + "m"); + } + var days = Math.floor(hours / 24); + if ( days < 7 ) { + var x = hours - 24*days; + return days + "d " + (x==0 ? "" : " " + x + "h"); + } + var weeks = Math.floor(days / 7); + var x = days - 7*weeks; + return weeks + "w " + (x==0 ? "" : " " + x + "d"); + } +} Propchange: incubator/ambari/branches/branch-1.4.0/ambari-web/app/utils/app_graph.js ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: incubator/ambari/branches/branch-1.4.0/ambari-web/app/views.js URL: http://svn.apache.org/viewvc/incubator/ambari/branches/branch-1.4.0/ambari-web/app/views.js?rev=1492013&r1=1492012&r2=1492013&view=diff ============================================================================== --- incubator/ambari/branches/branch-1.4.0/ambari-web/app/views.js (original) +++ incubator/ambari/branches/branch-1.4.0/ambari-web/app/views.js Tue Jun 11 23:56:21 2013 @@ -133,6 +133,7 @@ require('views/main/apps_view'); require('views/main/apps/item_view'); require('views/main/apps/item/bar_view'); require('views/main/apps/item/dag_view'); +require('views/main/apps/item/app_view'); require('views/main/mirroring_view'); require('views/main/mirroring/dropdown_view'); require('views/main/mirroring/dataset_view');