alluxio-master-2.x/stress/common/src/main/java/alluxio/stress/rpc/RpcTaskSummary.java
/*
 * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
 * (the "License"). You may not use this work except in compliance with the License, which is
 * available at www.apache.org/licenses/LICENSE-2.0
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied, as more fully set forth in the License.
 *
 * See the NOTICE file distributed with this work for information regarding copyright ownership.
 */

package alluxio.stress.rpc;

import alluxio.stress.BaseParameters;
import alluxio.stress.GraphGenerator;
import alluxio.stress.Summary;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.google.common.math.Quantiles;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/**
 * This object is used to summarize the RPC stress test results.
 */
public class RpcTaskSummary implements Summary {
  private List<RpcTaskResult.Point> mPoints;
  private List<String> mErrors;
  private BaseParameters mBaseParameters;
  private RpcBenchParameters mParameters;
  public long mCount;
  public long mTotalDurationMs;
  public double mAvgDurationMs;
  public double mPercentile5th;
  public double mPercentile25th;
  public double mMedian;
  public double mPercentile75th;
  public double mPercentile95th;

  /**
   * Used for deserialization.
   * */
  @JsonCreator
  public RpcTaskSummary() {}

  /**
   * Creates a summary from a task result.
   * @param r task result
   */
  public RpcTaskSummary(RpcTaskResult r) {
    mParameters = r.getParameters();
    mBaseParameters = r.getBaseParameters();
    mErrors = r.getErrors();
    mPoints = r.getPoints();
    mCount = mPoints.size();
    calculate();
  }

  private void calculate() {
    if (mPoints.isEmpty()) {
      return;
    }
    for (RpcTaskResult.Point p : mPoints) {
      mTotalDurationMs += p.mDurationMs;
    }
    mAvgDurationMs = (mCount == 0) ? 0.0 : mTotalDurationMs / ((double) mCount);
    Map<Integer, Double> percentiles = getPercentiles(5, 25, 50, 75, 95);
    mPercentile5th = percentiles.get(5);
    mPercentile25th = percentiles.get(25);
    mMedian = percentiles.get(50);
    mPercentile75th = percentiles.get(75);
    mPercentile95th = percentiles.get(95);
  }

  @Override
  public GraphGenerator graphGenerator() {
    return null;
  }

  @Override
  public String toString() {
    if (mPoints.isEmpty()) {
      return String.format("RpcTaskSummary:%nNo data points%nErrors: %s%n", mErrors);
    }
    return String.format("RpcTaskSummary: Data points: %d, Errors: %d%n"
        + "Total: %.3e, Average: %.3e, Median: %.3e%n"
        + "5 Percentile: %.3e%n25 Percentile: %.3e%n75 Percentile: %.3e%n95 Percentile: %.3e%n",
        mPoints.size(), mErrors.size(), (double) mTotalDurationMs, mAvgDurationMs, mMedian,
        mPercentile5th, mPercentile25th, mPercentile75th, mPercentile95th);
  }

  /**
   * Gets percentiles of the results at different indices.
   * @param indices the indices of the percentiles, e.g. 50th or 75th
   * @return a map of indices to percentiles
   */
  public Map<Integer, Double> getPercentiles(int... indices) {
    indices = Arrays.stream(indices)
        .map((index) -> Math.max(0, Math.min(100, index)))
        .toArray();
    return Quantiles
        .percentiles()
        .indexes(indices)
        .compute(mPoints.stream().map((p) -> p.mDurationMs).collect(Collectors.toList()));
  }

  /**
   * @return the points recorded
   */
  public List<RpcTaskResult.Point> getPoints() {
    return mPoints;
  }

  /**
   * @param points the data points
   */
  public void setPoints(List<RpcTaskResult.Point> points) {
    mPoints = points;
  }

  /**
   * @return the errors recorded
   */
  public List<String> getErrors() {
    return mErrors;
  }

  /**
   * @param errors the errors
   */
  public void setErrors(List<String> errors) {
    mErrors = errors;
  }

  /**
   * @return the {@link BaseParameters}
   */
  public BaseParameters getBaseParameters() {
    return mBaseParameters;
  }

  /**
   * @param baseParameters the {@link BaseParameters}
   */
  public void setBaseParameters(BaseParameters baseParameters) {
    mBaseParameters = baseParameters;
  }

  /**
   * @return the task specific {@link RpcBenchParameters}
   */
  @Nullable
  public RpcBenchParameters getParameters() {
    return mParameters;
  }

  /**
   * @param parameters the {@link RpcBenchParameters}
   */
  public void setParameters(RpcBenchParameters parameters) {
    mParameters = parameters;
  }
}
