-
Notifications
You must be signed in to change notification settings - Fork 28.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SPARK-23121][core] Fix for ui becoming unaccessible for long running streaming apps #20330
Conversation
@guoxiaolongzte could you please check if this change fixes the issue you have observed? |
cc @jiangxb1987, @srowen, @vanzin |
val (_, lastStageDescription) = lastStageNameAndDescription(store, job) | ||
val displayJobDescription = | ||
if (lastStageDescription.isEmpty) { | ||
job.name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using job.name instead of "" to behave more like the pre-2.3 version:
https://github.com/smurakozi/spark/blob/772e4648d95bda3353723337723543c741ea8476/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala#L70
Jenkins add to whitelist |
Test build #86389 has finished for PR 20330 at commit
|
.getOrElse("") | ||
val (_, lastStageDescription) = lastStageNameAndDescription(store, job) | ||
val displayJobDescription = | ||
if (lastStageDescription.isEmpty) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I generally prefer the opposite check.
if (data is good)
do something with data
else
fallback to something else
|
||
val formattedJobDescription = | ||
UIUtils.makeDescription(lastStageDescription, basePath, plainText = false) | ||
val jobDescription = UIUtils.makeDescription(lastStageDescription, basePath, plainText = false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to check for empty description here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lastStageDescription
may be empty, but it will not cause problems, makeDescription
will handle it properly, just like in the version before lastStageAttempt was used:
val jobDescription = UIUtils.makeDescription(jobData.description.getOrElse(""),
basePath, plainText = false)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, but don't you want the same behavior as above here (falling back to the job name)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved this logic to lastStageNameAndDescription
, so it's uniform.
val operationGraphContent = store.asOption(store.operationGraphForJob(jobId)) match { | ||
case Some(operationGraph) => UIUtils.showDagVizForJob(jobId, operationGraph) | ||
case None => | ||
<div id="no-info"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation is off.
@@ -18,7 +18,7 @@ | |||
package org.apache.spark.ui.jobs | |||
|
|||
import java.net.URLEncoder | |||
import java.util.Date | |||
import java.util.{Collections, Date} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New import is unused?
@@ -31,6 +31,7 @@ import org.apache.spark.SparkConf | |||
import org.apache.spark.internal.config._ | |||
import org.apache.spark.scheduler.TaskLocality | |||
import org.apache.spark.status._ | |||
import org.apache.spark.status.api.v1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just use JobData
since it's already imported?
Test build #4063 has finished for PR 20330 at commit
|
Test build #86399 has finished for PR 20330 at commit
|
store.asOption(store.lastStageAttempt(job.stageIds.max)) match { | ||
case Some(lastStageAttempt) => | ||
(lastStageAttempt.name, lastStageAttempt.description.getOrElse(job.name)) | ||
case None => ("", "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before, you were doing if (lastStageDescription.isEmpty) job.name else blah
at the call site.
Now, when the last stage is not in the store, the call site is getting an empty string as the description, instead of using the job name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would probably be simpler:
val stage = store.asOption(...)
(stage.map(_.name).getOrElse(""), stage.map(_.description.getOrElse(job.name)))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks for catching.
You could also add 'Closes #20287' to the PR description to close the other PR for the same bug automatically. |
Test build #86404 has finished for PR 20330 at commit
|
Test build #86417 has finished for PR 20330 at commit
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I check the other calls of lastStageAttempt
and all looks OK.
Merging to master / 2.3. |
… streaming apps ## What changes were proposed in this pull request? The allJobs and the job pages attempt to use stage attempt and DAG visualization from the store, but for long running jobs they are not guaranteed to be retained, leading to exceptions when these pages are rendered. To fix it `store.lastStageAttempt(stageId)` and `store.operationGraphForJob(jobId)` are wrapped in `store.asOption` and default values are used if the info is missing. ## How was this patch tested? Manual testing of the UI, also using the test command reported in SPARK-23121: ./bin/spark-submit --class org.apache.spark.examples.streaming.HdfsWordCount ./examples/jars/spark-examples_2.11-2.4.0-SNAPSHOT.jar /spark Closes #20287 Author: Sandor Murakozi <[email protected]> Closes #20330 from smurakozi/SPARK-23121. (cherry picked from commit 446948a) Signed-off-by: Marcelo Vanzin <[email protected]>
Thanks for your help @vanzin, @gengliangwang, @jiangxb1987 |
What changes were proposed in this pull request?
The allJobs and the job pages attempt to use stage attempt and DAG visualization from the store, but for long running jobs they are not guaranteed to be retained, leading to exceptions when these pages are rendered.
To fix it
store.lastStageAttempt(stageId)
andstore.operationGraphForJob(jobId)
are wrapped instore.asOption
and default values are used if the info is missing.How was this patch tested?
Manual testing of the UI, also using the test command reported in SPARK-23121:
./bin/spark-submit --class org.apache.spark.examples.streaming.HdfsWordCount ./examples/jars/spark-examples_2.11-2.4.0-SNAPSHOT.jar /spark
Closes #20287