@@ -29,8 +29,6 @@ import org.apache.spark.JobExecutionStatus
2929
3030/** Page showing list of all ongoing and recently finished jobs */
3131private [ui] class AllJobsPage (parent : JobsTab ) extends WebUIPage (" " ) {
32- private val startTime : Option [Long ] = parent.sc.map(_.startTime)
33- private val listener = parent.listener
3432 private val JOBS_LEGEND =
3533 <div class =" legend-area" ><svg width =" 200px" height =" 85px" >
3634 < rect x= " 5px" y= " 5px" width= " 20px" height= " 15px"
@@ -44,41 +42,44 @@ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
4442 <text x =" 35px" y =" 77px" >Running Job </text >
4543 </svg ></div >.toString.filter(_ != '\n ' )
4644
45+ private val EXECUTORS_LEGEND =
46+ <div class =" legend-area" ><svg width =" 200px" height =" 55px" >
47+ < rect x= " 5px" y= " 5px" width= " 20px" height= " 15px"
48+ 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"
51+ rx= " 2px" ry= " 2px" stroke= " #97B0F8" fill= " #EBCA59" ></ rect>
52+ <text x =" 35px" y =" 47px" >Executor Removed </text >
53+ </svg ></div >.toString.filter(_ != '\n ' )
54+
4755 private def getlastStageDescription (job : JobUIData ) = {
4856 val lastStageInfo = Option (job.stageIds)
4957 .filter(_.nonEmpty)
50- .flatMap { ids => listener.stageIdToInfo.get(ids.max)}
58+ .flatMap { ids => parent. listener.stageIdToInfo.get(ids.max)}
5159 val lastStageData = lastStageInfo.flatMap { s =>
52- listener.stageIdToData.get((s.stageId, s.attemptId))
60+ parent. listener.stageIdToData.get((s.stageId, s.attemptId))
5361 }
5462 lastStageData.flatMap(_.description).getOrElse(" " )
5563 }
5664
57- private def makeTimeline (jobs : Seq [JobUIData ], executors : Seq [ExecutorUIData ]): Seq [Node ] = {
58-
59- def makeJobEvent (jobUIDatas : Seq [JobUIData ]): Seq [String ] = {
60- jobUIDatas.flatMap { jobUIData =>
61- val jobId = jobUIData.jobId
62- val status = jobUIData.status
63- val jobDescription = getlastStageDescription(jobUIData)
64- val submissionTimeOpt = jobUIData.submissionTime
65- val completionTimeOpt = jobUIData.completionTime
66-
67- if (status == JobExecutionStatus .UNKNOWN || submissionTimeOpt.isEmpty ||
68- completionTimeOpt.isEmpty && status != JobExecutionStatus .RUNNING ) {
69- None
70- }
71-
72- val submissionTime = submissionTimeOpt.get
73- val completionTime = completionTimeOpt.getOrElse(System .currentTimeMillis())
74- val classNameByStatus = status match {
75- case JobExecutionStatus .SUCCEEDED => " succeeded"
76- case JobExecutionStatus .FAILED => " failed"
77- case JobExecutionStatus .RUNNING => " running"
78- }
65+ private def makeJobEvent (jobUIDatas : Seq [JobUIData ]): Seq [String ] = {
66+ jobUIDatas.filter { jobUIData =>
67+ jobUIData.status != JobExecutionStatus .UNKNOWN && jobUIData.submissionTime.isDefined
68+ }.map { jobUIData =>
69+ val jobId = jobUIData.jobId
70+ val status = jobUIData.status
71+ val jobDescription = getlastStageDescription(jobUIData)
72+ val submissionTime = jobUIData.submissionTime.get
73+ val completionTimeOpt = jobUIData.completionTime
74+ val completionTime = completionTimeOpt.getOrElse(System .currentTimeMillis())
75+ val classNameByStatus = status match {
76+ case JobExecutionStatus .SUCCEEDED => " succeeded"
77+ case JobExecutionStatus .FAILED => " failed"
78+ case JobExecutionStatus .RUNNING => " running"
79+ }
7980
80- val jobEventJsonAsStr =
81- s """
81+ val jobEventJsonAsStr =
82+ s """
8283 |{
8384 | 'className': 'job application-timeline-object ${classNameByStatus}',
8485 | 'group': 'jobs',
@@ -89,25 +90,25 @@ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
8990 | 'title': ' ${jobDescription} (Job ${jobId}) \\ nStatus: ${status}\\ n' +
9091 | 'Submission Time: ${UIUtils .formatDate(new Date (submissionTime))}' +
9192 | ' ${
92- if (status != JobExecutionStatus .RUNNING ) {
93- s """ \\ nCompletion Time: ${UIUtils .formatDate(new Date (completionTime))}"""
94- } else {
95- " "
96- }
97- }'
93+ if (status != JobExecutionStatus .RUNNING ) {
94+ s """ \\ nCompletion Time: ${UIUtils .formatDate(new Date (completionTime))}"""
95+ } else {
96+ " "
97+ }
98+ }'
9899 |}
99100 """ .stripMargin
100- Some (jobEventJsonAsStr)
101- }
101+ jobEventJsonAsStr
102102 }
103+ }
103104
104- def makeExecutorEvent (executorUIDatas : Seq [ExecutorUIData ]): Seq [String ] = {
105- val events = ListBuffer [String ]()
106- executorUIDatas.foreach { event =>
105+ private def makeExecutorEvent (executorUIDatas : Seq [ExecutorUIData ]): Seq [String ] = {
106+ val events = ListBuffer [String ]()
107+ executorUIDatas.foreach { event =>
107108
108- if (event.startTime.isDefined) {
109- val addedEvent =
110- s """
109+ if (event.startTime.isDefined) {
110+ val addedEvent =
111+ s """
111112 |{
112113 | 'className': 'executor added',
113114 | 'group': 'executors',
@@ -116,12 +117,12 @@ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
116117 | 'title': 'Added at ${UIUtils .formatDate(new Date (event.startTime.get))}'
117118 |}
118119 """ .stripMargin
119- events += addedEvent
120- }
120+ events += addedEvent
121+ }
121122
122- if (event.finishTime.isDefined) {
123- val removedEvent =
124- s """
123+ if (event.finishTime.isDefined) {
124+ val removedEvent =
125+ s """
125126 |{
126127 | 'className': 'executor removed',
127128 | 'group': 'executors',
@@ -137,31 +138,26 @@ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
137138 }'
138139 |}
139140 """ .stripMargin
140- events += removedEvent
141- }
141+ events += removedEvent
142142 }
143- events.toSeq
144143 }
144+ events.toSeq
145+ }
146+
147+ private def makeTimeline (
148+ jobs : Seq [JobUIData ],
149+ executors : Seq [ExecutorUIData ],
150+ startTime : Long ): Seq [Node ] = {
145151
146152 val jobEventJsonAsStrSeq = makeJobEvent(jobs)
147153 val executorEventJsonAsStrSeq = makeExecutorEvent(executors)
148154
149- val executorsLegend =
150- <div class =" legend-area" ><svg width =" 200px" height =" 55px" >
151- < rect x= " 5px" y= " 5px" width= " 20px" height= " 15px"
152- rx= " 2px" ry= " 2px" stroke= " #97B0F8" fill= " #D5DDF6" ></ rect>
153- <text x =" 35px" y =" 17px" >Executor Added </text >
154- < rect x= " 5px" y= " 35px" width= " 20px" height= " 15px"
155- rx= " 2px" ry= " 2px" stroke= " #97B0F8" fill= " #EBCA59" ></ rect>
156- <text x =" 35px" y =" 47px" >Executor Removed </text >
157- </svg ></div >.toString.filter(_ != '\n ' )
158-
159155 val groupJsonArrayAsStr =
160156 s """
161157 |[
162158 | {
163159 | 'id': 'executors',
164- | 'content': '<div>Executors</div> ${executorsLegend }',
160+ | 'content': '<div>Executors</div> ${EXECUTORS_LEGEND }',
165161 | },
166162 | {
167163 | 'id': 'jobs',
@@ -182,7 +178,7 @@ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
182178 <div id =" application-timeline" ></div > ++
183179 <script type =" text/javascript" >
184180 {Unparsed (s " drawApplicationTimeline( ${groupJsonArrayAsStr}, " +
185- s " ${eventArrayAsStr}, ${startTime.getOrElse( - 1L ) }); " )}
181+ s " ${eventArrayAsStr}, ${startTime}); " )}
186182 </script >
187183 }
188184
@@ -201,10 +197,7 @@ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
201197 def makeRow (job : JobUIData ): Seq [Node ] = {
202198 val lastStageInfo = Option (job.stageIds)
203199 .filter(_.nonEmpty)
204- .flatMap { ids => listener.stageIdToInfo.get(ids.max) }
205- val lastStageData = lastStageInfo.flatMap { s =>
206- listener.stageIdToData.get((s.stageId, s.attemptId))
207- }
200+ .flatMap { ids => parent.listener.stageIdToInfo.get(ids.max) }
208201
209202 val lastStageName = lastStageInfo.map(_.name).getOrElse(" (Unknown Stage Name)" )
210203 val lastStageDescription = getlastStageDescription(job)
@@ -252,7 +245,9 @@ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
252245 }
253246
254247 def render (request : HttpServletRequest ): Seq [Node ] = {
248+ val listener = parent.listener
255249 listener.synchronized {
250+ val startTime = listener.startTime
256251 val activeJobs = listener.activeJobs.values.toSeq
257252 val completedJobs = listener.completedJobs.reverse.toSeq
258253 val failedJobs = listener.failedJobs.reverse.toSeq
@@ -271,11 +266,11 @@ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
271266 val summary : NodeSeq =
272267 <div >
273268 <ul class =" unstyled" >
274- {if (startTime .isDefined) {
269+ {if (parent.sc .isDefined) {
275270 // Total duration is not meaningful unless the UI is live
276271 <li >
277272 <strong >Total Duration : </strong >
278- {UIUtils .formatDuration(System .currentTimeMillis() - startTime.get )}
273+ {UIUtils .formatDuration(System .currentTimeMillis() - startTime)}
279274 </li >
280275 }}
281276 <li >
@@ -310,9 +305,8 @@ private[ui] class AllJobsPage(parent: JobsTab) extends WebUIPage("") {
310305 </div >
311306
312307 var content = summary
313- val appStartTime =
314308 content ++= <h4 >Events on Application Timeline </h4 > ++
315- makeTimeline(activeJobs ++ completedJobs ++ failedJobs, listener.executors)
309+ makeTimeline(activeJobs ++ completedJobs ++ failedJobs, listener.executors, startTime )
316310
317311 if (shouldShowActiveJobs) {
318312 content ++= <h4 id =" active" >Active Jobs ({activeJobs.size})</h4 > ++
0 commit comments