public void recordMetrics() {
    if (metrics != null) {
      if (metricsRecorded.compareAndSet(false, true)) {
        metrics.operationRate.mark();
        metrics.operationCount.inc();
        metrics.nioRequestProcessingTimeInMs.update(nioMetricsTracker.requestProcessingTimeInMs.get());
        metrics.nioResponseProcessingTimeInMs.update(nioMetricsTracker.responseProcessingTimeInMs.get());
        metrics.nioRoundTripTimeInMs.update(nioMetricsTracker.roundTripTimeInMs);
        metrics.nioTimeToFirstByteInMs.update(nioMetricsTracker.timeToFirstByteInMs);

        metrics.scRequestProcessingTimeInMs.update(scalingMetricsTracker.requestProcessingTimeInMs.get());
        metrics.scRequestProcessingWaitTimeInMs.update(scalingMetricsTracker.requestProcessingWaitTimeInMs.get());
        metrics.scResponseProcessingTimeInMs.update(scalingMetricsTracker.responseProcessingTimeInMs.get());
        metrics.scResponseProcessingWaitTimeInMs.update(scalingMetricsTracker.responseProcessingWaitTimeInMs.get());
        metrics.scRoundTripTimeInMs.update(scalingMetricsTracker.roundTripTimeInMs);
        if (failed) {
          metrics.operationError.inc();
        }
        if (containerMetrics != null) {
          containerMetrics.recordMetrics(nioMetricsTracker.roundTripTimeInMs, responseStatus, bytesTransferred);
        }
        if (satisfied) {
          metrics.satisfiedRequestCount.inc();
        } else {
          metrics.unsatisfiedRequestCount.inc();
        }

        // Only add throughput metrics when the request is successful and bytes were actually transfered over the wire.
        // Recording throughput during failure could mean we incorrectly report throughput as something higher than normal since
        // the round trip time is likely to be shorter.
        // We also want to make sure we aren't polluting our metrics with a bunch of 0 throughput values.
        if (!failed && bytesTransferred > 0) {
          metrics.throughput.update(RestUtils.calculateThroughput(bytesTransferred, nioMetricsTracker.roundTripTimeInMs));
        }
      }
    } else {
      throw new IllegalStateException("Could not record metrics because there is no metrics tracker");
    }
  }
Records the metrics.
</p>
This method is expected to called when the {@link RestRequest}, that this instance of {@link RestRequestMetricsTracker} is
attached to, finishes.
ambry-api/src/main/java/com/github/ambry/rest/RestRequestMetricsTracker.java