forked from I2P_Developers/i2p.i2p
WIP: Draft: Prometheus-friendly stat variants
- gauge, counter, and info only, no buckets - embed type and units in stats - optimized for low memory/CPU usage, no doubles, no locking - to be hooked in
This commit is contained in:
69
core/java/src/net/i2p/stat/prometheus/AtomicFloat.java
Normal file
69
core/java/src/net/i2p/stat/prometheus/AtomicFloat.java
Normal file
@@ -0,0 +1,69 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
/*
|
||||
* Contains code adapted from Google Guava AtomicDouble:
|
||||
*
|
||||
* Written by Doug Lea and Martin Buchholz with assistance from
|
||||
* members of JCP JSR-166 Expert Group and released to the public
|
||||
* domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import static java.lang.Float.*;
|
||||
|
||||
/**
|
||||
* ref: https://stackoverflow.com/questions/5505460/java-is-there-no-atomicfloat-or-atomicfloat
|
||||
* with code adapted from Google Guava AtomicDouble
|
||||
* ref: https://github.com/google/guava/blob/master/guava/src/com/google/common/util/concurrent/AtomicDouble.java
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public class AtomicFloat extends Number {
|
||||
|
||||
private final AtomicInteger bits;
|
||||
|
||||
public AtomicFloat() {
|
||||
bits = new AtomicInteger();
|
||||
}
|
||||
|
||||
public AtomicFloat(float initialValue) {
|
||||
bits = new AtomicInteger(floatToIntBits(initialValue));
|
||||
}
|
||||
|
||||
public final void set(float newValue) {
|
||||
bits.set(floatToIntBits(newValue));
|
||||
}
|
||||
|
||||
public final float get() {
|
||||
return intBitsToFloat(bits.get());
|
||||
}
|
||||
|
||||
public final float incrementAndGet() {
|
||||
return addAndGet(1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Code adapted from Google Guava AtomicDouble
|
||||
*/
|
||||
public final float addAndGet(float value) {
|
||||
while (true) {
|
||||
int current = bits.get();
|
||||
float currentVal = intBitsToFloat(current);
|
||||
float nextVal = currentVal + value;
|
||||
int next = floatToRawIntBits(nextVal);
|
||||
if (bits.compareAndSet(current, next))
|
||||
return nextVal;
|
||||
}
|
||||
}
|
||||
|
||||
public int intValue() { return (int) get(); }
|
||||
public long longValue() { return (long) get(); }
|
||||
public float floatValue() { return get(); }
|
||||
public double doubleValue() { return get(); }
|
||||
|
||||
@Override
|
||||
public String toString() { return Double.toString(get()); }
|
||||
|
||||
|
||||
}
|
||||
57
core/java/src/net/i2p/stat/prometheus/Counter.java
Normal file
57
core/java/src/net/i2p/stat/prometheus/Counter.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A simple Prometheus-style counter, with overflow protection.
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public class Counter extends PromStat implements IntConsumer, IntSupplier {
|
||||
|
||||
private final AtomicInteger c = new AtomicInteger();
|
||||
|
||||
public Counter(String name, String desc, Unit unit) {
|
||||
super(name, desc, Type.COUNTER, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets to 0 on overflow.
|
||||
*/
|
||||
public void increment() {
|
||||
int v = c.incrementAndGet();
|
||||
if (v < 0)
|
||||
c.set(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets to 0 on overflow.
|
||||
*/
|
||||
public void add(int value) {
|
||||
int v = c.addAndGet(value);
|
||||
if (v < 0)
|
||||
c.set(0);
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
public double getDoubleValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplier interface
|
||||
*/
|
||||
public int getAsInt() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumer interface
|
||||
*/
|
||||
public void accept(int value) {
|
||||
c.addAndGet(value);
|
||||
}
|
||||
}
|
||||
48
core/java/src/net/i2p/stat/prometheus/FCounter.java
Normal file
48
core/java/src/net/i2p/stat/prometheus/FCounter.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
/**
|
||||
* A simple Prometheus-style counter.
|
||||
* No overflow protection, shouldn't happen.
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public class FCounter extends PromStat implements FloatConsumer, FloatSupplier {
|
||||
|
||||
private final AtomicFloat c = new AtomicFloat();
|
||||
|
||||
public FCounter(String name, String desc, Unit unit) {
|
||||
super(name, desc, Type.COUNTER, unit);
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
c.incrementAndGet();
|
||||
// assume won't overflow
|
||||
}
|
||||
|
||||
public void add(float value) {
|
||||
c.addAndGet(value);
|
||||
// assume won't overflow
|
||||
}
|
||||
|
||||
public float getValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
public double getDoubleValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplier interface
|
||||
*/
|
||||
public float getAsFloat() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumer interface
|
||||
*/
|
||||
public void accept(float value) {
|
||||
c.addAndGet(value);
|
||||
}
|
||||
}
|
||||
59
core/java/src/net/i2p/stat/prometheus/FGauge.java
Normal file
59
core/java/src/net/i2p/stat/prometheus/FGauge.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
|
||||
/**
|
||||
* A simple Prometheus-style gauge
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public class FGauge extends PromStat implements FloatConsumer, FloatSupplier {
|
||||
|
||||
private final AtomicFloat c = new AtomicFloat();
|
||||
private final FloatSupplier s;
|
||||
|
||||
public FGauge(String name, String desc, Unit unit) {
|
||||
this(name, desc, unit, null);
|
||||
}
|
||||
|
||||
public FGauge(String name, String desc, Unit unit, FloatSupplier supplier) {
|
||||
super(name, desc, Type.GAUGE, unit);
|
||||
s = supplier;
|
||||
}
|
||||
|
||||
public void setValue(float value) {
|
||||
c.set(value);
|
||||
}
|
||||
|
||||
public float getValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
public double getDoubleValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* For StatManager
|
||||
*/
|
||||
@Override
|
||||
public void coalesceStats() {
|
||||
if (s != null)
|
||||
c.set(s.getAsFloat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplier interface
|
||||
*/
|
||||
public float getAsFloat() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumer interface
|
||||
*
|
||||
* Adds the value
|
||||
*/
|
||||
public void accept(float value) {
|
||||
c.set(value);
|
||||
}
|
||||
}
|
||||
10
core/java/src/net/i2p/stat/prometheus/FloatConsumer.java
Normal file
10
core/java/src/net/i2p/stat/prometheus/FloatConsumer.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
/**
|
||||
* Until we set a min SDK in Android that has java.util.function
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public interface FloatConsumer {
|
||||
public void accept(float value);
|
||||
}
|
||||
10
core/java/src/net/i2p/stat/prometheus/FloatSupplier.java
Normal file
10
core/java/src/net/i2p/stat/prometheus/FloatSupplier.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
/**
|
||||
* Until we set a min SDK in Android that has java.util.function
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public interface FloatSupplier {
|
||||
public float getAsFloat();
|
||||
}
|
||||
60
core/java/src/net/i2p/stat/prometheus/Gauge.java
Normal file
60
core/java/src/net/i2p/stat/prometheus/Gauge.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A simple Prometheus-style gauge
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public class Gauge extends PromStat implements IntConsumer, IntSupplier {
|
||||
|
||||
private final AtomicInteger c = new AtomicInteger();
|
||||
private final IntSupplier s;
|
||||
|
||||
public Gauge(String name, String desc, Unit unit) {
|
||||
this(name, desc, unit, null);
|
||||
}
|
||||
|
||||
public Gauge(String name, String desc, Unit unit, IntSupplier supplier) {
|
||||
super(name, desc, Type.GAUGE, unit);
|
||||
s = supplier;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
c.set(value);
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
public double getDoubleValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* For StatManager
|
||||
*/
|
||||
@Override
|
||||
public void coalesceStats() {
|
||||
if (s != null)
|
||||
c.set(s.getAsInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplier interface
|
||||
*/
|
||||
public int getAsInt() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumer interface
|
||||
*
|
||||
* Adds the value
|
||||
*/
|
||||
public void accept(int value) {
|
||||
c.set(value);
|
||||
}
|
||||
}
|
||||
76
core/java/src/net/i2p/stat/prometheus/Info.java
Normal file
76
core/java/src/net/i2p/stat/prometheus/Info.java
Normal file
@@ -0,0 +1,76 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A simple Prometheus-style info. Value is always 1.
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public class Info extends PromStat implements IntSupplier, PropsSupplier, PropsConsumer {
|
||||
|
||||
private final Map<String, String> props;
|
||||
|
||||
/**
|
||||
* Map returned by getValues() will be a ConcurrentHashMap
|
||||
*/
|
||||
public Info(String name, String desc) {
|
||||
this(name, desc, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param props use caution, use a ConcurrentHashMap if setValue() or accept()
|
||||
* will be called later to change the properties
|
||||
*/
|
||||
public Info(String name, String desc, Map<String, String> props) {
|
||||
super(name, desc, Type.GAUGE, Unit.NONE);
|
||||
this.props = (props != null) ? props : new ConcurrentHashMap<String, String>(4);
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public double getDoubleValue() {
|
||||
return 1.0d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return not a copy
|
||||
*/
|
||||
public Map<String, String> getValues() {
|
||||
return props;
|
||||
}
|
||||
|
||||
public void setValue(String key, String val) {
|
||||
props.put(key, val);
|
||||
}
|
||||
|
||||
public void removeValue(String key) {
|
||||
props.remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplier interface
|
||||
*/
|
||||
public int getAsInt() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplier interface
|
||||
*/
|
||||
public Map<String, String> getAsMap() {
|
||||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumer interface
|
||||
*/
|
||||
public void accept(Map<String, String> values) {
|
||||
props.putAll(values);
|
||||
}
|
||||
}
|
||||
10
core/java/src/net/i2p/stat/prometheus/IntConsumer.java
Normal file
10
core/java/src/net/i2p/stat/prometheus/IntConsumer.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
/**
|
||||
* Until we set a min SDK in Android that has java.util.function
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public interface IntConsumer {
|
||||
public void accept(int value);
|
||||
}
|
||||
10
core/java/src/net/i2p/stat/prometheus/IntSupplier.java
Normal file
10
core/java/src/net/i2p/stat/prometheus/IntSupplier.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
/**
|
||||
* Until we set a min SDK in Android that has java.util.function
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public interface IntSupplier {
|
||||
public int getAsInt();
|
||||
}
|
||||
50
core/java/src/net/i2p/stat/prometheus/LCounter.java
Normal file
50
core/java/src/net/i2p/stat/prometheus/LCounter.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* A simple Prometheus-style counter.
|
||||
* No overflow protection, shouldn't happen.
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public class LCounter extends PromStat implements LongConsumer, LongSupplier {
|
||||
|
||||
private final AtomicLong c = new AtomicLong();
|
||||
|
||||
public LCounter(String name, String desc, Unit unit) {
|
||||
super(name, desc, Type.COUNTER, unit);
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
c.incrementAndGet();
|
||||
// assume won't overflow
|
||||
}
|
||||
|
||||
public void add(long value) {
|
||||
c.addAndGet(value);
|
||||
// assume won't overflow
|
||||
}
|
||||
|
||||
public long getValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
public double getDoubleValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplier interface
|
||||
*/
|
||||
public long getAsLong() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumer interface
|
||||
*/
|
||||
public void accept(long value) {
|
||||
c.addAndGet(value);
|
||||
}
|
||||
}
|
||||
60
core/java/src/net/i2p/stat/prometheus/LGauge.java
Normal file
60
core/java/src/net/i2p/stat/prometheus/LGauge.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* A simple Prometheus-style gauge
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public class LGauge extends PromStat implements LongConsumer, LongSupplier {
|
||||
|
||||
private final AtomicLong c = new AtomicLong();
|
||||
private final LongSupplier s;
|
||||
|
||||
public LGauge(String name, String desc, Unit unit) {
|
||||
this(name, desc, unit, null);
|
||||
}
|
||||
|
||||
public LGauge(String name, String desc, Unit unit, LongSupplier supplier) {
|
||||
super(name, desc, Type.GAUGE, unit);
|
||||
s = supplier;
|
||||
}
|
||||
|
||||
public void setValue(long value) {
|
||||
c.set(value);
|
||||
}
|
||||
|
||||
public long getValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
public double getDoubleValue() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* For StatManager
|
||||
*/
|
||||
@Override
|
||||
public void coalesceStats() {
|
||||
if (s != null)
|
||||
c.set(s.getAsLong());
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplier interface
|
||||
*/
|
||||
public long getAsLong() {
|
||||
return c.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumer interface
|
||||
*
|
||||
* Adds the value
|
||||
*/
|
||||
public void accept(long value) {
|
||||
c.set(value);
|
||||
}
|
||||
}
|
||||
10
core/java/src/net/i2p/stat/prometheus/LongConsumer.java
Normal file
10
core/java/src/net/i2p/stat/prometheus/LongConsumer.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
/**
|
||||
* Until we set a min SDK in Android that has java.util.function
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public interface LongConsumer {
|
||||
public void accept(long value);
|
||||
}
|
||||
10
core/java/src/net/i2p/stat/prometheus/LongSupplier.java
Normal file
10
core/java/src/net/i2p/stat/prometheus/LongSupplier.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
/**
|
||||
* Until we set a min SDK in Android that has java.util.function
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public interface LongSupplier {
|
||||
public long getAsLong();
|
||||
}
|
||||
83
core/java/src/net/i2p/stat/prometheus/PromStat.java
Normal file
83
core/java/src/net/i2p/stat/prometheus/PromStat.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
/**
|
||||
* A simple Prometheus-style metric.
|
||||
*
|
||||
* Units are stored in the units specified,
|
||||
* and scaled in getScaledValue().
|
||||
*
|
||||
* These stats are not persisted by StatManager.
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public abstract class PromStat {
|
||||
|
||||
private final String desc;
|
||||
private final String name;
|
||||
private final String promName;
|
||||
private final Type type;
|
||||
private final Unit unit;
|
||||
|
||||
/*
|
||||
* @param name [a-zA-Z0-9_.] only. '.' will be replaced with '_' for getPromName()
|
||||
*/
|
||||
public PromStat(String name, String description, Type type, Unit unit) {
|
||||
this.name = name;
|
||||
desc = description;
|
||||
this.type = type;
|
||||
this.unit = unit;
|
||||
String p = name.replace(".", "_");
|
||||
if (p.replaceAll("[a-zA-Z0-9_]", "").length() != 0)
|
||||
throw new IllegalArgumentException("invalid chars in name " + name);
|
||||
if (type != Type.INFO)
|
||||
p += '_' + unit.getName();
|
||||
if (type == Type.COUNTER)
|
||||
p += "_total";
|
||||
promName = p;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getPromName() {
|
||||
return promName;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public Type getType() { return type; }
|
||||
|
||||
public Unit getUnit() { return unit; }
|
||||
|
||||
/**
|
||||
* In units specified
|
||||
*/
|
||||
public abstract double getDoubleValue();
|
||||
|
||||
/**
|
||||
* Scaled to what Prometheus expects,
|
||||
* seconds, bytes, or count.
|
||||
*/
|
||||
public double getScaledValue() {
|
||||
double rv = getDoubleValue();
|
||||
switch (unit) {
|
||||
case KBYTES:
|
||||
rv *= 1000f;
|
||||
break;
|
||||
|
||||
case MS:
|
||||
rv /= 1000f;
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* For StatManager.
|
||||
* Does nothing (for counters), extend for guages if necessary.
|
||||
*/
|
||||
public void coalesceStats() {}
|
||||
}
|
||||
12
core/java/src/net/i2p/stat/prometheus/PropsConsumer.java
Normal file
12
core/java/src/net/i2p/stat/prometheus/PropsConsumer.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Until we set a min SDK in Android that has java.util.function
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public interface PropsConsumer {
|
||||
public void accept(Map<String, String> values);
|
||||
}
|
||||
12
core/java/src/net/i2p/stat/prometheus/PropsSupplier.java
Normal file
12
core/java/src/net/i2p/stat/prometheus/PropsSupplier.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Until we set a min SDK in Android that has java.util.function
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public interface PropsSupplier {
|
||||
public Map<String, String> getAsMap();
|
||||
}
|
||||
21
core/java/src/net/i2p/stat/prometheus/Type.java
Normal file
21
core/java/src/net/i2p/stat/prometheus/Type.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
/**
|
||||
* Prometheus-style types
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public enum Type {
|
||||
|
||||
COUNTER("counter"),
|
||||
GAUGE("gauge"),
|
||||
INFO("info");
|
||||
|
||||
private final String name;
|
||||
|
||||
Type(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() { return name; }
|
||||
}
|
||||
24
core/java/src/net/i2p/stat/prometheus/Unit.java
Normal file
24
core/java/src/net/i2p/stat/prometheus/Unit.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package net.i2p.stat.prometheus;
|
||||
|
||||
/**
|
||||
* Prometheus-style units
|
||||
*
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public enum Unit {
|
||||
|
||||
BYTES("bytes"),
|
||||
KBYTES("bytes"),
|
||||
SECONDS("seconds"),
|
||||
MS("seconds"),
|
||||
EVENTS("count"),
|
||||
NONE("");
|
||||
|
||||
private final String name;
|
||||
|
||||
Unit(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() { return name; }
|
||||
}
|
||||
Reference in New Issue
Block a user