@Override
  public ThrottlingRecommendation recommend(RestRequest restRequest) throws QuotaException {
    quotaMetrics.recommendRate.mark();
    if (quotaEnforcers.isEmpty()) {
      quotaMetrics.noQuotaRecommendationRate.mark();
      return null;
    }
    ThrottlingRecommendation throttlingRecommendation;
    Timer.Context timer = quotaMetrics.quotaRecommendationTime.time();
    try {
      List<QuotaRecommendation> quotaRecommendations = new ArrayList<>();
      for (QuotaEnforcer quotaEnforcer : quotaEnforcers) {
        try {
          quotaRecommendations.add(quotaEnforcer.recommend(restRequest));
        } catch (QuotaException quotaException) {
          LOGGER.warn("Could not get recommendation for quota {} due to exception: {}",
              quotaEnforcer.supportedQuotaNames(), quotaException.getMessage());
        }
      }
      if (quotaRecommendations.isEmpty()) {
        quotaMetrics.noRecommendationRate.mark();
      } else if (quotaRecommendations.size() < quotaEnforcers.size()) {
        quotaMetrics.partialQuotaRecommendationRate.mark();
      }
      throttlingRecommendation = quotaRecommendationMergePolicy.mergeEnforcementRecommendations(quotaRecommendations);
      if (throttlingRecommendation.shouldThrottle()) {
        quotaMetrics.quotaExceedRecommendationRate.mark();
      }
    } finally {
      timer.stop();
    }
    return throttlingRecommendation;
  }
{@inheritDoc}

If there are any {@link QuotaEnforcer#recommend} calls that throw exception, this implementation logs the exception,
and makes a best effort to gather as many recommendations as possible. Recommendations for some {@link QuotaName}s
will be missing in those cases.
ambry-quota/src/main/java/com/github/ambry/quota/AmbryQuotaManager.java