sonarqube fixes
This commit is contained in:
parent
ec58c764d2
commit
1db95358c5
16 changed files with 193 additions and 152 deletions
|
@ -1,7 +1,7 @@
|
|||
ext {
|
||||
user = 'xbib'
|
||||
name = 'metrics'
|
||||
description = 'A stripped-down version of Coda Hale Metrics'
|
||||
description = 'A stripped-down and modified version of Coda Hale Metrics'
|
||||
scmUrl = 'https://github.com/' + user + '/' + name
|
||||
scmConnection = 'scm:git:git://github.com/' + user + '/' + name + '.git'
|
||||
scmDeveloperConnection = 'scm:git:git://github.com/' + user + '/' + name + '.git'
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
package org.xbib.metrics;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.ThreadMXBean;
|
||||
|
||||
/**
|
||||
* An abstraction for how time passes. It is passed to {@link Sampler} to track timing.
|
||||
* An interface for how time passes. It is passed to {@link Sampler} to track timing.
|
||||
*/
|
||||
public abstract class Clock {
|
||||
public interface Clock {
|
||||
|
||||
/**
|
||||
* The default clock to use.
|
||||
*
|
||||
* @return the default {@link Clock} instance
|
||||
* @see Clock.UserTimeClock
|
||||
* @see UserTimeClock
|
||||
*/
|
||||
public static Clock defaultClock() {
|
||||
static Clock defaultClock() {
|
||||
return UserTimeClock.DEFAULT;
|
||||
}
|
||||
|
||||
|
@ -23,40 +20,13 @@ public abstract class Clock {
|
|||
*
|
||||
* @return time tick in nanoseconds
|
||||
*/
|
||||
public abstract long getTick();
|
||||
long getTick();
|
||||
|
||||
/**
|
||||
* Returns the current time in milliseconds.
|
||||
*
|
||||
* @return time in milliseconds
|
||||
*/
|
||||
public long getTime() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* A clock implementation which returns the current time in epoch nanoseconds.
|
||||
*/
|
||||
public static class UserTimeClock extends Clock {
|
||||
@Override
|
||||
public long getTick() {
|
||||
return System.nanoTime();
|
||||
}
|
||||
|
||||
static final Clock DEFAULT = new UserTimeClock();
|
||||
}
|
||||
|
||||
/**
|
||||
* A clock implementation which returns the current thread's CPU time.
|
||||
*/
|
||||
public static class CpuTimeClock extends Clock {
|
||||
private static final ThreadMXBean THREAD_MX_BEAN = ManagementFactory.getThreadMXBean();
|
||||
|
||||
@Override
|
||||
public long getTick() {
|
||||
return THREAD_MX_BEAN.getCurrentThreadCpuTime();
|
||||
}
|
||||
}
|
||||
|
||||
long getTime();
|
||||
|
||||
}
|
||||
|
|
21
src/main/java/org/xbib/metrics/CpuTimeClock.java
Normal file
21
src/main/java/org/xbib/metrics/CpuTimeClock.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package org.xbib.metrics;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.ThreadMXBean;
|
||||
|
||||
/**
|
||||
* A clock implementation which returns the current thread's CPU time.
|
||||
*/
|
||||
class CpuTimeClock implements Clock {
|
||||
private static final ThreadMXBean THREAD_MX_BEAN = ManagementFactory.getThreadMXBean();
|
||||
|
||||
@Override
|
||||
public long getTick() {
|
||||
return THREAD_MX_BEAN.getCurrentThreadCpuTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTime() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
}
|
|
@ -15,7 +15,8 @@ public class ExpWeightedMovingAverage {
|
|||
private static final double M5_ALPHA = 1 - Math.exp(-5 / 60.0 / 5);
|
||||
private static final double M15_ALPHA = 1 - Math.exp(-5 / 60.0 / 15);
|
||||
private final LongAdder uncounted = new LongAdder();
|
||||
private final double alpha, interval;
|
||||
private final double alpha;
|
||||
private final double interval;
|
||||
private volatile boolean initialized = false;
|
||||
private volatile double rate = 0.0;
|
||||
|
||||
|
|
|
@ -72,10 +72,12 @@ public class ExponentiallyDecayingReservoir implements Reservoir {
|
|||
this.nextScaleTime = new AtomicLong(clock.getTick() + RESCALE_THRESHOLD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return (int) min(size, count.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(long value) {
|
||||
update(value, currentTimeInSeconds());
|
||||
}
|
||||
|
@ -119,6 +121,7 @@ public class ExponentiallyDecayingReservoir implements Reservoir {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot getSnapshot() {
|
||||
lockForRegularUsage();
|
||||
try {
|
||||
|
|
|
@ -14,6 +14,7 @@ package org.xbib.metrics;
|
|||
*
|
||||
* @param <T> the type of the metric's value
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Gauge<T> extends Metric {
|
||||
/**
|
||||
* Returns the metric's current value.
|
||||
|
|
|
@ -40,7 +40,7 @@ public class Histogram implements Metric, Sampling, Count {
|
|||
|
||||
@Override
|
||||
public void inc(String index, String type, String id) {
|
||||
|
||||
// not used
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -55,7 +55,7 @@ public class Histogram implements Metric, Sampling, Count {
|
|||
|
||||
@Override
|
||||
public void dec(String index, String type, String id) {
|
||||
|
||||
// not used
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -46,12 +46,7 @@ public class Meter implements Metered {
|
|||
|
||||
public void spawn(long intervalSeconds) {
|
||||
this.future = Executors.newScheduledThreadPool(1)
|
||||
.scheduleAtFixedRate(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
tickIfNecessary();
|
||||
}
|
||||
}, intervalSeconds, intervalSeconds, TimeUnit.SECONDS);
|
||||
.scheduleAtFixedRate(this::tickIfNecessary, intervalSeconds, intervalSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
|
|
|
@ -3,16 +3,12 @@ package org.xbib.metrics;
|
|||
/**
|
||||
* A filter used to determine whether or not a metric should be reported, among other things.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface MetricFilter {
|
||||
/**
|
||||
* Matches all metrics, regardless of type or name.
|
||||
*/
|
||||
MetricFilter ALL = new MetricFilter() {
|
||||
@Override
|
||||
public boolean matches(MetricName name, Metric metric) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
MetricFilter ALL = (name, metric) -> true;
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the metric matches the filter; {@code false} otherwise.
|
||||
|
|
|
@ -41,7 +41,7 @@ public class MetricName implements Comparable<MetricName> {
|
|||
**/
|
||||
public static MetricName join(MetricName... parts) {
|
||||
final StringBuilder nameBuilder = new StringBuilder();
|
||||
final Map<String, String> tags = new HashMap<String, String>();
|
||||
final Map<String, String> tags = new HashMap<>();
|
||||
|
||||
boolean first = true;
|
||||
|
||||
|
@ -92,16 +92,13 @@ public class MetricName implements Comparable<MetricName> {
|
|||
if (name == null || name.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
builder.append(SEPARATOR);
|
||||
}
|
||||
|
||||
builder.append(name);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
@ -109,7 +106,6 @@ public class MetricName implements Comparable<MetricName> {
|
|||
if (tags == null || tags.isEmpty()) {
|
||||
return EMPTY_TAGS;
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(tags);
|
||||
}
|
||||
|
||||
|
@ -132,7 +128,6 @@ public class MetricName implements Comparable<MetricName> {
|
|||
*/
|
||||
public MetricName resolve(String p) {
|
||||
final String next;
|
||||
|
||||
if (p != null && !p.isEmpty()) {
|
||||
if (key != null && !key.isEmpty()) {
|
||||
next = key + SEPARATOR + p;
|
||||
|
@ -142,7 +137,6 @@ public class MetricName implements Comparable<MetricName> {
|
|||
} else {
|
||||
next = this.key;
|
||||
}
|
||||
|
||||
return new MetricName(next, tags);
|
||||
}
|
||||
|
||||
|
@ -153,9 +147,9 @@ public class MetricName implements Comparable<MetricName> {
|
|||
* @return A newly created metric name with the specified tags associated with it.
|
||||
*/
|
||||
public MetricName tagged(Map<String, String> add) {
|
||||
final Map<String, String> tags = new HashMap<String, String>(add);
|
||||
tags.putAll(this.tags);
|
||||
return new MetricName(key, tags);
|
||||
final Map<String, String> map = new HashMap<>(add);
|
||||
map.putAll(this.tags);
|
||||
return new MetricName(key, map);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -171,17 +165,13 @@ public class MetricName implements Comparable<MetricName> {
|
|||
if (pairs == null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (pairs.length % 2 != 0) {
|
||||
throw new IllegalArgumentException("Argument count must be even");
|
||||
}
|
||||
|
||||
final Map<String, String> add = new HashMap<String, String>();
|
||||
|
||||
final Map<String, String> add = new HashMap<>();
|
||||
for (int i = 0; i < pairs.length; i += 2) {
|
||||
add.put(pairs[i], pairs[i + 1]);
|
||||
}
|
||||
|
||||
return tagged(add);
|
||||
}
|
||||
|
||||
|
@ -189,9 +179,7 @@ public class MetricName implements Comparable<MetricName> {
|
|||
public String toString() {
|
||||
if (tags.isEmpty()) {
|
||||
return key;
|
||||
//return key + "{}";
|
||||
}
|
||||
|
||||
return key + tags;
|
||||
}
|
||||
|
||||
|
@ -209,17 +197,13 @@ public class MetricName implements Comparable<MetricName> {
|
|||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MetricName other = (MetricName) obj;
|
||||
|
||||
if (key == null) {
|
||||
if (other.key != null) {
|
||||
return false;
|
||||
|
@ -227,23 +211,15 @@ public class MetricName implements Comparable<MetricName> {
|
|||
} else if (!key.equals(other.key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return tags.equals(other.tags);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(MetricName o) {
|
||||
if (o == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int c = compareName(key, o.getKey());
|
||||
|
||||
if (c != 0) {
|
||||
return c;
|
||||
}
|
||||
|
||||
return compareTags(tags, o.getTags());
|
||||
}
|
||||
|
||||
|
@ -251,15 +227,12 @@ public class MetricName implements Comparable<MetricName> {
|
|||
if (left == null && right == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (left == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (right == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return left.compareTo(right);
|
||||
}
|
||||
|
||||
|
@ -267,45 +240,35 @@ public class MetricName implements Comparable<MetricName> {
|
|||
if (left == null && right == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (left == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (right == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final Iterable<String> keys = uniqueSortedKeys(left, right);
|
||||
|
||||
for (final String key : keys) {
|
||||
final String a = left.get(key);
|
||||
final String b = right.get(key);
|
||||
|
||||
for (final String s : keys) {
|
||||
final String a = left.get(s);
|
||||
final String b = right.get(s);
|
||||
if (a == null && b == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (b == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int c = a.compareTo(b);
|
||||
|
||||
if (c != 0) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private Iterable<String> uniqueSortedKeys(Map<String, String> left, Map<String, String> right) {
|
||||
final Set<String> set = new TreeSet<String>(left.keySet());
|
||||
final Set<String> set = new TreeSet<>(left.keySet());
|
||||
set.addAll(right.keySet());
|
||||
return set;
|
||||
}
|
||||
|
|
|
@ -10,12 +10,15 @@ import java.util.TreeSet;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A registry of metric instances.
|
||||
*/
|
||||
public class MetricRegistry implements MetricSet {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(MetricRegistry.class.getName());
|
||||
private final ConcurrentMap<MetricName, Metric> metrics;
|
||||
private final List<MetricRegistryListener> listeners;
|
||||
|
||||
|
@ -23,7 +26,7 @@ public class MetricRegistry implements MetricSet {
|
|||
* Creates a new {@link MetricRegistry}.
|
||||
*/
|
||||
public MetricRegistry() {
|
||||
this(new ConcurrentHashMap<MetricName, Metric>());
|
||||
this(new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,7 +38,7 @@ public class MetricRegistry implements MetricSet {
|
|||
*/
|
||||
protected MetricRegistry(ConcurrentMap<MetricName, Metric> metricsMap) {
|
||||
this.metrics = metricsMap;
|
||||
this.listeners = new CopyOnWriteArrayList<MetricRegistryListener>();
|
||||
this.listeners = new CopyOnWriteArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,7 +71,9 @@ public class MetricRegistry implements MetricSet {
|
|||
}
|
||||
final String[] parts = new String[length + 1];
|
||||
parts[0] = name;
|
||||
System.arraycopy(names, 0, parts, 1, length);
|
||||
if (names != null) {
|
||||
System.arraycopy(names, 0, parts, 1, length);
|
||||
}
|
||||
return MetricName.build(parts);
|
||||
}
|
||||
|
||||
|
@ -80,7 +85,7 @@ public class MetricRegistry implements MetricSet {
|
|||
* @see #register(MetricName, Metric)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Metric> T register(String name, T metric) throws IllegalArgumentException {
|
||||
public <T extends Metric> T register(String name, T metric) {
|
||||
return register(MetricName.build(name), metric);
|
||||
}
|
||||
|
||||
|
@ -94,7 +99,7 @@ public class MetricRegistry implements MetricSet {
|
|||
* @throws IllegalArgumentException if the name is already registered
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Metric> T register(MetricName name, T metric) throws IllegalArgumentException {
|
||||
public <T extends Metric> T register(MetricName name, T metric) {
|
||||
if (metric instanceof MetricSet) {
|
||||
registerAll(name, (MetricSet) metric);
|
||||
} else {
|
||||
|
@ -115,7 +120,7 @@ public class MetricRegistry implements MetricSet {
|
|||
* @param metrics a set of metrics
|
||||
* @throws IllegalArgumentException if any of the names are already registered
|
||||
*/
|
||||
public void registerAll(MetricSet metrics) throws IllegalArgumentException {
|
||||
public void registerAll(MetricSet metrics) {
|
||||
registerAll(null, metrics);
|
||||
}
|
||||
|
||||
|
@ -368,6 +373,7 @@ public class MetricRegistry implements MetricSet {
|
|||
try {
|
||||
return register(name, builder.newMetric());
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.log(Level.WARNING, e.getMessage(), e);
|
||||
final Metric added = metrics.get(name);
|
||||
if (builder.isInstance(added)) {
|
||||
return (T) added;
|
||||
|
@ -379,7 +385,7 @@ public class MetricRegistry implements MetricSet {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Metric> SortedMap<MetricName, T> getMetrics(Class<T> klass, MetricFilter filter) {
|
||||
final TreeMap<MetricName, T> timers = new TreeMap<MetricName, T>();
|
||||
final TreeMap<MetricName, T> timers = new TreeMap<>();
|
||||
for (Map.Entry<MetricName, Metric> entry : metrics.entrySet()) {
|
||||
if (klass.isInstance(entry.getValue()) && filter.matches(entry.getKey(),
|
||||
entry.getValue())) {
|
||||
|
@ -433,11 +439,8 @@ public class MetricRegistry implements MetricSet {
|
|||
}
|
||||
}
|
||||
|
||||
private void registerAll(MetricName prefix, MetricSet metrics) throws IllegalArgumentException {
|
||||
if (prefix == null) {
|
||||
prefix = MetricName.EMPTY;
|
||||
}
|
||||
|
||||
private void registerAll(MetricName prefixName, MetricSet metrics) {
|
||||
MetricName prefix = prefixName == null ? MetricName.EMPTY : prefixName;
|
||||
for (Map.Entry<MetricName, Metric> entry : metrics.getMetrics().entrySet()) {
|
||||
if (entry.getValue() instanceof MetricSet) {
|
||||
registerAll(MetricName.join(prefix, entry.getKey()), (MetricSet) entry.getValue());
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.util.Map;
|
|||
*
|
||||
* @see MetricRegistry#registerAll(MetricSet)
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface MetricSet extends Metric {
|
||||
/**
|
||||
* A map of metric names to metrics.
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.xbib.metrics;
|
|||
/**
|
||||
* An object which samples values.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Sampling {
|
||||
/**
|
||||
* Returns a snapshot of the values.
|
||||
|
|
|
@ -3,9 +3,9 @@ package org.xbib.metrics;
|
|||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A statistical snapshot of a {@link Snapshot}.
|
||||
* A {@link Snapshot}.
|
||||
*/
|
||||
public abstract class Snapshot {
|
||||
public interface Snapshot {
|
||||
|
||||
/**
|
||||
* Returns the value at the given quantile.
|
||||
|
@ -13,109 +13,97 @@ public abstract class Snapshot {
|
|||
* @param quantile a given quantile, in {@code [0..1]}
|
||||
* @return the value in the distribution at {@code quantile}
|
||||
*/
|
||||
public abstract double getValue(double quantile);
|
||||
double getValue(double quantile);
|
||||
|
||||
/**
|
||||
* Returns the entire set of values in the snapshot.
|
||||
*
|
||||
* @return the entire set of values
|
||||
*/
|
||||
public abstract long[] getValues();
|
||||
long[] getValues();
|
||||
|
||||
/**
|
||||
* Returns the number of values in the snapshot.
|
||||
*
|
||||
* @return the number of values
|
||||
*/
|
||||
public abstract int size();
|
||||
int size();
|
||||
|
||||
/**
|
||||
* Returns the median value in the distribution.
|
||||
*
|
||||
* @return the median value
|
||||
*/
|
||||
public double getMedian() {
|
||||
return getValue(0.5);
|
||||
}
|
||||
double getMedian();
|
||||
|
||||
/**
|
||||
* Returns the value at the 75th percentile in the distribution.
|
||||
*
|
||||
* @return the value at the 75th percentile
|
||||
*/
|
||||
public double get75thPercentile() {
|
||||
return getValue(0.75);
|
||||
}
|
||||
double get75thPercentile();
|
||||
|
||||
/**
|
||||
* Returns the value at the 95th percentile in the distribution.
|
||||
*
|
||||
* @return the value at the 95th percentile
|
||||
*/
|
||||
public double get95thPercentile() {
|
||||
return getValue(0.95);
|
||||
}
|
||||
double get95thPercentile();
|
||||
|
||||
/**
|
||||
* Returns the value at the 98th percentile in the distribution.
|
||||
*
|
||||
* @return the value at the 98th percentile
|
||||
*/
|
||||
public double get98thPercentile() {
|
||||
return getValue(0.98);
|
||||
}
|
||||
double get98thPercentile();
|
||||
|
||||
/**
|
||||
* Returns the value at the 99th percentile in the distribution.
|
||||
*
|
||||
* @return the value at the 99th percentile
|
||||
*/
|
||||
public double get99thPercentile() {
|
||||
return getValue(0.99);
|
||||
}
|
||||
double get99thPercentile();
|
||||
|
||||
/**
|
||||
* Returns the value at the 99.9th percentile in the distribution.
|
||||
*
|
||||
* @return the value at the 99.9th percentile
|
||||
*/
|
||||
public double get999thPercentile() {
|
||||
return getValue(0.999);
|
||||
}
|
||||
double get999thPercentile();
|
||||
|
||||
/**
|
||||
* Returns the highest value in the snapshot.
|
||||
*
|
||||
* @return the highest value
|
||||
*/
|
||||
public abstract long getMax();
|
||||
long getMax();
|
||||
|
||||
/**
|
||||
* Returns the arithmetic mean of the values in the snapshot.
|
||||
*
|
||||
* @return the arithmetic mean
|
||||
*/
|
||||
public abstract double getMean();
|
||||
double getMean();
|
||||
|
||||
/**
|
||||
* Returns the lowest value in the snapshot.
|
||||
*
|
||||
* @return the lowest value
|
||||
*/
|
||||
public abstract long getMin();
|
||||
long getMin();
|
||||
|
||||
/**
|
||||
* Returns the standard deviation of the values in the snapshot.
|
||||
*
|
||||
* @return the standard value
|
||||
*/
|
||||
public abstract double getStdDev();
|
||||
double getStdDev();
|
||||
|
||||
/**
|
||||
* Writes the values of the snapshot to the given stream.
|
||||
*
|
||||
* @param output an output stream
|
||||
*/
|
||||
public abstract void dump(OutputStream output);
|
||||
void dump(OutputStream output);
|
||||
|
||||
}
|
||||
|
|
20
src/main/java/org/xbib/metrics/UserTimeClock.java
Normal file
20
src/main/java/org/xbib/metrics/UserTimeClock.java
Normal file
|
@ -0,0 +1,20 @@
|
|||
package org.xbib.metrics;
|
||||
|
||||
/**
|
||||
* A clock implementation which returns the current time in epoch nanoseconds.
|
||||
*/
|
||||
class UserTimeClock implements Clock {
|
||||
|
||||
static final Clock DEFAULT = new UserTimeClock();
|
||||
|
||||
@Override
|
||||
public long getTick() {
|
||||
return System.nanoTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTime() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
|
@ -6,12 +6,11 @@ import java.io.PrintWriter;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* A statistical snapshot of a {@link WeightedSnapshot}.
|
||||
*/
|
||||
public class WeightedSnapshot extends Snapshot {
|
||||
public class WeightedSnapshot implements Snapshot {
|
||||
|
||||
private final long[] values;
|
||||
private final double[] normWeights;
|
||||
|
@ -25,31 +24,28 @@ public class WeightedSnapshot extends Snapshot {
|
|||
public WeightedSnapshot(Collection<WeightedSample> values) {
|
||||
final WeightedSample[] copy = values.toArray(new WeightedSample[]{});
|
||||
|
||||
Arrays.sort(copy, new Comparator<WeightedSample>() {
|
||||
@Override
|
||||
public int compare(WeightedSample o1, WeightedSample o2) {
|
||||
if (o1.value > o2.value) {
|
||||
return 1;
|
||||
}
|
||||
if (o1.value < o2.value) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
Arrays.sort(copy, (o1, o2) -> {
|
||||
if (o1.value > o2.value) {
|
||||
return 1;
|
||||
}
|
||||
if (o1.value < o2.value) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
this.values = new long[copy.length];
|
||||
this.normWeights = new double[copy.length];
|
||||
this.quantiles = new double[copy.length];
|
||||
|
||||
double sumWeight = 0;
|
||||
double sumWeight = 0.0f;
|
||||
for (WeightedSample sample : copy) {
|
||||
sumWeight += sample.weight;
|
||||
}
|
||||
|
||||
for (int i = 0; i < copy.length; i++) {
|
||||
this.values[i] = copy[i].value;
|
||||
this.normWeights[i] = copy[i].weight / sumWeight;
|
||||
this.normWeights[i] = safeDivide(copy[i].weight, sumWeight);
|
||||
}
|
||||
|
||||
for (int i = 1; i < copy.length; i++) {
|
||||
|
@ -57,6 +53,88 @@ public class WeightedSnapshot extends Snapshot {
|
|||
}
|
||||
}
|
||||
|
||||
private static double safeDivide(double dividend, double divisor) {
|
||||
if (Double.compare(divisor, Double.NaN) == 0) {
|
||||
return Double.NaN;
|
||||
}
|
||||
if (Double.compare(dividend, Double.NaN) == 0) {
|
||||
return Double.NaN;
|
||||
}
|
||||
if (Double.compare(divisor, 0.0) == 0) {
|
||||
if (Double.compare(dividend, 0.0) == -1) {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
return Double.POSITIVE_INFINITY;
|
||||
}
|
||||
if (Double.compare(divisor, -0.0) == 0) {
|
||||
if (Double.compare(dividend, -0.0) == 1) {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
return Double.POSITIVE_INFINITY;
|
||||
}
|
||||
return dividend / divisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the median value in the distribution.
|
||||
*
|
||||
* @return the median value
|
||||
*/
|
||||
@Override
|
||||
public double getMedian() {
|
||||
return getValue(0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the 75th percentile in the distribution.
|
||||
*
|
||||
* @return the value at the 75th percentile
|
||||
*/
|
||||
@Override
|
||||
public double get75thPercentile() {
|
||||
return getValue(0.75);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the 95th percentile in the distribution.
|
||||
*
|
||||
* @return the value at the 95th percentile
|
||||
*/
|
||||
@Override
|
||||
public double get95thPercentile() {
|
||||
return getValue(0.95);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the 98th percentile in the distribution.
|
||||
*
|
||||
* @return the value at the 98th percentile
|
||||
*/
|
||||
@Override
|
||||
public double get98thPercentile() {
|
||||
return getValue(0.98);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the 99th percentile in the distribution.
|
||||
*
|
||||
* @return the value at the 99th percentile
|
||||
*/
|
||||
@Override
|
||||
public double get99thPercentile() {
|
||||
return getValue(0.99);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the 99.9th percentile in the distribution.
|
||||
*
|
||||
* @return the value at the 99.9th percentile
|
||||
*/
|
||||
@Override
|
||||
public double get999thPercentile() {
|
||||
return getValue(0.999);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the given quantile.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue