All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.airlift.stats.TimeDistribution Maven / Gradle / Ivy
package io.airlift.stats;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.errorprone.annotations.concurrent.GuardedBy;
import org.weakref.jmx.Managed;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Verify.verify;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.SECONDS;
public class TimeDistribution
{
private static final double[] SNAPSHOT_QUANTILES = new double[] {0.5, 0.75, 0.9, 0.95, 0.99};
private static final double[] PERCENTILES;
static {
PERCENTILES = new double[100];
for (int i = 0; i < 100; ++i) {
PERCENTILES[i] = (i / 100.0);
}
}
private final double alpha;
@GuardedBy("this")
private DecayTDigest digest;
@GuardedBy("this")
private final DecayCounter total;
private final TimeUnit unit;
public TimeDistribution()
{
this(SECONDS);
}
public TimeDistribution(TimeUnit unit)
{
this(0, unit);
}
public TimeDistribution(double alpha)
{
this(alpha, SECONDS);
}
public TimeDistribution(double alpha, TimeUnit unit)
{
requireNonNull(unit, "unit is null");
this.alpha = alpha;
digest = new DecayTDigest(TDigest.DEFAULT_COMPRESSION, alpha);
total = new DecayCounter(alpha);
this.unit = unit;
}
public synchronized void add(long value)
{
digest.add(value);
total.add(value);
}
@Managed
public synchronized double getCount()
{
return digest.getCount();
}
@Managed
public synchronized double getP50()
{
return convertToUnit(digest.valueAt(0.5));
}
@Managed
public synchronized double getP75()
{
return convertToUnit(digest.valueAt(0.75));
}
@Managed
public synchronized double getP90()
{
return convertToUnit(digest.valueAt(0.90));
}
@Managed
public synchronized double getP95()
{
return convertToUnit(digest.valueAt(0.95));
}
@Managed
public synchronized double getP99()
{
return convertToUnit(digest.valueAt(0.99));
}
@Managed
public synchronized double getMin()
{
return convertToUnit(digest.getMin());
}
@Managed
public synchronized double getMax()
{
return convertToUnit(digest.getMax());
}
@Managed
public synchronized double getAvg()
{
return convertToUnit(total.getCount()) / getCount();
}
@Managed
public TimeUnit getUnit()
{
return unit;
}
@Managed
public Map getPercentiles()
{
double[] values;
synchronized (this) {
values = digest.valuesAt(PERCENTILES);
}
verify(values.length == PERCENTILES.length, "values length mismatch");
Map result = new LinkedHashMap<>(values.length);
for (int i = 0; i < values.length; ++i) {
result.put(PERCENTILES[i], values[i]);
}
return result;
}
private double convertToUnit(long nanos)
{
if (nanos == Long.MAX_VALUE || nanos == Long.MIN_VALUE) {
return Double.NaN;
}
return nanos * 1.0 / unit.toNanos(1);
}
private double convertToUnit(double nanos)
{
return convertToUnit(nanos, (double) unit.toNanos(1));
}
private static double convertToUnit(double nanos, double unitNanos)
{
return nanos / unitNanos;
}
public TimeDistributionSnapshot snapshot()
{
double totalCount;
double digestCount;
double min;
double max;
double[] quantiles;
synchronized (this) {
totalCount = total.getCount();
digestCount = digest.getCount();
min = digest.getMin();
max = digest.getMax();
quantiles = digest.valuesAt(SNAPSHOT_QUANTILES);
}
double unitNanos = (double) unit.toNanos(1);
double average = convertToUnit(totalCount, unitNanos) / digestCount;
return new TimeDistributionSnapshot(
digestCount,
convertToUnit(quantiles[0], unitNanos), // p50
convertToUnit(quantiles[1], unitNanos), // p75
convertToUnit(quantiles[2], unitNanos), // p90
convertToUnit(quantiles[3], unitNanos), // p95
convertToUnit(quantiles[4], unitNanos), // p99
convertToUnit(min, unitNanos),
convertToUnit(max, unitNanos),
average,
unit);
}
@Managed
public synchronized void reset()
{
total.reset();
digest = new DecayTDigest(TDigest.DEFAULT_COMPRESSION, alpha);
}
public static class TimeDistributionSnapshot
{
private final double count;
private final double p50;
private final double p75;
private final double p90;
private final double p95;
private final double p99;
private final double min;
private final double max;
private final double avg;
private final TimeUnit unit;
@JsonCreator
public TimeDistributionSnapshot(
@JsonProperty("count") double count,
@JsonProperty("p50") double p50,
@JsonProperty("p75") double p75,
@JsonProperty("p90") double p90,
@JsonProperty("p95") double p95,
@JsonProperty("p99") double p99,
@JsonProperty("min") double min,
@JsonProperty("max") double max,
@JsonProperty("avg") double avg,
@JsonProperty("unit") TimeUnit unit)
{
this.count = count;
this.p50 = p50;
this.p75 = p75;
this.p90 = p90;
this.p95 = p95;
this.p99 = p99;
this.min = min;
this.max = max;
this.avg = avg;
this.unit = unit;
}
@JsonProperty
public double getCount()
{
return count;
}
@JsonProperty
public double getP50()
{
return p50;
}
@JsonProperty
public double getP75()
{
return p75;
}
@JsonProperty
public double getP90()
{
return p90;
}
@JsonProperty
public double getP95()
{
return p95;
}
@JsonProperty
public double getP99()
{
return p99;
}
@JsonProperty
public double getMin()
{
return min;
}
@JsonProperty
public double getMax()
{
return max;
}
@JsonProperty
public double getAvg()
{
return avg;
}
@JsonProperty
public TimeUnit unit()
{
return unit;
}
@Override
public String toString()
{
return toStringHelper(this)
.add("count", count)
.add("p50", p50)
.add("p75", p75)
.add("p90", p90)
.add("p95", p95)
.add("p99", p99)
.add("min", min)
.add("max", max)
.add("avg", avg)
.add("unit", unit)
.toString();
}
}
}