@@ -37,13 +37,14 @@ import org.apache.spark.util.Distribution
37
37
private [ui] case class TimelineUIData (divId : String , data : Seq [(Long , _)], minX : Long , maxX : Long ,
38
38
minY : Long , maxY : Long , unitY : String ) {
39
39
40
- def toHtmlAndJs : ( Seq [Node ], String ) = {
40
+ def toHtml ( jsCollector : JsCollector ) : Seq [Node ] = {
41
41
val jsForData = data.map { case (x, y) =>
42
42
s """ {"x": $x, "y": $y} """
43
43
}.mkString(" [" , " ," , " ]" )
44
-
45
- (<div id ={divId}></div >,
44
+ jsCollector.addStatement(
46
45
s " drawTimeline('# $divId', $jsForData, $minX, $maxX, $minY, $maxY, ' $unitY'); " )
46
+
47
+ <div id ={divId}></div >
47
48
}
48
49
}
49
50
@@ -57,11 +58,12 @@ private[ui] case class TimelineUIData(divId: String, data: Seq[(Long, _)], minX:
57
58
private [ui] case class DistributionUIData (
58
59
divId : String , data : Seq [_], minY : Long , maxY : Long , unitY : String ) {
59
60
60
- def toHtmlAndJs : ( Seq [Node ], String ) = {
61
+ def toHtml ( jsCollector : JsCollector ) : Seq [Node ] = {
61
62
val jsForData = data.mkString(" [" , " ," , " ]" )
63
+ jsCollector.addPreparedStatement(s " prepareDistribution( $jsForData, $minY, $maxY); " )
64
+ jsCollector.addStatement(s " drawDistribution('# $divId', $jsForData, $minY, $maxY, ' $unitY'); " )
62
65
63
- (<div id ={divId}></div >,
64
- s " drawDistribution('# $divId', $jsForData, $minY, $maxY, ' $unitY'); " )
66
+ <div id ={divId}></div >
65
67
}
66
68
}
67
69
@@ -149,7 +151,7 @@ private[ui] class StreamingPage(parent: StreamingTab)
149
151
batchInfo.totalDelay.map(batchInfo.batchTime.milliseconds -> _)
150
152
})
151
153
152
- val jsCollector = ArrayBuffer [ String ]()
154
+ val jsCollector = new JsCollector
153
155
154
156
// Use the max value of "schedulingDelay", "processingTime", and "totalDelay" to make the
155
157
// Y axis ranges same.
@@ -179,17 +181,15 @@ private[ui] class StreamingPage(parent: StreamingTab)
179
181
maxBatchTime,
180
182
minEventRate,
181
183
maxEventRate,
182
- " events/sec" ).toHtmlAndJs
183
- jsCollector += timelineDataForEventRateOfAllReceivers._2
184
+ " events/sec" ).toHtml(jsCollector)
184
185
185
186
val distributionDataForEventRateOfAllReceivers =
186
187
DistributionUIData (
187
188
" all-receiver-events-distribution" ,
188
189
eventRateForAllReceivers.data.map(_._2),
189
190
minEventRate,
190
191
maxEventRate,
191
- " events/sec" ).toHtmlAndJs
192
- jsCollector += distributionDataForEventRateOfAllReceivers._2
192
+ " events/sec" ).toHtml(jsCollector)
193
193
194
194
val timelineDataForSchedulingDelay =
195
195
TimelineUIData (
@@ -199,17 +199,15 @@ private[ui] class StreamingPage(parent: StreamingTab)
199
199
maxBatchTime,
200
200
minTime,
201
201
maxTime,
202
- " ms" ).toHtmlAndJs
203
- jsCollector += timelineDataForSchedulingDelay._2
202
+ " ms" ).toHtml(jsCollector)
204
203
205
204
val distributionDataForSchedulingDelay =
206
205
DistributionUIData (
207
206
" scheduling-delay-distribution" ,
208
207
schedulingDelay.data.map(_._2),
209
208
minTime,
210
209
maxTime,
211
- " ms" ).toHtmlAndJs
212
- jsCollector += distributionDataForSchedulingDelay._2
210
+ " ms" ).toHtml(jsCollector)
213
211
214
212
val timelineDataForProcessingTime =
215
213
TimelineUIData (
@@ -219,17 +217,15 @@ private[ui] class StreamingPage(parent: StreamingTab)
219
217
maxBatchTime,
220
218
minTime,
221
219
maxTime,
222
- " ms" ).toHtmlAndJs
223
- jsCollector += timelineDataForProcessingTime._2
220
+ " ms" ).toHtml(jsCollector)
224
221
225
222
val distributionDataForProcessingTime =
226
223
DistributionUIData (
227
224
" processing-time-distribution" ,
228
225
processingTime.data.map(_._2),
229
226
minTime,
230
227
maxTime,
231
- " ms" ).toHtmlAndJs
232
- jsCollector += distributionDataForProcessingTime._2
228
+ " ms" ).toHtml(jsCollector)
233
229
234
230
val timelineDataForTotalDelay =
235
231
TimelineUIData (
@@ -239,17 +235,15 @@ private[ui] class StreamingPage(parent: StreamingTab)
239
235
maxBatchTime,
240
236
minTime,
241
237
maxTime,
242
- " ms" ).toHtmlAndJs
243
- jsCollector += timelineDataForTotalDelay._2
238
+ " ms" ).toHtml(jsCollector)
244
239
245
240
val distributionDataForTotalDelay =
246
241
DistributionUIData (
247
242
" total-delay-distribution" ,
248
243
totalDelay.data.map(_._2),
249
244
minTime,
250
245
maxTime,
251
- " ms" ).toHtmlAndJs
252
- jsCollector += distributionDataForTotalDelay._2
246
+ " ms" ).toHtml(jsCollector)
253
247
254
248
val table =
255
249
// scalastyle:off
@@ -266,8 +260,8 @@ private[ui] class StreamingPage(parent: StreamingTab)
266
260
</div >
267
261
<div >Avg : {eventRateForAllReceivers.avg.map(_.formatted(" %.2f" )).getOrElse(emptyCell)} events/ sec</div >
268
262
</td >
269
- <td >{timelineDataForEventRateOfAllReceivers._1 }</td >
270
- <td >{distributionDataForEventRateOfAllReceivers._1 }</td >
263
+ <td >{timelineDataForEventRateOfAllReceivers}</td >
264
+ <td >{distributionDataForEventRateOfAllReceivers}</td >
271
265
</tr >
272
266
<tr id =" inputs-table" style =" display: none;" >
273
267
<td colspan =" 3" >
@@ -279,39 +273,34 @@ private[ui] class StreamingPage(parent: StreamingTab)
279
273
<div ><strong >Scheduling Delay </strong ></div >
280
274
<div >Avg : {formatDurationOption(schedulingDelay.avg)}</div >
281
275
</td >
282
- <td >{timelineDataForSchedulingDelay._1 }</td >
283
- <td >{distributionDataForSchedulingDelay._1 }</td >
276
+ <td >{timelineDataForSchedulingDelay}</td >
277
+ <td >{distributionDataForSchedulingDelay}</td >
284
278
</tr >
285
279
<tr >
286
280
<td style =" vertical-align: middle;" >
287
281
<div ><strong >Processing Time </strong ></div >
288
282
<div >Avg : {formatDurationOption(processingTime.avg)}</div >
289
283
</td >
290
- <td >{timelineDataForProcessingTime._1 }</td >
291
- <td >{distributionDataForProcessingTime._1 }</td >
284
+ <td >{timelineDataForProcessingTime}</td >
285
+ <td >{distributionDataForProcessingTime}</td >
292
286
</tr >
293
287
<tr >
294
288
<td style =" vertical-align: middle;" >
295
289
<div ><strong >Total Delay </strong ></div >
296
290
<div >Avg : {formatDurationOption(totalDelay.avg)}</div >
297
291
</td >
298
- <td >{timelineDataForTotalDelay._1 }</td >
299
- <td >{distributionDataForTotalDelay._1 }</td >
292
+ <td >{timelineDataForTotalDelay}</td >
293
+ <td >{distributionDataForTotalDelay}</td >
300
294
</tr >
301
295
</tbody >
302
296
</table >
303
297
// scalastyle:on
304
298
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
311
300
}
312
301
313
302
private def generateInputReceiversTable (
314
- jsCollector : ArrayBuffer [ String ] ,
303
+ jsCollector : JsCollector ,
315
304
minX : Long ,
316
305
maxX : Long ,
317
306
minY : Long ,
@@ -337,7 +326,7 @@ private[ui] class StreamingPage(parent: StreamingTab)
337
326
}
338
327
339
328
private def generateInputReceiverRow (
340
- jsCollector : ArrayBuffer [ String ] ,
329
+ jsCollector : JsCollector ,
341
330
receiverId : Int ,
342
331
distribution : Option [Distribution ],
343
332
minX : Long ,
@@ -367,17 +356,15 @@ private[ui] class StreamingPage(parent: StreamingTab)
367
356
maxX,
368
357
minY,
369
358
maxY,
370
- " events/sec" ).toHtmlAndJs
371
- jsCollector += timelineForEventRate._2
359
+ " events/sec" ).toHtml(jsCollector)
372
360
373
361
val distributionForEventsRate =
374
362
DistributionUIData (
375
363
s " receiver- $receiverId-events-distribution " ,
376
364
receivedRecords.map(_._2),
377
365
minY,
378
366
maxY,
379
- " events/sec" ).toHtmlAndJs
380
- jsCollector += distributionForEventsRate._2
367
+ " events/sec" ).toHtml(jsCollector)
381
368
382
369
// scalastyle:off
383
370
<tr >
@@ -394,9 +381,9 @@ private[ui] class StreamingPage(parent: StreamingTab)
394
381
</tr >
395
382
<tr >
396
383
<td colspan =" 3" >
397
- {timelineForEventRate._1 }
384
+ {timelineForEventRate}
398
385
</td >
399
- <td >{distributionForEventsRate._1 }</td >
386
+ <td >{distributionForEventsRate}</td >
400
387
</tr >
401
388
// scalastyle:on
402
389
}
@@ -435,3 +422,27 @@ private object StreamingPage {
435
422
val BLACK_DOWN_TRIANGLE_HTML = " ▼"
436
423
}
437
424
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