From 8aaa1b8f70583ef48a3de3f3f55325a7283d585d Mon Sep 17 00:00:00 2001 From: Kent Yao Date: Mon, 25 Sep 2023 14:11:15 +0800 Subject: [PATCH] [SPARK-44895][CORE] Add 'daemon', 'priority' for ThreadStackTrace --- .../scala/org/apache/spark/status/api/v1/api.scala | 10 ++++++---- .../main/scala/org/apache/spark/util/Utils.scala | 4 +++- .../org/apache/spark/ui/UISeleniumSuite.scala | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/core/src/main/scala/org/apache/spark/status/api/v1/api.scala b/core/src/main/scala/org/apache/spark/status/api/v1/api.scala index 3e4e2f17a77e1..7a0c69e294883 100644 --- a/core/src/main/scala/org/apache/spark/status/api/v1/api.scala +++ b/core/src/main/scala/org/apache/spark/status/api/v1/api.scala @@ -540,19 +540,21 @@ case class ThreadStackTrace( lockName: Option[String], lockOwnerName: Option[String], suspended: Boolean, - inNative: Boolean) { + inNative: Boolean, + isDaemon: Boolean, + priority: Int) { /** * Returns a string representation of this thread stack trace * w.r.t java.lang.management.ThreadInfo(JDK 8)'s toString. * - * TODO(SPARK-44895): Considering 'daemon', 'priority' from higher JDKs - * * TODO(SPARK-44896): Also considering adding information os_prio, cpu, elapsed, tid, nid, etc., * from the jstack tool */ override def toString: String = { - val sb = new StringBuilder(s""""$threadName" Id=$threadId $threadState""") + val daemon = if (isDaemon) " daemon" else "" + val sb = new StringBuilder( + s""""$threadName"$daemon prio=$priority Id=$threadId $threadState""") lockName.foreach(lock => sb.append(s" on $lock")) lockOwnerName.foreach { owner => sb.append(s"""owned by "$owner"""") diff --git a/core/src/main/scala/org/apache/spark/util/Utils.scala b/core/src/main/scala/org/apache/spark/util/Utils.scala index 149071ee1b608..dca189190ba65 100644 --- a/core/src/main/scala/org/apache/spark/util/Utils.scala +++ b/core/src/main/scala/org/apache/spark/util/Utils.scala @@ -2198,7 +2198,9 @@ private[spark] object Utils Option(threadInfo.getLockName), Option(threadInfo.getLockOwnerName), threadInfo.isSuspended, - threadInfo.isInNative) + threadInfo.isInNative, + threadInfo.isDaemon, + threadInfo.getPriority) } /** diff --git a/core/src/test/scala/org/apache/spark/ui/UISeleniumSuite.scala b/core/src/test/scala/org/apache/spark/ui/UISeleniumSuite.scala index dd9927d7ba17e..7e74cc9287f9a 100644 --- a/core/src/test/scala/org/apache/spark/ui/UISeleniumSuite.scala +++ b/core/src/test/scala/org/apache/spark/ui/UISeleniumSuite.scala @@ -885,6 +885,20 @@ class UISeleniumSuite extends SparkFunSuite with WebBrowser with Matchers { } } + test("SPARK-44895: Add 'daemon', 'priority' for ThreadStackTrace") { + withSpark(newSparkContext()) { sc => + val uiThreads = getJson(sc.ui.get, "executors/driver/threads") + .children + .filter(v => (v \ "threadName").extract[String].matches("SparkUI-\\d+")) + val priority = Thread.currentThread().getPriority + + uiThreads.foreach { v => + assert((v \ "isDaemon").extract[Boolean]) + assert((v \ "priority").extract[Int] === priority) + } + } + } + def goToUi(sc: SparkContext, path: String): Unit = { goToUi(sc.ui.get, path) }