Skip to content

Commit a63d9ed

Browse files
CodingCatAndrew Or
authored andcommitted
[SPARK-9516][UI] Improvement of Thread Dump Page
https://issues.apache.org/jira/browse/SPARK-9516 - [x] new look of Thread Dump Page - [x] click column title to sort - [x] grep - [x] search as you type squito JoshRosen It's ready for the review now Author: CodingCat <[email protected]> Closes #7910 from CodingCat/SPARK-9516.
1 parent c2de99a commit a63d9ed

File tree

4 files changed

+118
-43
lines changed

4 files changed

+118
-43
lines changed

core/src/main/resources/org/apache/spark/ui/static/sorttable.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ sorttable = {
169169
for (var i=0; i<table.tBodies[0].rows.length; i++) {
170170
text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]);
171171
if (text != '') {
172-
if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) {
172+
if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) {
173173
return sorttable.sort_numeric;
174174
}
175175
// check for a date: dd/mm/yyyy or dd/mm/yy
@@ -266,8 +266,8 @@ sorttable = {
266266
return aa-bb;
267267
},
268268
sort_alpha: function(a,b) {
269-
if (a[0]==b[0]) return 0;
270-
if (a[0]<b[0]) return -1;
269+
if (a[0].toLowerCase()==b[0].toLowerCase()) return 0;
270+
if (a[0].toLowerCase()<b[0].toLowerCase()) return -1;
271271
return 1;
272272
},
273273
sort_ddmm: function(a,b) {

core/src/main/resources/org/apache/spark/ui/static/table.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,75 @@ function stripeSummaryTable() {
3030
}
3131
});
3232
}
33+
34+
function toggleThreadStackTrace(threadId, forceAdd) {
35+
var stackTrace = $("#" + threadId + "_stacktrace")
36+
if (stackTrace.length == 0) {
37+
var stackTraceText = $('#' + threadId + "_td_stacktrace").html()
38+
var threadCell = $("#thread_" + threadId + "_tr")
39+
threadCell.after("<tr id=\"" + threadId +"_stacktrace\" class=\"accordion-body\"><td colspan=\"3\"><pre>" +
40+
stackTraceText + "</pre></td></tr>")
41+
} else {
42+
if (!forceAdd) {
43+
stackTrace.remove()
44+
}
45+
}
46+
}
47+
48+
function expandAllThreadStackTrace(toggleButton) {
49+
$('.accordion-heading').each(function() {
50+
//get thread ID
51+
if (!$(this).hasClass("hidden")) {
52+
var trId = $(this).attr('id').match(/thread_([0-9]+)_tr/m)[1]
53+
toggleThreadStackTrace(trId, true)
54+
}
55+
})
56+
if (toggleButton) {
57+
$('.expandbutton').toggleClass('hidden')
58+
}
59+
}
60+
61+
function collapseAllThreadStackTrace(toggleButton) {
62+
$('.accordion-body').each(function() {
63+
$(this).remove()
64+
})
65+
if (toggleButton) {
66+
$('.expandbutton').toggleClass('hidden');
67+
}
68+
}
69+
70+
71+
// inOrOut - true: over, false: out
72+
function onMouseOverAndOut(threadId) {
73+
$("#" + threadId + "_td_id").toggleClass("threaddump-td-mouseover");
74+
$("#" + threadId + "_td_name").toggleClass("threaddump-td-mouseover");
75+
$("#" + threadId + "_td_state").toggleClass("threaddump-td-mouseover");
76+
}
77+
78+
function onSearchStringChange() {
79+
var searchString = $('#search').val().toLowerCase();
80+
//remove the stacktrace
81+
collapseAllThreadStackTrace(false)
82+
if (searchString.length == 0) {
83+
$('tr').each(function() {
84+
$(this).removeClass('hidden')
85+
})
86+
} else {
87+
$('tr').each(function(){
88+
if($(this).attr('id') && $(this).attr('id').match(/thread_[0-9]+_tr/) ) {
89+
var children = $(this).children()
90+
var found = false
91+
for (i = 0; i < children.length; i++) {
92+
if (children.eq(i).text().toLowerCase().indexOf(searchString) >= 0) {
93+
found = true
94+
}
95+
}
96+
if (found) {
97+
$(this).removeClass('hidden')
98+
} else {
99+
$(this).addClass('hidden')
100+
}
101+
}
102+
});
103+
}
104+
}

core/src/main/resources/org/apache/spark/ui/static/webui.css

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,8 @@ a.expandbutton {
221221
cursor: pointer;
222222
}
223223

224-
.executor-thread {
225-
background: #E6E6E6;
226-
}
227-
228-
.non-executor-thread {
229-
background: #FAFAFA;
224+
.threaddump-td-mouseover {
225+
background-color: #49535a !important;
226+
color: white;
227+
cursor:pointer;
230228
}

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

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -60,44 +60,49 @@ private[ui] class ExecutorThreadDumpPage(parent: ExecutorsTab) extends WebUIPage
6060
}
6161
}
6262
}.map { thread =>
63-
val threadName = thread.threadName
64-
val className = "accordion-heading " + {
65-
if (threadName.contains("Executor task launch")) {
66-
"executor-thread"
67-
} else {
68-
"non-executor-thread"
69-
}
70-
}
71-
<div class="accordion-group">
72-
<div class={className} onclick="$(this).next().toggleClass('hidden')">
73-
<a class="accordion-toggle">
74-
Thread {thread.threadId}: {threadName} ({thread.threadState})
75-
</a>
76-
</div>
77-
<div class="accordion-body hidden">
78-
<div class="accordion-inner">
79-
<pre>{thread.stackTrace}</pre>
63+
val threadId = thread.threadId
64+
<tr id={s"thread_${threadId}_tr"} class="accordion-heading"
65+
onclick={s"toggleThreadStackTrace($threadId, false)"}
66+
onmouseover={s"onMouseOverAndOut($threadId)"}
67+
onmouseout={s"onMouseOverAndOut($threadId)"}>
68+
<td id={s"${threadId}_td_id"}>{threadId}</td>
69+
<td id={s"${threadId}_td_name"}>{thread.threadName}</td>
70+
<td id={s"${threadId}_td_state"}>{thread.threadState}</td>
71+
<td id={s"${threadId}_td_stacktrace"} class="hidden">{thread.stackTrace}</td>
72+
</tr>
73+
}
74+
75+
<div class="row-fluid">
76+
<p>Updated at {UIUtils.formatDate(time)}</p>
77+
{
78+
// scalastyle:off
79+
<p><a class="expandbutton" onClick="expandAllThreadStackTrace(true)">
80+
Expand All
81+
</a></p>
82+
<p><a class="expandbutton hidden" onClick="collapseAllThreadStackTrace(true)">
83+
Collapse All
84+
</a></p>
85+
<div class="form-inline">
86+
<div class="bs-example" data-example-id="simple-form-inline">
87+
<div class="form-group">
88+
<div class="input-group">
89+
Search: <input type="text" class="form-control" id="search" oninput="onSearchStringChange()"></input>
8090
</div>
8191
</div>
8292
</div>
93+
</div>
94+
<p></p>
95+
// scalastyle:on
8396
}
84-
85-
<div class="row-fluid">
86-
<p>Updated at {UIUtils.formatDate(time)}</p>
87-
{
88-
// scalastyle:off
89-
<p><a class="expandbutton"
90-
onClick="$('.accordion-body').removeClass('hidden'); $('.expandbutton').toggleClass('hidden')">
91-
Expand All
92-
</a></p>
93-
<p><a class="expandbutton hidden"
94-
onClick="$('.accordion-body').addClass('hidden'); $('.expandbutton').toggleClass('hidden')">
95-
Collapse All
96-
</a></p>
97-
// scalastyle:on
98-
}
99-
<div class="accordion">{dumpRows}</div>
100-
</div>
97+
<table class={UIUtils.TABLE_CLASS_STRIPED + " accordion-group" + " sortable"}>
98+
<thead>
99+
<th onClick="collapseAllThreadStackTrace(false)">Thread ID</th>
100+
<th onClick="collapseAllThreadStackTrace(false)">Thread Name</th>
101+
<th onClick="collapseAllThreadStackTrace(false)">Thread State</th>
102+
</thead>
103+
<tbody>{dumpRows}</tbody>
104+
</table>
105+
</div>
101106
}.getOrElse(Text("Error fetching thread dump"))
102107
UIUtils.headerSparkPage(s"Thread dump for executor $executorId", content, parent)
103108
}

0 commit comments

Comments
 (0)