@@ -22,13 +22,15 @@ import java.util.concurrent.atomic.AtomicInteger
22
22
23
23
import scala .collection .immutable .{HashSet , TreeSet }
24
24
import scala .collection .mutable .HashMap
25
+ import scala .collection .mutable
25
26
26
27
import com .google .common .collect .Interners
27
28
28
29
import org .apache .spark .JobExecutionStatus
29
30
import org .apache .spark .executor .{ExecutorMetrics , TaskMetrics }
30
31
import org .apache .spark .resource .ResourceInformation
31
32
import org .apache .spark .scheduler .{AccumulableInfo , StageInfo , TaskInfo }
33
+ import org .apache .spark .status .TaskIndexNames ._
32
34
import org .apache .spark .status .api .v1
33
35
import org .apache .spark .storage .{RDDInfo , StorageLevel }
34
36
import org .apache .spark .ui .SparkUI
@@ -184,6 +186,19 @@ private class LiveTask(
184
186
info.timeRunning(lastUpdateTime.getOrElse(System .currentTimeMillis()))
185
187
}
186
188
189
+ val hasMetrics = metrics.executorDeserializeTime >= 0
190
+ val handleZeros = mutable.HashSet [String ]()
191
+
192
+ /**
193
+ * For non successful tasks, store the metrics as negetive to avoid the calculation in the
194
+ * task summary. `toApi` method in TaskDataWrapper will make it actual value.
195
+ */
196
+ val taskMetrics : v1.TaskMetrics = if (hasMetrics && ! info.successful) {
197
+ makeNegative(metrics, handleZeros)
198
+ } else {
199
+ metrics
200
+ }
201
+
187
202
new TaskDataWrapper (
188
203
info.taskId,
189
204
info.index,
@@ -199,30 +214,32 @@ private class LiveTask(
199
214
newAccumulatorInfos(info.accumulables),
200
215
errorMessage,
201
216
202
- metrics.executorDeserializeTime,
203
- metrics.executorDeserializeCpuTime,
204
- metrics.executorRunTime,
205
- metrics.executorCpuTime,
206
- metrics.resultSize,
207
- metrics.jvmGcTime,
208
- metrics.resultSerializationTime,
209
- metrics.memoryBytesSpilled,
210
- metrics.diskBytesSpilled,
211
- metrics.peakExecutionMemory,
212
- metrics.inputMetrics.bytesRead,
213
- metrics.inputMetrics.recordsRead,
214
- metrics.outputMetrics.bytesWritten,
215
- metrics.outputMetrics.recordsWritten,
216
- metrics.shuffleReadMetrics.remoteBlocksFetched,
217
- metrics.shuffleReadMetrics.localBlocksFetched,
218
- metrics.shuffleReadMetrics.fetchWaitTime,
219
- metrics.shuffleReadMetrics.remoteBytesRead,
220
- metrics.shuffleReadMetrics.remoteBytesReadToDisk,
221
- metrics.shuffleReadMetrics.localBytesRead,
222
- metrics.shuffleReadMetrics.recordsRead,
223
- metrics.shuffleWriteMetrics.bytesWritten,
224
- metrics.shuffleWriteMetrics.writeTime,
225
- metrics.shuffleWriteMetrics.recordsWritten,
217
+ hasMetrics,
218
+ handleZeros,
219
+ taskMetrics.executorDeserializeTime,
220
+ taskMetrics.executorDeserializeCpuTime,
221
+ taskMetrics.executorRunTime,
222
+ taskMetrics.executorCpuTime,
223
+ taskMetrics.resultSize,
224
+ taskMetrics.jvmGcTime,
225
+ taskMetrics.resultSerializationTime,
226
+ taskMetrics.memoryBytesSpilled,
227
+ taskMetrics.diskBytesSpilled,
228
+ taskMetrics.peakExecutionMemory,
229
+ taskMetrics.inputMetrics.bytesRead,
230
+ taskMetrics.inputMetrics.recordsRead,
231
+ taskMetrics.outputMetrics.bytesWritten,
232
+ taskMetrics.outputMetrics.recordsWritten,
233
+ taskMetrics.shuffleReadMetrics.remoteBlocksFetched,
234
+ taskMetrics.shuffleReadMetrics.localBlocksFetched,
235
+ taskMetrics.shuffleReadMetrics.fetchWaitTime,
236
+ taskMetrics.shuffleReadMetrics.remoteBytesRead,
237
+ taskMetrics.shuffleReadMetrics.remoteBytesReadToDisk,
238
+ taskMetrics.shuffleReadMetrics.localBytesRead,
239
+ taskMetrics.shuffleReadMetrics.recordsRead,
240
+ taskMetrics.shuffleWriteMetrics.bytesWritten,
241
+ taskMetrics.shuffleWriteMetrics.writeTime,
242
+ taskMetrics.shuffleWriteMetrics.recordsWritten,
226
243
227
244
stageId,
228
245
stageAttemptId)
@@ -710,6 +727,50 @@ private object LiveEntityHelpers {
710
727
addMetrics(m1, m2, - 1 )
711
728
}
712
729
730
+ /**
731
+ * Convert all the metric values to negative as well as handle zero values.
732
+ * This method assumes that all the metric values are greater than or equal to zero
733
+ */
734
+ def makeNegative (
735
+ m : v1.TaskMetrics ,
736
+ handleZeros : mutable.HashSet [String ]): v1.TaskMetrics = {
737
+ // If the metric value is 0, then make -1 and update the metric index in handleZeros.
738
+ def updateMetricValue (metric : Long , index : String ): Long = {
739
+ if (metric == 0L ) {
740
+ handleZeros.add(index)
741
+ - 1L
742
+ } else {
743
+ metric * - 1L
744
+ }
745
+ }
746
+
747
+ createMetrics(
748
+ updateMetricValue(m.executorDeserializeTime, DESER_TIME ),
749
+ updateMetricValue(m.executorDeserializeCpuTime, DESER_CPU_TIME ),
750
+ updateMetricValue(m.executorRunTime, EXEC_RUN_TIME ),
751
+ updateMetricValue(m.executorCpuTime, EXEC_CPU_TIME ),
752
+ updateMetricValue(m.resultSize, RESULT_SIZE ),
753
+ updateMetricValue(m.jvmGcTime, GC_TIME ),
754
+ updateMetricValue(m.resultSerializationTime, SER_TIME ),
755
+ updateMetricValue(m.memoryBytesSpilled, MEM_SPILL ),
756
+ updateMetricValue(m.diskBytesSpilled, DISK_SPILL ),
757
+ updateMetricValue(m.peakExecutionMemory, PEAK_MEM ),
758
+ updateMetricValue(m.inputMetrics.bytesRead, INPUT_SIZE ),
759
+ updateMetricValue(m.inputMetrics.recordsRead, INPUT_RECORDS ),
760
+ updateMetricValue(m.outputMetrics.bytesWritten, OUTPUT_SIZE ),
761
+ updateMetricValue(m.outputMetrics.recordsWritten, OUTPUT_RECORDS ),
762
+ updateMetricValue(m.shuffleReadMetrics.remoteBlocksFetched, SHUFFLE_REMOTE_BLOCKS ),
763
+ updateMetricValue(m.shuffleReadMetrics.localBlocksFetched, SHUFFLE_LOCAL_BLOCKS ),
764
+ updateMetricValue(m.shuffleReadMetrics.fetchWaitTime, SHUFFLE_READ_TIME ),
765
+ updateMetricValue(m.shuffleReadMetrics.remoteBytesRead, SHUFFLE_REMOTE_READS ),
766
+ updateMetricValue(m.shuffleReadMetrics.remoteBytesReadToDisk, SHUFFLE_REMOTE_READS_TO_DISK ),
767
+ updateMetricValue(m.shuffleReadMetrics.localBytesRead, SHUFFLE_LOCAL_READ ),
768
+ updateMetricValue(m.shuffleReadMetrics.recordsRead, SHUFFLE_READ_RECORDS ),
769
+ updateMetricValue(m.shuffleWriteMetrics.bytesWritten, SHUFFLE_WRITE_SIZE ),
770
+ updateMetricValue(m.shuffleWriteMetrics.writeTime, SHUFFLE_WRITE_TIME ),
771
+ updateMetricValue(m.shuffleWriteMetrics.recordsWritten, SHUFFLE_WRITE_RECORDS ))
772
+ }
773
+
713
774
private def addMetrics (m1 : v1.TaskMetrics , m2 : v1.TaskMetrics , mult : Int ): v1.TaskMetrics = {
714
775
createMetrics(
715
776
m1.executorDeserializeTime + m2.executorDeserializeTime * mult,
0 commit comments