Skip to content

Commit d78672a

Browse files
committed
Make the X axis use the same range
1 parent 881c907 commit d78672a

File tree

2 files changed

+68
-47
lines changed

2 files changed

+68
-47
lines changed

core/src/main/resources/org/apache/spark/ui/static/streaming-page.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
*/
1717

1818

19+
var globalMinX = 0;
20+
var globalMaxX = 0;
21+
var binCount = 10;
22+
1923
// An invisible div to show details of a point in the graph
2024
var graphTooltip = d3.select("body").append("div")
2125
.style("position", "absolute")
@@ -137,14 +141,14 @@ function drawDistribution(id, values, minY, maxY, unitY) {
137141
var height = 150 - margin.top - margin.bottom;
138142

139143
//var binCount = values.length > 100 ? 100 : values.length;
140-
var binCount = 10;
141144
var formatBinValue = d3.format(",.2f");
142145

143146
var y = d3.scale.linear().domain([minY, maxY]).range([height, 0]);
144147
var data = d3.layout.histogram().range([minY, maxY]).bins(binCount)(values);
145148

146149
var x = d3.scale.linear()
147-
.domain([0, d3.max(data, function(d) { return d.y; })])
150+
.domain([globalMinX, globalMaxX])
151+
//.domain([0, d3.max(data, function(d) { return d.y; })])
148152
.range([0, width]);
149153

150154
var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5);
@@ -197,3 +201,9 @@ function drawDistribution(id, values, minY, maxY, unitY) {
197201
hideGraphTooltip();
198202
});
199203
}
204+
205+
function prepareDistribution(values, minY, maxY) {
206+
var data = d3.layout.histogram().range([minY, maxY]).bins(binCount)(values);
207+
var maxBarSize = d3.max(data, function(d) { return d.y; });
208+
globalMaxX = maxBarSize > globalMaxX? maxBarSize : globalMaxX;
209+
}

streaming/src/main/scala/org/apache/spark/streaming/ui/StreamingPage.scala

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,14 @@ import org.apache.spark.util.Distribution
3737
private[ui] case class TimelineUIData(divId: String, data: Seq[(Long, _)], minX: Long, maxX: Long,
3838
minY: Long, maxY: Long, unitY: String) {
3939

40-
def toHtmlAndJs: (Seq[Node], String) = {
40+
def toHtml(jsCollector: JsCollector): Seq[Node] = {
4141
val jsForData = data.map { case (x, y) =>
4242
s"""{"x": $x, "y": $y}"""
4343
}.mkString("[", ",", "]")
44-
45-
(<div id={divId}></div>,
44+
jsCollector.addStatement(
4645
s"drawTimeline('#$divId', $jsForData, $minX, $maxX, $minY, $maxY, '$unitY');")
46+
47+
<div id={divId}></div>
4748
}
4849
}
4950

@@ -57,11 +58,12 @@ private[ui] case class TimelineUIData(divId: String, data: Seq[(Long, _)], minX:
5758
private[ui] case class DistributionUIData(
5859
divId: String, data: Seq[_], minY: Long, maxY: Long, unitY: String) {
5960

60-
def toHtmlAndJs: (Seq[Node], String) = {
61+
def toHtml(jsCollector: JsCollector): Seq[Node] = {
6162
val jsForData = data.mkString("[", ",", "]")
63+
jsCollector.addPreparedStatement(s"prepareDistribution($jsForData, $minY, $maxY);")
64+
jsCollector.addStatement(s"drawDistribution('#$divId', $jsForData, $minY, $maxY, '$unitY');")
6265

63-
(<div id={divId}></div>,
64-
s"drawDistribution('#$divId', $jsForData, $minY, $maxY, '$unitY');")
66+
<div id={divId}></div>
6567
}
6668
}
6769

@@ -149,7 +151,7 @@ private[ui] class StreamingPage(parent: StreamingTab)
149151
batchInfo.totalDelay.map(batchInfo.batchTime.milliseconds -> _)
150152
})
151153

152-
val jsCollector = ArrayBuffer[String]()
154+
val jsCollector = new JsCollector
153155

154156
// Use the max value of "schedulingDelay", "processingTime", and "totalDelay" to make the
155157
// Y axis ranges same.
@@ -179,17 +181,15 @@ private[ui] class StreamingPage(parent: StreamingTab)
179181
maxBatchTime,
180182
minEventRate,
181183
maxEventRate,
182-
"events/sec").toHtmlAndJs
183-
jsCollector += timelineDataForEventRateOfAllReceivers._2
184+
"events/sec").toHtml(jsCollector)
184185

185186
val distributionDataForEventRateOfAllReceivers =
186187
DistributionUIData(
187188
"all-receiver-events-distribution",
188189
eventRateForAllReceivers.data.map(_._2),
189190
minEventRate,
190191
maxEventRate,
191-
"events/sec").toHtmlAndJs
192-
jsCollector += distributionDataForEventRateOfAllReceivers._2
192+
"events/sec").toHtml(jsCollector)
193193

194194
val timelineDataForSchedulingDelay =
195195
TimelineUIData(
@@ -199,17 +199,15 @@ private[ui] class StreamingPage(parent: StreamingTab)
199199
maxBatchTime,
200200
minTime,
201201
maxTime,
202-
"ms").toHtmlAndJs
203-
jsCollector += timelineDataForSchedulingDelay._2
202+
"ms").toHtml(jsCollector)
204203

205204
val distributionDataForSchedulingDelay =
206205
DistributionUIData(
207206
"scheduling-delay-distribution",
208207
schedulingDelay.data.map(_._2),
209208
minTime,
210209
maxTime,
211-
"ms").toHtmlAndJs
212-
jsCollector += distributionDataForSchedulingDelay._2
210+
"ms").toHtml(jsCollector)
213211

214212
val timelineDataForProcessingTime =
215213
TimelineUIData(
@@ -219,17 +217,15 @@ private[ui] class StreamingPage(parent: StreamingTab)
219217
maxBatchTime,
220218
minTime,
221219
maxTime,
222-
"ms").toHtmlAndJs
223-
jsCollector += timelineDataForProcessingTime._2
220+
"ms").toHtml(jsCollector)
224221

225222
val distributionDataForProcessingTime =
226223
DistributionUIData(
227224
"processing-time-distribution",
228225
processingTime.data.map(_._2),
229226
minTime,
230227
maxTime,
231-
"ms").toHtmlAndJs
232-
jsCollector += distributionDataForProcessingTime._2
228+
"ms").toHtml(jsCollector)
233229

234230
val timelineDataForTotalDelay =
235231
TimelineUIData(
@@ -239,17 +235,15 @@ private[ui] class StreamingPage(parent: StreamingTab)
239235
maxBatchTime,
240236
minTime,
241237
maxTime,
242-
"ms").toHtmlAndJs
243-
jsCollector += timelineDataForTotalDelay._2
238+
"ms").toHtml(jsCollector)
244239

245240
val distributionDataForTotalDelay =
246241
DistributionUIData(
247242
"total-delay-distribution",
248243
totalDelay.data.map(_._2),
249244
minTime,
250245
maxTime,
251-
"ms").toHtmlAndJs
252-
jsCollector += distributionDataForTotalDelay._2
246+
"ms").toHtml(jsCollector)
253247

254248
val table =
255249
// scalastyle:off
@@ -266,8 +260,8 @@ private[ui] class StreamingPage(parent: StreamingTab)
266260
</div>
267261
<div>Avg: {eventRateForAllReceivers.avg.map(_.formatted("%.2f")).getOrElse(emptyCell)} events/sec</div>
268262
</td>
269-
<td>{timelineDataForEventRateOfAllReceivers._1}</td>
270-
<td>{distributionDataForEventRateOfAllReceivers._1}</td>
263+
<td>{timelineDataForEventRateOfAllReceivers}</td>
264+
<td>{distributionDataForEventRateOfAllReceivers}</td>
271265
</tr>
272266
<tr id="inputs-table" style="display: none;" >
273267
<td colspan="3">
@@ -279,39 +273,34 @@ private[ui] class StreamingPage(parent: StreamingTab)
279273
<div><strong>Scheduling Delay</strong></div>
280274
<div>Avg: {formatDurationOption(schedulingDelay.avg)}</div>
281275
</td>
282-
<td>{timelineDataForSchedulingDelay._1}</td>
283-
<td>{distributionDataForSchedulingDelay._1}</td>
276+
<td>{timelineDataForSchedulingDelay}</td>
277+
<td>{distributionDataForSchedulingDelay}</td>
284278
</tr>
285279
<tr>
286280
<td style="vertical-align: middle;">
287281
<div><strong>Processing Time</strong></div>
288282
<div>Avg: {formatDurationOption(processingTime.avg)}</div>
289283
</td>
290-
<td>{timelineDataForProcessingTime._1}</td>
291-
<td>{distributionDataForProcessingTime._1}</td>
284+
<td>{timelineDataForProcessingTime}</td>
285+
<td>{distributionDataForProcessingTime}</td>
292286
</tr>
293287
<tr>
294288
<td style="vertical-align: middle;">
295289
<div><strong>Total Delay</strong></div>
296290
<div>Avg: {formatDurationOption(totalDelay.avg)}</div>
297291
</td>
298-
<td>{timelineDataForTotalDelay._1}</td>
299-
<td>{distributionDataForTotalDelay._1}</td>
292+
<td>{timelineDataForTotalDelay}</td>
293+
<td>{distributionDataForTotalDelay}</td>
300294
</tr>
301295
</tbody>
302296
</table>
303297
// scalastyle:on
304298

305-
val js =
306-
s"""
307-
|$$(document).ready(function(){
308-
| ${jsCollector.mkString("\n")}
309-
|});""".stripMargin
310-
table ++ <script>{Unparsed(js)}</script>
299+
table ++ jsCollector.toHtml
311300
}
312301

313302
private def generateInputReceiversTable(
314-
jsCollector: ArrayBuffer[String],
303+
jsCollector: JsCollector,
315304
minX: Long,
316305
maxX: Long,
317306
minY: Long,
@@ -337,7 +326,7 @@ private[ui] class StreamingPage(parent: StreamingTab)
337326
}
338327

339328
private def generateInputReceiverRow(
340-
jsCollector: ArrayBuffer[String],
329+
jsCollector: JsCollector,
341330
receiverId: Int,
342331
distribution: Option[Distribution],
343332
minX: Long,
@@ -367,17 +356,15 @@ private[ui] class StreamingPage(parent: StreamingTab)
367356
maxX,
368357
minY,
369358
maxY,
370-
"events/sec").toHtmlAndJs
371-
jsCollector += timelineForEventRate._2
359+
"events/sec").toHtml(jsCollector)
372360

373361
val distributionForEventsRate =
374362
DistributionUIData(
375363
s"receiver-$receiverId-events-distribution",
376364
receivedRecords.map(_._2),
377365
minY,
378366
maxY,
379-
"events/sec").toHtmlAndJs
380-
jsCollector += distributionForEventsRate._2
367+
"events/sec").toHtml(jsCollector)
381368

382369
// scalastyle:off
383370
<tr>
@@ -394,9 +381,9 @@ private[ui] class StreamingPage(parent: StreamingTab)
394381
</tr>
395382
<tr>
396383
<td colspan="3">
397-
{timelineForEventRate._1}
384+
{timelineForEventRate}
398385
</td>
399-
<td>{distributionForEventsRate._1}</td>
386+
<td>{distributionForEventsRate}</td>
400387
</tr>
401388
// scalastyle:on
402389
}
@@ -435,3 +422,27 @@ private object StreamingPage {
435422
val BLACK_DOWN_TRIANGLE_HTML = "&#9660;"
436423
}
437424

425+
private[ui] class JsCollector {
426+
private val preparedStatements = ArrayBuffer[String]()
427+
private val statements = ArrayBuffer[String]()
428+
429+
def addPreparedStatement(js: String): Unit = {
430+
preparedStatements += js
431+
}
432+
433+
def addStatement(js: String): Unit = {
434+
statements += js
435+
}
436+
437+
def toHtml: Seq[Node] = {
438+
val js =
439+
s"""
440+
|$$(document).ready(function(){
441+
| ${preparedStatements.mkString("\n")}
442+
| ${statements.mkString("\n")}
443+
|});""".stripMargin
444+
445+
<script>{Unparsed(js)}</script>
446+
}
447+
}
448+

0 commit comments

Comments
 (0)