Skip to content

Commit 28714b6

Browse files
committed
Fixed highlight issue
Implemented toggling function
1 parent 0dc4278 commit 28714b6

File tree

5 files changed

+79
-42
lines changed

5 files changed

+79
-42
lines changed

core/src/main/resources/org/apache/spark/ui/static/timeline-view.css

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ div#application-timeline, div#job-timeline {
2020
}
2121

2222
#application-timeline div.legend-area {
23-
margin-top: 20px;
23+
margin-top: 5px;
2424
}
2525

2626
.vis.timeline div.content {
@@ -109,6 +109,18 @@ div#application-timeline, div#job-timeline {
109109
z-index: 2;
110110
}
111111

112-
tr.corresponding-item-hover {
113-
background: #FFE1FA !important;
112+
tr.corresponding-item-hover>td, tr.corresponding-item-hover>th {
113+
background-color: #FFE1FA !important;
114+
}
115+
116+
#application-timeline.collapsed {
117+
display: none;
118+
}
119+
120+
#job-timeline.collapsed {
121+
display: none;
122+
}
123+
124+
.control-panel {
125+
margin-bottom: 5px;
114126
}

core/src/main/resources/org/apache/spark/ui/static/timeline-view.js

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,31 @@ function drawApplicationTimeline(groupArray, eventObjArray, startTime) {
3939
$(".item.range.job.application-timeline-object").each(function() {
4040
var getJobId = function(baseElem) {
4141
var jobIdText = $($(baseElem).find(".application-timeline-content")[0]).text();
42-
var jobId = "#job-" + jobIdText.match("\\(Job (\\d+)\\)")[1];
42+
var jobId = jobIdText.match("\\(Job (\\d+)\\)")[1];
4343
return jobId;
44-
}
44+
};
4545

4646
$(this).click(function() {
47-
window.location.href = getJobId(this);
47+
window.location.href = "job/?id=" + getJobId(this);
4848
});
4949

5050
$(this).hover(
5151
function() {
52-
$(getJobId(this)).addClass("corresponding-item-hover");
52+
$("#job-" + getJobId(this)).addClass("corresponding-item-hover");
5353
},
5454
function() {
55-
$(getJobId(this)).removeClass("corresponding-item-hover");
55+
$("#job-" + getJobId(this)).removeClass("corresponding-item-hover");
5656
}
5757
);
5858
});
59+
60+
$("span.expand-application-timeline").click(function() {
61+
$("#application-timeline").toggleClass('collapsed');
62+
63+
// Switch the class of the arrow from open to closed.
64+
$(this).find('.expand-application-timeline-arrow').toggleClass('arrow-open');
65+
$(this).find('.expand-application-timeline-arrow').toggleClass('arrow-closed');
66+
});
5967
}
6068

6169
function drawJobTimeline(groupArray, eventObjArray, startTime) {
@@ -80,26 +88,36 @@ function drawJobTimeline(groupArray, eventObjArray, startTime) {
8088
setupZoomable("#job-timeline-zoom-lock", jobTimeline);
8189

8290
$(".item.range.stage.job-timeline-object").each(function() {
83-
84-
var getStageId = function(baseElem) {
91+
var getStageIdAndAttempt = function(baseElem) {
8592
var stageIdText = $($(baseElem).find(".job-timeline-content")[0]).text();
86-
var stageId = "#stage-" + stageIdText.match("\\(Stage (\\d+\\.\\d+)\\)")[1].replace(".", "-");
87-
return stageId;
88-
}
93+
var stageIdAndAttempt = stageIdText.match("\\(Stage (\\d+\\.\\d+)\\)")[1].split(".");
94+
return stageIdAndAttempt;
95+
};
8996

9097
$(this).click(function() {
91-
window.location.href = getStageId(this);
98+
var idAndAttempt = getStageIdAndAttempt(this);
99+
var id = idAndAttempt[0];
100+
var attempt = idAndAttempt[1];
101+
window.location.href = "../../stages/stage/?id=" + id + "&attempt=" + attempt;
92102
});
93103

94104
$(this).hover(
95105
function() {
96-
$(getStageId(this)).addClass("corresponding-item-hover");
106+
$("#stage-" + getStageId(this)).addClass("corresponding-item-hover");
97107
},
98108
function() {
99-
$(getStageId(this)).removeClass("corresponding-item-hover");
109+
$("#stage-" + getStageId(this)).removeClass("corresponding-item-hover");
100110
}
101111
);
102112
});
113+
114+
$("span.expand-job-timeline").click(function() {
115+
$("#job-timeline").toggleClass('collapsed');
116+
117+
// Switch the class of the arrow from open to closed.
118+
$(this).find('.expand-job-timeline-arrow').toggleClass('arrow-open');
119+
$(this).find('.expand-job-timeline-arrow').toggleClass('arrow-closed');
120+
});
103121
}
104122

105123
function setupZoomable(id, timeline) {

core/src/main/scala/org/apache/spark/ui/exec/ExecutorsTab.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ class ExecutorsListener(storageStatusListener: StorageStatusListener) extends Sp
6565
executorIdToData(eid) = ExecutorUIData(executorAdded.time)
6666
}
6767

68-
override def onExecutorRemoved(executorRemoved: SparkListenerExecutorRemoved): Unit = synchronized {
68+
override def onExecutorRemoved(
69+
executorRemoved: SparkListenerExecutorRemoved): Unit = synchronized {
6970
val eid = executorRemoved.executorId
7071
val uiData = executorIdToData(eid)
7172
uiData.finishTime = Some(executorRemoved.time)

core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,26 @@ import org.apache.spark.JobExecutionStatus
3030
/** Page showing list of all ongoing and recently finished jobs */
3131
private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
3232
private val JOBS_LEGEND =
33-
<div class="legend-area"><svg width="200px" height="85px">
33+
<div class="legend-area"><svg width="150px" height="85px">
3434
<rect x="5px" y="5px" width="20px" height="15px"
3535
rx="2px" ry="2px" stroke="#97B0F8" fill="#D5DDF6"></rect>
36-
<text x="35px" y="17px">Succeeded Job</text>
37-
<rect x="5px" y="35px" width="20px" height="15px"
36+
<text x="35px" y="17px">Succeeded</text>
37+
<rect x="5px" y="30px" width="20px" height="15px"
3838
rx="2px" ry="2px" stroke="#97B0F8" fill="#FF5475"></rect>
39-
<text x="35px" y="47px">Failed Job</text>
40-
<rect x="5px" y="65px" width="20px" height="15px"
39+
<text x="35px" y="42px">Failed</text>
40+
<rect x="5px" y="55px" width="20px" height="15px"
4141
rx="2px" ry="2px" stroke="#97B0F8" fill="#FDFFCA"></rect>
42-
<text x="35px" y="77px">Running Job</text>
42+
<text x="35px" y="67px">Running</text>
4343
</svg></div>.toString.filter(_ != '\n')
4444

4545
private val EXECUTORS_LEGEND =
46-
<div class="legend-area"><svg width="200px" height="55px">
46+
<div class="legend-area"><svg width="150px" height="55px">
4747
<rect x="5px" y="5px" width="20px" height="15px"
4848
rx="2px" ry="2px" stroke="#97B0F8" fill="#D5DDF6"></rect>
49-
<text x="35px" y="17px">Executor Added</text>
50-
<rect x="5px" y="35px" width="20px" height="15px"
49+
<text x="35px" y="17px">Added</text>
50+
<rect x="5px" y="30px" width="20px" height="15px"
5151
rx="2px" ry="2px" stroke="#97B0F8" fill="#EBCA59"></rect>
52-
<text x="35px" y="47px">Executor Removed</text>
52+
<text x="35px" y="42px">Removed</text>
5353
</svg></div>.toString.filter(_ != '\n')
5454

5555
private def getLastStageNameAndDescription(job: JobUIData): (String, String) = {
@@ -170,7 +170,11 @@ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
170170
val eventArrayAsStr =
171171
(jobEventJsonAsStrSeq ++ executorEventJsonAsStrSeq).mkString("[", ",", "]")
172172

173-
<div id="application-timeline">
173+
<span class="expand-application-timeline">
174+
<span class="expand-application-timeline-arrow arrow-closed"></span>
175+
<strong>Event Timeline</strong>
176+
</span> ++
177+
<div id="application-timeline" class="collapsed">
174178
<div class="control-panel">
175179
<div id="application-timeline-zoom-lock">
176180
<input type="checkbox" checked="checked"></input>
@@ -303,8 +307,7 @@ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
303307

304308
var content = summary
305309
val executorListener = parent.executorListener
306-
content ++= <h4>Event Timeline</h4> ++
307-
makeTimeline(activeJobs ++ completedJobs ++ failedJobs,
310+
content ++= makeTimeline(activeJobs ++ completedJobs ++ failedJobs,
308311
executorListener.executorIdToData, startTime)
309312

310313
if (shouldShowActiveJobs) {

core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,26 @@ import org.apache.spark.ui.jobs.UIData.ExecutorUIData
3232
/** Page showing statistics and stage list for a given job */
3333
private[ui] class JobPage(parent: JobsTab) extends WebUIPage("job") {
3434
private val STAGES_LEGEND =
35-
<div class="legend-area"><svg width="200px" height="85px">
35+
<div class="legend-area"><svg width="150px" height="85px">
3636
<rect x="5px" y="5px" width="20px" height="15px"
3737
rx="2px" ry="2px" stroke="#97B0F8" fill="#D5DDF6"></rect>
38-
<text x="35px" y="17px">Completed Stage </text>
39-
<rect x="5px" y="35px" width="20px" height="15px"
38+
<text x="35px" y="17px">Completed</text>
39+
<rect x="5px" y="30px" width="20px" height="15px"
4040
rx="2px" ry="2px" stroke="#97B0F8" fill="#FF5475"></rect>
41-
<text x="35px" y="47px">Failed Stage</text>
42-
<rect x="5px" y="65px" width="20px" height="15px"
41+
<text x="35px" y="42px">Failed</text>
42+
<rect x="5px" y="55px" width="20px" height="15px"
4343
rx="2px" ry="2px" stroke="#97B0F8" fill="#FDFFCA"></rect>
44-
<text x="35px" y="77px">Active Stage</text>
44+
<text x="35px" y="67px">Active</text>
4545
</svg></div>.toString.filter(_ != '\n')
4646

4747
private val EXECUTORS_LEGEND =
48-
<div class="legend-area"><svg width="200px" height="55px">
48+
<div class="legend-area"><svg width="150px" height="55px">
4949
<rect x="5px" y="5px" width="20px" height="15px"
5050
rx="2px" ry="2px" stroke="#97B0F8" fill="#D5DDF6"></rect>
5151
<text x="35px" y="17px">Executor Added</text>
52-
<rect x="5px" y="35px" width="20px" height="15px"
52+
<rect x="5px" y="30px" width="20px" height="15px"
5353
rx="2px" ry="2px" stroke="#97B0F8" fill="#EBCA59"></rect>
54-
<text x="35px" y="47px">Executor Removed</text>
54+
<text x="35px" y="42px">Executor Removed</text>
5555
</svg></div>.toString.filter(_ != '\n')
5656

5757
private def makeStageEvent(stageInfos: Seq[StageInfo]): Seq[String] = {
@@ -150,7 +150,11 @@ private[ui] class JobPage(parent: JobsTab) extends WebUIPage("job") {
150150
val eventArrayAsStr =
151151
(stageEventJsonAsStrSeq ++ executorsJsonAsStrSeq).mkString("[", ",", "]")
152152

153-
<div id="job-timeline">
153+
<span class="expand-job-timeline">
154+
<span class="expand-job-timeline-arrow arrow-closed"></span>
155+
<strong>Event Timeline</strong>
156+
</span> ++
157+
<div id="job-timeline" class="collapsed">
154158
<div class="control-panel">
155159
<div id="job-timeline-zoom-lock">
156160
<input type="checkbox" checked="checked"></input>
@@ -291,8 +295,7 @@ private[ui] class JobPage(parent: JobsTab) extends WebUIPage("job") {
291295
var content = summary
292296
val jobStartTime = jobData.submissionTime.get
293297
val executorListener = parent.executorListener
294-
content ++= <h4>Event Timeline</h4> ++
295-
makeTimeline(activeStages ++ completedStages ++ failedStages,
298+
content ++= makeTimeline(activeStages ++ completedStages ++ failedStages,
296299
executorListener.executorIdToData, jobStartTime)
297300

298301
if (shouldShowActiveStages) {

0 commit comments

Comments
 (0)