Skip to content

Commit a459f49

Browse files
committed
Add a dash line to processing time graphs
1 parent 8e4363c commit a459f49

File tree

4 files changed

+87
-14
lines changed

4 files changed

+87
-14
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
fill: gray;
3131
}
3232

33+
.tooltip-inner {
34+
max-width: 500px !important;
35+
}
36+
3337
.line {
3438
fill: none;
3539
stroke: #0088cc;
@@ -47,6 +51,10 @@
4751
fill: rgb(0, 194, 255);
4852
}
4953

54+
.stable-text text:hover {
55+
fill: #0088cc;
56+
}
57+
5058
.timeline {
5159
width: 500px;
5260
}

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

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function hideBootstrapTooltip(node) {
6363
* @param maxY the max value of Y axis
6464
* @param unitY the unit of Y axis
6565
*/
66-
function drawTimeline(id, data, minX, maxX, minY, maxY, unitY) {
66+
function drawTimeline(id, data, minX, maxX, minY, maxY, unitY, batchTime) {
6767
d3.select(d3.select(id).node().parentNode).style("padding", "8px 0 8px 8px").style("border-right", "0px solid white");
6868
var margin = {top: 20, right: 27, bottom: 30, left: timelineMarginLeft};
6969
var width = 500 - margin.left - margin.right;
@@ -101,6 +101,26 @@ function drawTimeline(id, data, minX, maxX, minY, maxY, unitY) {
101101
.attr("transform", "translate(0," + (-3) + ")")
102102
.text(unitY);
103103

104+
105+
if (batchTime) {
106+
var batchTimeline = d3.svg.line()
107+
.x(function(d) { return x(d.x); })
108+
.y(function(d) { return y(d.y); });
109+
110+
console.log(batchTime);
111+
var batchTimeData = [
112+
{x: minX, y: batchTime}, {x: maxX, y: batchTime}
113+
];
114+
console.log(batchTimeData);
115+
116+
svg.append("path")
117+
.datum(batchTimeData)
118+
.style("stroke-dasharray", ("6, 6"))
119+
.style("stroke", "lightblue")
120+
.attr("class", "line")
121+
.attr("d", batchTimeline);
122+
}
123+
104124
svg.append("path")
105125
.datum(data)
106126
.attr("class", "line")
@@ -136,6 +156,7 @@ function drawTimeline(id, data, minX, maxX, minY, maxY, unitY) {
136156
.attr("fill", "white")
137157
.attr("opacity", "0");
138158
});
159+
139160
}
140161

141162
/**
@@ -145,7 +166,7 @@ function drawTimeline(id, data, minX, maxX, minY, maxY, unitY) {
145166
* @param maxY the max value of Y axis
146167
* @param unitY the unit of Y axis
147168
*/
148-
function drawDistribution(id, values, minY, maxY, unitY) {
169+
function drawDistribution(id, values, minY, maxY, unitY, batchTime) {
149170
d3.select(d3.select(id).node().parentNode).style("padding", "8px 8px 8px 0").style("border-left", "0px solid white");
150171
var margin = {top: 20, right: 30, bottom: 30, left: 10};
151172
var width = 300 - margin.left - margin.right;
@@ -169,6 +190,25 @@ function drawDistribution(id, values, minY, maxY, unitY) {
169190
.append("g")
170191
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
171192

193+
if (batchTime) {
194+
var batchTimeline = d3.svg.line()
195+
.x(function(d) { return x(d.x); })
196+
.y(function(d) { return y(d.y); });
197+
198+
console.log(batchTime);
199+
var batchTimeData = [
200+
{x: distributionMinX, y: batchTime}, {x: distributionMaxX, y: batchTime}
201+
];
202+
console.log(batchTimeData);
203+
204+
svg.append("path")
205+
.datum(batchTimeData)
206+
.style("stroke-dasharray", ("6, 6"))
207+
.style("stroke", "lightblue")
208+
.attr("class", "line")
209+
.attr("d", batchTimeline);
210+
}
211+
172212
svg.append("g")
173213
.attr("class", "x axis")
174214
.attr("transform", "translate(0," + 0 + ")")
@@ -208,6 +248,22 @@ function drawDistribution(id, values, minY, maxY, unitY) {
208248
hideBootstrapTooltip(d3.select(this).node());
209249
//hideGraphTooltip();
210250
});
251+
252+
if (batchTime && batchTime <= maxY) {
253+
svg.append("text")
254+
.style("fill", "lightblue")
255+
.attr("class", "stable-text")
256+
.attr("text-anchor", "middle")
257+
.attr("transform", "translate(" + (x(distributionMaxX)-20) +"," + (y(batchTime) + 15) + ")")
258+
.text("stable")
259+
.on('mouseover', function(d) {
260+
var tip = "Processing Time <= Batch Interval (" + formatBinValue(batchTime) +" " + unitY +")";
261+
showBootstrapTooltip(d3.select(this).node(), tip);
262+
})
263+
.on('mouseout', function() {
264+
hideBootstrapTooltip(d3.select(this).node());
265+
});
266+
}
211267
}
212268

213269
function prepareTimeline(minY, maxY) {

core/src/main/scala/org/apache/spark/ui/UIUtils.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ private[spark] object UIUtils extends Logging {
4242
case TimeUnit.NANOSECONDS => "ns"
4343
case TimeUnit.MICROSECONDS => "us"
4444
case TimeUnit.MILLISECONDS => "ms"
45-
case TimeUnit.SECONDS => "s"
45+
case TimeUnit.SECONDS => "sec"
4646
case TimeUnit.MINUTES => "min"
47-
case TimeUnit.HOURS => "h"
48-
case TimeUnit.DAYS => "d"
47+
case TimeUnit.HOURS => "hrs"
48+
case TimeUnit.DAYS => "days"
4949
}
5050

5151
/**

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

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,20 @@ import org.apache.spark.util.Distribution
4040
* @param unitY the unit of Y axis
4141
*/
4242
private[ui] class TimelineUIData(divId: String, data: Seq[(Long, _)], minX: Long, maxX: Long,
43-
minY: Double, maxY: Double, unitY: String) {
43+
minY: Double, maxY: Double, unitY: String, batchTime: Option[Double] = None) {
4444

4545
def toHtml(jsCollector: JsCollector): Seq[Node] = {
4646
val jsForData = data.map { case (x, y) =>
4747
s"""{"x": $x, "y": $y}"""
4848
}.mkString("[", ",", "]")
4949
jsCollector.addPreparedStatement(s"prepareTimeline($minY, $maxY);")
50-
jsCollector.addStatement(
51-
s"drawTimeline('#$divId', $jsForData, $minX, $maxX, $minY, $maxY, '$unitY');")
52-
50+
if (batchTime.isDefined) {
51+
jsCollector.addStatement(
52+
s"drawTimeline('#$divId', $jsForData, $minX, $maxX, $minY, $maxY, '$unitY', ${batchTime.get});")
53+
} else {
54+
jsCollector.addStatement(
55+
s"drawTimeline('#$divId', $jsForData, $minX, $maxX, $minY, $maxY, '$unitY');")
56+
}
5357
<div id={divId}></div>
5458
}
5559
}
@@ -62,13 +66,16 @@ private[ui] class TimelineUIData(divId: String, data: Seq[(Long, _)], minX: Long
6266
* @param unitY the unit of Y axis
6367
*/
6468
private[ui] class DistributionUIData(
65-
divId: String, data: Seq[_], minY: Double, maxY: Double, unitY: String) {
69+
divId: String, data: Seq[_], minY: Double, maxY: Double, unitY: String, batchTime: Option[Double] = None) {
6670

6771
def toHtml(jsCollector: JsCollector): Seq[Node] = {
6872
val jsForData = data.mkString("[", ",", "]")
6973
jsCollector.addPreparedStatement(s"prepareDistribution($jsForData, $minY, $maxY);")
70-
jsCollector.addStatement(s"drawDistribution('#$divId', $jsForData, $minY, $maxY, '$unitY');")
71-
74+
if (batchTime.isDefined) {
75+
jsCollector.addStatement(s"drawDistribution('#$divId', $jsForData, $minY, $maxY, '$unitY', ${batchTime.get});")
76+
} else {
77+
jsCollector.addStatement(s"drawDistribution('#$divId', $jsForData, $minY, $maxY, '$unitY');")
78+
}
7279
<div id={divId}></div>
7380
}
7481
}
@@ -204,6 +211,8 @@ private[ui] class StreamingPage(parent: StreamingTab)
204211
|else {$$(this).html('$BLACK_RIGHT_TRIANGLE_HTML');status = false;}
205212
|window.history.pushState('', document.title, window.location.pathname + '?show-receivers-detail=' + status);""".stripMargin.replaceAll("\\n", "")
206213

214+
var batchTime = StreamingPage.convertToTimeUnit(listener.batchDuration, unit)
215+
207216
val timelineDataForEventRateOfAllReceivers =
208217
new TimelineUIData(
209218
"all-receiver-events-timeline",
@@ -248,15 +257,15 @@ private[ui] class StreamingPage(parent: StreamingTab)
248257
maxBatchTime,
249258
minTime,
250259
maxTime,
251-
formattedUnit).toHtml(jsCollector)
260+
formattedUnit, Some(batchTime)).toHtml(jsCollector)
252261

253262
val distributionDataForProcessingTime =
254263
new DistributionUIData(
255264
"processing-time-distribution",
256265
processingTime.distributionData(unit),
257266
minTime,
258267
maxTime,
259-
formattedUnit).toHtml(jsCollector)
268+
formattedUnit, Some(batchTime)).toHtml(jsCollector)
260269

261270
val timelineDataForTotalDelay =
262271
new TimelineUIData(

0 commit comments

Comments
 (0)