-
Notifications
You must be signed in to change notification settings - Fork 29.1k
[SPARK-31081][UI][SQL] Make the display of stageId/stageAttemptId/taskId of sql metrics configurable in UI #27849
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -135,6 +135,14 @@ object StaticSQLConf { | |
| .intConf | ||
| .createWithDefault(1000) | ||
|
|
||
| val DISPLAY_TASK_ID_FOR_MAX_METRIC = | ||
| buildStaticConf("spark.sql.ui.displayTaskInfoForMaxMetric") | ||
| .doc("If turn on, Spark will display stageId-stageAttemptId-taskId of the max metrics to " + | ||
| "tell where the max value comes from. It's useful to help debug job quicker.") | ||
| .version("3.0.0") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Ngone51 . cc @rxin since he is the release manager of 3.0.0 (also cc @gatorsmile ).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a UI issue to me. The SQL web UI is really hard to read now with the stage id stuff. Ideally, we should revisit #26843 and think of a better way to improve readability. But no one has proposed an idea yet. This PR disables the stage id stuff, which seems like a good compromise for 3.0: we keep the UI unchanged, but for people who really need the stage id info, they can still enable it.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 for making this 3.0. The UI changes in #26843 can be confusing to users after 3.0 release. |
||
| .booleanConf | ||
| .createWithDefault(false) | ||
|
|
||
| val BROADCAST_EXCHANGE_MAX_THREAD_THRESHOLD = | ||
| buildStaticConf("spark.sql.broadcastExchange.maxThreadThreshold") | ||
| .internal() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,9 +22,10 @@ import java.util.{Arrays, Locale} | |
|
|
||
| import scala.concurrent.duration._ | ||
|
|
||
| import org.apache.spark.SparkContext | ||
| import org.apache.spark.{SparkConf, SparkContext} | ||
| import org.apache.spark.scheduler.AccumulableInfo | ||
| import org.apache.spark.sql.execution.ui.SparkListenerDriverAccumUpdates | ||
| import org.apache.spark.sql.internal.StaticSQLConf | ||
| import org.apache.spark.util.{AccumulatorContext, AccumulatorV2, Utils} | ||
|
|
||
|
|
||
|
|
@@ -116,8 +117,8 @@ object SQLMetrics { | |
| // data size total (min, med, max): | ||
| // 100GB (100MB, 1GB, 10GB) | ||
| val acc = new SQLMetric(SIZE_METRIC, -1) | ||
| acc.register(sc, name = Some(s"$name total (min, med, max (stageId (attemptId): taskId))"), | ||
| countFailedValues = false) | ||
| acc.register(sc, name = Some(s"$name total (min, med, ${attachTaskId("max", sc.conf)})"), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new indentation looks incorrect at this line?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also noted that, thanks. |
||
| countFailedValues = false) | ||
| acc | ||
| } | ||
|
|
||
|
|
@@ -126,16 +127,16 @@ object SQLMetrics { | |
| // duration(min, med, max): | ||
| // 5s (800ms, 1s, 2s) | ||
| val acc = new SQLMetric(TIMING_METRIC, -1) | ||
| acc.register(sc, name = Some(s"$name total (min, med, max (stageId (attemptId): taskId))"), | ||
| acc.register(sc, name = Some(s"$name total (min, med, ${attachTaskId("max", sc.conf)})"), | ||
| countFailedValues = false) | ||
| acc | ||
| } | ||
|
|
||
| def createNanoTimingMetric(sc: SparkContext, name: String): SQLMetric = { | ||
| // Same with createTimingMetric, just normalize the unit of time to millisecond. | ||
| val acc = new SQLMetric(NS_TIMING_METRIC, -1) | ||
| acc.register(sc, name = Some(s"$name total (min, med, max (stageId (attemptId): taskId))"), | ||
| countFailedValues = false) | ||
| acc.register(sc, name = Some(s"$name total (min, med, ${attachTaskId("max", sc.conf)})"), | ||
| countFailedValues = false) | ||
| acc | ||
| } | ||
|
|
||
|
|
@@ -150,7 +151,7 @@ object SQLMetrics { | |
| // probe avg (min, med, max): | ||
| // (1.2, 2.2, 6.3) | ||
| val acc = new SQLMetric(AVERAGE_METRIC) | ||
| acc.register(sc, name = Some(s"$name (min, med, max (stageId (attemptId): taskId))"), | ||
| acc.register(sc, name = Some(s"$name (min, med, ${attachTaskId("max", sc.conf)})"), | ||
| countFailedValues = false) | ||
| acc | ||
| } | ||
|
|
@@ -168,13 +169,7 @@ object SQLMetrics { | |
| * A function that defines how we aggregate the final accumulator results among all tasks, | ||
| * and represent it in string for a SQL physical operator. | ||
| */ | ||
| def stringValue(metricsType: String, values: Array[Long], maxMetrics: Array[Long]): String = { | ||
| // stringMetric = "(driver)" OR (stage $stageId (attempt $attemptId): task $taskId)) | ||
| val stringMetric = if (maxMetrics.isEmpty) { | ||
| "(driver)" | ||
| } else { | ||
| s"(stage ${maxMetrics(1)} (attempt ${maxMetrics(2)}): task ${maxMetrics(3)})" | ||
| } | ||
| def stringValue(metricsType: String, values: Array[Long], taskId: String = ""): String = { | ||
| if (metricsType == SUM_METRIC) { | ||
| val numberFormat = NumberFormat.getIntegerInstance(Locale.US) | ||
| numberFormat.format(values.sum) | ||
|
|
@@ -187,7 +182,7 @@ object SQLMetrics { | |
| } else { | ||
| Arrays.sort(validValues) | ||
| Seq(toNumberFormat(validValues(0)), toNumberFormat(validValues(validValues.length / 2)), | ||
| s"${toNumberFormat(validValues(validValues.length - 1))} $stringMetric") | ||
| s"${toNumberFormat(validValues(validValues.length - 1))}$taskId") | ||
| } | ||
| metric | ||
| } | ||
|
|
@@ -212,7 +207,7 @@ object SQLMetrics { | |
| Arrays.sort(validValues) | ||
| Seq(strFormat(validValues.sum), strFormat(validValues(0)), | ||
| strFormat(validValues(validValues.length / 2)), | ||
| s"${strFormat(validValues(validValues.length - 1))} $stringMetric") | ||
| s"${strFormat(validValues(validValues.length - 1))}$taskId") | ||
| } | ||
| metric | ||
| } | ||
|
|
@@ -233,4 +228,13 @@ object SQLMetrics { | |
| SparkListenerDriverAccumUpdates(executionId.toLong, metrics.map(m => m.id -> m.value))) | ||
| } | ||
| } | ||
|
|
||
| private def attachTaskId(name: String, conf: SparkConf): String = { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are attaching
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I know. I'm thinking about a better name, while adding stageId/attemptId makes me feel too long for the method name.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| val display = conf.get(StaticSQLConf.DISPLAY_TASK_ID_FOR_MAX_METRIC) | ||
| if (display) { | ||
| s"$name (stageId (attemptId): taskId)" | ||
| } else { | ||
| 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.
shall we make it an internal conf?