docs: public void addIOMetrics(AccessExecution attempt, @Nullable MetricFetcher fetcher, String jobID, String taskID) {
  		if (attempt.getState().isTerminal()) {
  			IOMetrics ioMetrics = attempt.getIOMetrics();
  			if (ioMetrics != null) { // execAttempt is already finished, use final metrics stored in ExecutionGraph
  				this.numBytesIn += ioMetrics.getNumBytesIn();
  				this.numBytesOut += ioMetrics.getNumBytesOut();
  				this.numRecordsIn += ioMetrics.getNumRecordsIn();
  				this.numRecordsOut += ioMetrics.getNumRecordsOut();
  			}
  		} else { // execAttempt is still running, use MetricQueryService instead
  			if (fetcher != null) {
  				fetcher.update();
  				MetricStore.ComponentMetricStore metrics = fetcher.getMetricStore()
  					.getSubtaskMetricStore(jobID, taskID, attempt.getParallelSubtaskIndex());
  				if (metrics != null) {
  					/**
  					 * We want to keep track of missing metrics to be able to make a difference between 0 as a value
  					 * and a missing value.
  					 * In case a metric is missing for a parallel instance of a task, we set the complete flag as
  					 * false.
  					 */
  					if (metrics.getMetric(MetricNames.IO_NUM_BYTES_IN) == null){
  						this.numBytesInComplete = false;
  					}
  					else {
  						this.numBytesIn += Long.valueOf(metrics.getMetric(MetricNames.IO_NUM_BYTES_IN));
  					}
  
  					if (metrics.getMetric(MetricNames.IO_NUM_BYTES_OUT) == null){
  						this.numBytesOutComplete = false;
  					}
  					else {
  						this.numBytesOut += Long.valueOf(metrics.getMetric(MetricNames.IO_NUM_BYTES_OUT));
  					}
  
  					if (metrics.getMetric(MetricNames.IO_NUM_RECORDS_IN) == null){
  						this.numRecordsInComplete = false;
  					}
  					else {
  						this.numRecordsIn += Long.valueOf(metrics.getMetric(MetricNames.IO_NUM_RECORDS_IN));
  					}
  
  					if (metrics.getMetric(MetricNames.IO_NUM_RECORDS_OUT) == null){
  						this.numRecordsOutComplete = false;
  					}
  					else {
  						this.numRecordsOut += Long.valueOf(metrics.getMetric(MetricNames.IO_NUM_RECORDS_OUT));
  					}
  				}
  				else {
  					this.numBytesInComplete = false;
  					this.numBytesOutComplete = false;
  					this.numRecordsInComplete = false;
  					this.numRecordsOutComplete = false;
  				}
  			}
  		}
  	}