diff --git a/core/src/main/resources/org/apache/spark/ui/static/timeline-view.css b/core/src/main/resources/org/apache/spark/ui/static/timeline-view.css index 7d1fc0670f711..826d10a05cf86 100644 --- a/core/src/main/resources/org/apache/spark/ui/static/timeline-view.css +++ b/core/src/main/resources/org/apache/spark/ui/static/timeline-view.css @@ -20,7 +20,7 @@ div#application-timeline, div#job-timeline { } #application-timeline div.legend-area { - margin-top: 20px; + margin-top: 5px; } .vis.timeline div.content { @@ -109,6 +109,18 @@ div#application-timeline, div#job-timeline { z-index: 2; } -tr.corresponding-item-hover { - background: #FFE1FA !important; +tr.corresponding-item-hover>td, tr.corresponding-item-hover>th { + background-color: #FFE1FA !important; +} + +#application-timeline.collapsed { + display: none; +} + +#job-timeline.collapsed { + display: none; +} + +.control-panel { + margin-bottom: 5px; } diff --git a/core/src/main/resources/org/apache/spark/ui/static/timeline-view.js b/core/src/main/resources/org/apache/spark/ui/static/timeline-view.js index 781df5d522705..0c6d4f715da6a 100644 --- a/core/src/main/resources/org/apache/spark/ui/static/timeline-view.js +++ b/core/src/main/resources/org/apache/spark/ui/static/timeline-view.js @@ -39,23 +39,31 @@ function drawApplicationTimeline(groupArray, eventObjArray, startTime) { $(".item.range.job.application-timeline-object").each(function() { var getJobId = function(baseElem) { var jobIdText = $($(baseElem).find(".application-timeline-content")[0]).text(); - var jobId = "#job-" + jobIdText.match("\\(Job (\\d+)\\)")[1]; + var jobId = jobIdText.match("\\(Job (\\d+)\\)")[1]; return jobId; - } + }; $(this).click(function() { - window.location.href = getJobId(this); + window.location.href = "job/?id=" + getJobId(this); }); $(this).hover( function() { - $(getJobId(this)).addClass("corresponding-item-hover"); + $("#job-" + getJobId(this)).addClass("corresponding-item-hover"); }, function() { - $(getJobId(this)).removeClass("corresponding-item-hover"); + $("#job-" + getJobId(this)).removeClass("corresponding-item-hover"); } ); }); + + $("span.expand-application-timeline").click(function() { + $("#application-timeline").toggleClass('collapsed'); + + // Switch the class of the arrow from open to closed. + $(this).find('.expand-application-timeline-arrow').toggleClass('arrow-open'); + $(this).find('.expand-application-timeline-arrow').toggleClass('arrow-closed'); + }); } function drawJobTimeline(groupArray, eventObjArray, startTime) { @@ -80,26 +88,36 @@ function drawJobTimeline(groupArray, eventObjArray, startTime) { setupZoomable("#job-timeline-zoom-lock", jobTimeline); $(".item.range.stage.job-timeline-object").each(function() { - - var getStageId = function(baseElem) { + var getStageIdAndAttempt = function(baseElem) { var stageIdText = $($(baseElem).find(".job-timeline-content")[0]).text(); - var stageId = "#stage-" + stageIdText.match("\\(Stage (\\d+\\.\\d+)\\)")[1].replace(".", "-"); - return stageId; - } + var stageIdAndAttempt = stageIdText.match("\\(Stage (\\d+\\.\\d+)\\)")[1].split("."); + return stageIdAndAttempt; + }; $(this).click(function() { - window.location.href = getStageId(this); + var idAndAttempt = getStageIdAndAttempt(this); + var id = idAndAttempt[0]; + var attempt = idAndAttempt[1]; + window.location.href = "../../stages/stage/?id=" + id + "&attempt=" + attempt; }); $(this).hover( function() { - $(getStageId(this)).addClass("corresponding-item-hover"); + $("#stage-" + getStageId(this)).addClass("corresponding-item-hover"); }, function() { - $(getStageId(this)).removeClass("corresponding-item-hover"); + $("#stage-" + getStageId(this)).removeClass("corresponding-item-hover"); } ); }); + + $("span.expand-job-timeline").click(function() { + $("#job-timeline").toggleClass('collapsed'); + + // Switch the class of the arrow from open to closed. + $(this).find('.expand-job-timeline-arrow').toggleClass('arrow-open'); + $(this).find('.expand-job-timeline-arrow').toggleClass('arrow-closed'); + }); } function setupZoomable(id, timeline) { diff --git a/core/src/main/scala/org/apache/spark/ui/exec/ExecutorsTab.scala b/core/src/main/scala/org/apache/spark/ui/exec/ExecutorsTab.scala index bb4bcf06bfec2..0a08b000e2d03 100644 --- a/core/src/main/scala/org/apache/spark/ui/exec/ExecutorsTab.scala +++ b/core/src/main/scala/org/apache/spark/ui/exec/ExecutorsTab.scala @@ -65,7 +65,8 @@ class ExecutorsListener(storageStatusListener: StorageStatusListener) extends Sp executorIdToData(eid) = ExecutorUIData(executorAdded.time) } - override def onExecutorRemoved(executorRemoved: SparkListenerExecutorRemoved): Unit = synchronized { + override def onExecutorRemoved( + executorRemoved: SparkListenerExecutorRemoved): Unit = synchronized { val eid = executorRemoved.executorId val uiData = executorIdToData(eid) uiData.finishTime = Some(executorRemoved.time) diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala b/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala index ddf6d966c305d..b5208b1cd6262 100644 --- a/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala +++ b/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala @@ -30,26 +30,26 @@ import org.apache.spark.JobExecutionStatus /** Page showing list of all ongoing and recently finished jobs */ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") { private val JOBS_LEGEND = -