Metrics: Add custom witness for plugins, and code clean up

Remove LongGauge and DoubleGauge and Replace with NumberGauge
 - This is an unecessary distiction for Gauges and can complicate the serialization. Double/Float should serialize with decimal precision, and Jackson handles this by default.

Add custom witness to match existing Ruby API, such that existing Ruby plugins should not need changes

Remove namespace from LazyDelegatingGauge
 - It was only there for logging, but newer versions (not here) will completely remove the concept of namespace.

Part of #7788

Fixes #8053
This commit is contained in:
Jake Landis 2017-08-22 17:06:17 -05:00
parent c317fee147
commit 9b961c46d7
22 changed files with 462 additions and 231 deletions

View file

@ -4,7 +4,7 @@ module LogStash module Instrument module MetricType
class Gauge < LazyDelegatingGauge
def initialize(namespaces, key)
super(namespaces, key.to_s)
super(key.to_s)
end
def execute(action, value = nil)

View file

@ -21,13 +21,9 @@ public enum MetricType {
*/
GAUGE_BOOLEAN("gauge/boolean"),
/**
* A gauge backed by a {@link Double} type
* A gauge backed by a {@link Number} type
*/
GAUGE_DOUBLE("gauge/double"),
/**
* A gauge backed by a {@link Long} type
*/
GAUGE_LONG("gauge/long"),
GAUGE_NUMBER("gauge/number"),
/**
* A gauge backed by a {@link Object} type.
*/

View file

@ -1,35 +0,0 @@
package org.logstash.instrument.metrics.gauge;
import org.logstash.instrument.metrics.MetricType;
/**
* A {@link GaugeMetric} that is backed by a {@link Double}
*/
public class DoubleGauge extends AbstractGaugeMetric<Double> {
/**
* Constructor
*
* @param name The name of this metric. This value may be used for display purposes.
*/
public DoubleGauge(String name) {
super(name);
}
/**
* Constructor
*
* @param name The name of this metric. This value may be used for display purposes.
* @param initialValue The initial value for this {@link GaugeMetric}, may be null
*/
public DoubleGauge(String name, Double initialValue) {
super(name, initialValue);
}
@Override
public MetricType getType() {
return MetricType.GAUGE_DOUBLE;
}
}

View file

@ -7,11 +7,10 @@ import org.logstash.ext.JrubyTimestampExtLibrary.RubyTimestamp;
import org.logstash.instrument.metrics.AbstractMetric;
import org.logstash.instrument.metrics.MetricType;
import java.util.List;
/**
* A lazy proxy to a more specific typed {@link GaugeMetric}. The metric will only be initialized if the initial value is set, or once the {@code set} operation is called.
* <p><strong>Intended only for use with Ruby's duck typing, Java consumers should use the specific typed {@link GaugeMetric}</strong></p>
*
* @deprecated - there are no plans to replace this.
*/
public class LazyDelegatingGauge extends AbstractMetric<Object> implements GaugeMetric<Object, Object> {
@ -19,32 +18,28 @@ public class LazyDelegatingGauge extends AbstractMetric<Object> implements Gauge
private final static Logger LOGGER = LogManager.getLogger(LazyDelegatingGauge.class);
protected final String key;
protected final List<String> nameSpaces;
private GaugeMetric lazyMetric;
/**
* Constructor - protected so that Ruby may sub class proxy and discourage usage from Java, null initial value
* Constructor - null initial value
*
* @param nameSpace The namespace for this metric
* @param key The key <i>(with in the namespace)</i> for this metric
* @deprecated - there are no plans to replace this
*/
public LazyDelegatingGauge(final List<String> nameSpace, final String key) {
this(nameSpace, key, null);
public LazyDelegatingGauge(final String key) {
this(key, null);
}
/**
* Constructor - protected so that Ruby may sub class proxy and discourage usage from Java
* Constructor - with initial value
*
* @param nameSpace The namespace for this metric
* @param key The key <i>(with in the namespace)</i> for this metric
* @param key The key for this metric
* @param initialValue The initial value for this {@link GaugeMetric}, may be null
* @deprecated - there are no plans to replace this
*/
protected LazyDelegatingGauge(List<String> nameSpace, String key, Object initialValue) {
public LazyDelegatingGauge(String key, Object initialValue) {
super(key);
this.nameSpaces = nameSpace;
this.key = key;
if (initialValue != null) {
wakeMetric(initialValue);
@ -86,10 +81,8 @@ public class LazyDelegatingGauge extends AbstractMetric<Object> implements Gauge
//"quack quack"
if (value instanceof String) {
lazyMetric = new TextGauge(key, (String) value);
} else if (value instanceof Long) {
lazyMetric = new LongGauge(key, (Long) value);
} else if (value instanceof Double) {
lazyMetric = new DoubleGauge(key, (Double) value);
} else if (value instanceof Number) {
lazyMetric = new NumberGauge(key, (Number) value);
} else if (value instanceof Boolean) {
lazyMetric = new BooleanGauge(key, (Boolean) value);
} else if (value instanceof RubyHash) {
@ -97,11 +90,10 @@ public class LazyDelegatingGauge extends AbstractMetric<Object> implements Gauge
} else if (value instanceof RubyTimestamp) {
lazyMetric = new RubyTimeStampGauge(key, ((RubyTimestamp) value));
} else {
LOGGER.warn("A gauge metric of an unknown type ({}) has been create for key: {}, namespace:{}. This may result in invalid serialization. It is recommended to " +
"log an issue to the responsible developer/development team.", value.getClass().getCanonicalName(), key, nameSpaces);
LOGGER.warn("A gauge metric of an unknown type ({}) has been create for key: {}. This may result in invalid serialization. It is recommended to " +
"log an issue to the responsible developer/development team.", value.getClass().getCanonicalName(), key);
lazyMetric = new UnknownGauge(key, value);
}
}
}
}

View file

@ -3,17 +3,16 @@ package org.logstash.instrument.metrics.gauge;
import org.logstash.instrument.metrics.MetricType;
/**
* A {@link GaugeMetric} that is backed by a {@link Long}
* A {@link GaugeMetric} that is backed by a {@link Number}
*/
public class LongGauge extends AbstractGaugeMetric<Long> {
public class NumberGauge extends AbstractGaugeMetric<Number> {
/**
* Constructor
*
* @param name The name of this metric. This value may be used for display purposes.
*/
public LongGauge(String name) {
public NumberGauge(String name) {
super(name);
}
@ -23,14 +22,13 @@ public class LongGauge extends AbstractGaugeMetric<Long> {
* @param name The name of this metric. This value may be used for display purposes.
* @param initialValue The initial value for this {@link GaugeMetric}, may be null
*/
public LongGauge(String name, Long initialValue) {
public NumberGauge(String name, Number initialValue) {
super(name, initialValue);
}
@Override
public MetricType getType() {
return MetricType.GAUGE_LONG;
return MetricType.GAUGE_NUMBER;
}
}

View file

@ -6,7 +6,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.logstash.instrument.metrics.Metric;
import org.logstash.instrument.metrics.gauge.BooleanGauge;
import org.logstash.instrument.metrics.gauge.LongGauge;
import org.logstash.instrument.metrics.gauge.NumberGauge;
import org.logstash.instrument.metrics.gauge.TextGauge;
import java.io.IOException;
@ -19,10 +19,10 @@ final public class ConfigWitness implements SerializableWitness {
private final BooleanGauge deadLetterQueueEnabled;
private final BooleanGauge configReloadAutomatic;
private final LongGauge batchSize;
private final LongGauge workers;
private final LongGauge batchDelay;
private final LongGauge configReloadInterval;
private final NumberGauge batchSize;
private final NumberGauge workers;
private final NumberGauge batchDelay;
private final NumberGauge configReloadInterval;
private final TextGauge deadLetterQueuePath;
private final Snitch snitch;
private final static String KEY = "config";
@ -35,10 +35,10 @@ final public class ConfigWitness implements SerializableWitness {
public ConfigWitness() {
deadLetterQueueEnabled = new BooleanGauge("dead_letter_queue_enabled");
configReloadAutomatic = new BooleanGauge("config_reload_automatic");
batchSize = new LongGauge("batch_size");
workers = new LongGauge("workers");
batchDelay = new LongGauge("batch_delay");
configReloadInterval = new LongGauge("config_reload_interval");
batchSize = new NumberGauge("batch_size");
workers = new NumberGauge("workers");
batchDelay = new NumberGauge("batch_delay");
configReloadInterval = new NumberGauge("config_reload_interval");
deadLetterQueuePath = new TextGauge("dead_letter_queue_path");
snitch = new Snitch(this);
}
@ -151,14 +151,14 @@ final public class ConfigWitness implements SerializableWitness {
void innerSerialize(ConfigWitness witness, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeObjectFieldStart(KEY);
MetricSerializer<Metric<Long>> longSerializer = MetricSerializer.Get.longSerializer(gen);
MetricSerializer<Metric<Number>> numberSerializer = MetricSerializer.Get.numberSerializer(gen);
MetricSerializer<Metric<Boolean>> booleanSerializer = MetricSerializer.Get.booleanSerializer(gen);
MetricSerializer<Metric<String>> stringSerializer = MetricSerializer.Get.stringSerializer(gen);
longSerializer.serialize(witness.batchSize);
longSerializer.serialize(witness.workers);
longSerializer.serialize(witness.batchDelay);
longSerializer.serialize(witness.configReloadInterval);
numberSerializer.serialize(witness.batchSize);
numberSerializer.serialize(witness.workers);
numberSerializer.serialize(witness.batchDelay);
numberSerializer.serialize(witness.configReloadInterval);
booleanSerializer.serialize(witness.configReloadAutomatic);
booleanSerializer.serialize(witness.deadLetterQueueEnabled);
stringSerializer.serialize(witness.deadLetterQueuePath);
@ -182,7 +182,7 @@ final public class ConfigWitness implements SerializableWitness {
*
* @return the batch delay. May be {@code null}
*/
public Long batchDelay() {
public Number batchDelay() {
return witness.batchDelay.getValue();
}
@ -192,7 +192,7 @@ final public class ConfigWitness implements SerializableWitness {
*
* @return the batch size. May be {@code null}
*/
public Long batchSize() {
public Number batchSize() {
return witness.batchSize.getValue();
}
@ -211,7 +211,7 @@ final public class ConfigWitness implements SerializableWitness {
*
* @return the configured reload interval. May be {@code null}
*/
public Long configReloadInterval() {
public Number configReloadInterval() {
return witness.configReloadInterval.getValue();
}
@ -239,7 +239,7 @@ final public class ConfigWitness implements SerializableWitness {
*
* @return the configured number of workers. May be {@code null}
*/
public Long workers() {
public Number workers() {
return witness.workers.getValue();
}
}

View file

@ -5,7 +5,7 @@ import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.logstash.instrument.metrics.Metric;
import org.logstash.instrument.metrics.gauge.LongGauge;
import org.logstash.instrument.metrics.gauge.NumberGauge;
import java.io.IOException;
@ -18,13 +18,13 @@ public class DeadLetterQueueWitness implements SerializableWitness {
private static String KEY = "dead_letter_queue";
private static final Serializer SERIALIZER = new Serializer();
private final Snitch snitch;
private final LongGauge queueSizeInBytes;
private final NumberGauge queueSizeInBytes;
/**
* Constructor
*/
public DeadLetterQueueWitness() {
queueSizeInBytes = new LongGauge("queue_size_in_bytes");
queueSizeInBytes = new NumberGauge("queue_size_in_bytes");
snitch = new Snitch(this);
}
@ -82,8 +82,8 @@ public class DeadLetterQueueWitness implements SerializableWitness {
void innerSerialize(DeadLetterQueueWitness witness, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeObjectFieldStart(KEY);
MetricSerializer<Metric<Long>> longSerializer = MetricSerializer.Get.longSerializer(gen);
longSerializer.serialize(witness.queueSizeInBytes);
MetricSerializer<Metric<Number>> numberSerializer = MetricSerializer.Get.numberSerializer(gen);
numberSerializer.serialize(witness.queueSizeInBytes);
gen.writeEndObject();
}
}
@ -103,7 +103,7 @@ public class DeadLetterQueueWitness implements SerializableWitness {
*
* @return the queue size in bytes. May be {@code null}
*/
public Long queueSizeInBytes() {
public Number queueSizeInBytes() {
return witness.queueSizeInBytes.getValue();
}
}

View file

@ -25,9 +25,24 @@ public interface MetricSerializer<T extends Metric<?>> {
/**
* Helper class to create a functional fluent api.
* Usage example: {@code MetricSerializer.Get.longSerializer(gen).serialize(99);}
* Usage example: {@code MetricSerializer.Get.numberSerializer(gen).serialize(99);}
*/
class Get {
/**
* Proper way to serialize a {@link Number} type metric to JSON
*
* @param gen The {@link JsonGenerator} used to generate JSON
* @return the {@link MetricSerializer} which is the function used to serialize the metric
*/
static MetricSerializer<Metric<Number>> numberSerializer(JsonGenerator gen) {
return m -> {
if (m != null) {
Number value = m.getValue();
gen.writeObjectField(m.getName(), value == null ? 0 : value);
}
};
}
/**
* Proper way to serialize a {@link Long} type metric to JSON
*

View file

@ -4,10 +4,19 @@ import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.jruby.RubySymbol;
import org.logstash.instrument.metrics.Metric;
import org.logstash.instrument.metrics.counter.CounterMetric;
import org.logstash.instrument.metrics.counter.LongCounter;
import org.logstash.instrument.metrics.gauge.GaugeMetric;
import org.logstash.instrument.metrics.gauge.LazyDelegatingGauge;
import org.logstash.instrument.metrics.gauge.TextGauge;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Witness for a single plugin.
@ -16,9 +25,12 @@ import java.io.IOException;
public class PluginWitness implements SerializableWitness {
private final EventsWitness eventsWitness;
private final CustomWitness customWitness;
private final TextGauge id;
private final TextGauge name;
private final Snitch snitch;
private static final Serializer SERIALIZER = new Serializer();
/**
@ -28,6 +40,7 @@ public class PluginWitness implements SerializableWitness {
*/
public PluginWitness(String id) {
eventsWitness = new EventsWitness();
customWitness = new CustomWitness();
this.id = new TextGauge("id", id);
this.name = new TextGauge("name");
this.snitch = new Snitch(this);
@ -53,6 +66,15 @@ public class PluginWitness implements SerializableWitness {
return this;
}
/**
* Get a reference to the associated custom witness
*
* @return the {@link CustomWitness}
*/
public CustomWitness custom() {
return this.customWitness;
}
/**
* Get a reference to associated snitch to get discrete metric values.
*
@ -97,9 +119,169 @@ public class PluginWitness implements SerializableWitness {
void innerSerialize(PluginWitness witness, JsonGenerator gen, SerializerProvider provider) throws IOException {
MetricSerializer<Metric<String>> stringSerializer = MetricSerializer.Get.stringSerializer(gen);
MetricSerializer<Metric<Long>> longSerializer = MetricSerializer.Get.longSerializer(gen);
stringSerializer.serialize(witness.id);
witness.events().genJson(gen, provider);
stringSerializer.serialize(witness.name);
for (GaugeMetric<Object, Object> gauge : witness.customWitness.gauges.values()) {
gen.writeObjectField(gauge.getName(), gauge.getValue());
}
for (CounterMetric<Long> counter : witness.customWitness.counters.values()) {
longSerializer.serialize(counter);
}
}
}
/**
* A custom witness that we can hand off to plugin's to contribute to the metrics
*/
public class CustomWitness {
private final Snitch snitch;
/**
* private Constructor - not for external instantiation
*/
private CustomWitness() {
this.snitch = new Snitch(this);
}
private final Map<String, GaugeMetric<Object, Object>> gauges = new ConcurrentHashMap<>();
private final Map<String, CounterMetric<Long>> counters = new ConcurrentHashMap<>();
/**
* Set that gauge value
*
* @param key the {@link RubySymbol} for the key of this gauge. Note - internally this will be converted to a {@link String}
* @param value The value of the Gauge. This allows for any {@link Object} type, unless text or numeric type, there is no guarantees of proper serialization.
*/
public void gauge(RubySymbol key, Object value) {
gauge(key.asJavaString(), value);
}
/**
* Set that gauge value
*
* @param key the {@link String} for the key of this gauge. Note - internally this will be converted to a {@link String}
* @param value The value of the Gauge. This allows for any {@link Object} type, unless text or numeric type, there is no guarantees of proper serialization.
*/
public void gauge(String key, Object value) {
GaugeMetric<Object, Object> gauge = gauges.get(key);
if (gauge != null) {
gauge.set(value);
} else {
gauge = new LazyDelegatingGauge(key, value);
gauges.put(key, gauge);
}
}
/**
* Increments the underlying counter for this {@link RubySymbol} by 1.
*
* @param key the {@link RubySymbol} key of the counter to increment. Note - internally this will be converted to a {@link String}
*/
public void increment(RubySymbol key) {
increment(key.asJavaString());
}
/**
* Increments the underlying counter for this {@link RubySymbol} by 1.
*
* @param key the {@link String} key of the counter to increment. Note - internally this will be converted to a {@link String}
*/
public void increment(String key) {
increment(key, 1);
}
/**
* Increments the underlying counter for this {@link RubySymbol} by the given value.
*
* @param key the {@link RubySymbol} key of the counter to increment. Note - internally this will be converted to a {@link String}
* @param by the amount to increment by
*/
public void increment(RubySymbol key, long by) {
increment(key.asJavaString(), by);
}
/**
* Increments the underlying counter for this {@link RubySymbol} by the given value.
*
* @param key the {@link String} key of the counter to increment. Note - internally this will be converted to a {@link String}
* @param by the amount to increment by
*/
public void increment(String key, long by) {
CounterMetric<Long> counter = counters.get(key);
if (counter != null) {
counter.increment(by);
} else {
counter = new LongCounter(key);
counter.increment();
counters.put(key, counter);
}
}
/**
* Get a reference to associated snitch to get discrete metric values.
*
* @return the associate {@link Snitch}
*/
public Snitch snitch() {
return snitch;
}
/**
* Snitch for a plugin. Provides discrete metric values.
*/
public class Snitch {
private final CustomWitness witness;
/**
* Construtor
*
* @param witness the witness
*/
private Snitch(CustomWitness witness) {
this.witness = witness;
}
/**
* Get the underlying {@link GaugeMetric}. May call {@link GaugeMetric#getType()} to get the underlying type.
*
* @param key the key/name of the {@link GaugeMetric}.
* @return the {@link GaugeMetric} May return {@code null}
*/
public GaugeMetric gauge(String key) {
return witness.gauges.get(key);
}
/**
* Gets the full set of custom {@link GaugeMetric}
*
* @return the map of all of the {@link GaugeMetric}, keyed by the associated {@link GaugeMetric} key/name
*/
public Map<String, GaugeMetric<?, ?>> gauges() {
return Collections.unmodifiableMap(witness.gauges);
}
/**
* Get the custom Counter. May call {@link CounterMetric#getType()} to get the underlying type.
*
* @param key the key/name of the {@link CounterMetric}
* @return the {@link CounterMetric} for the given key. May return {@code null}
*/
public CounterMetric<?> counter(String key) {
return witness.counters.get(key);
}
/**
* Gets the full set of the custom {@link CounterMetric}
*
* @return the map of all of the {@link CounterMetric}, keyed by the associated {@link CounterMetric} key/name
*/
public Map<String, CounterMetric<?>> counters() {
return Collections.unmodifiableMap(witness.counters);
}
}
}

View file

@ -27,7 +27,6 @@ public class PluginsWitness implements SerializableWitness {
* Constructor.
*/
public PluginsWitness() {
this.inputs = new ConcurrentHashMap<>();
this.outputs = new ConcurrentHashMap<>();
this.filters = new ConcurrentHashMap<>();

View file

@ -5,7 +5,7 @@ import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.logstash.instrument.metrics.Metric;
import org.logstash.instrument.metrics.gauge.LongGauge;
import org.logstash.instrument.metrics.gauge.NumberGauge;
import org.logstash.instrument.metrics.gauge.TextGauge;
import java.io.IOException;
@ -17,7 +17,7 @@ import java.io.IOException;
final public class QueueWitness implements SerializableWitness {
private final TextGauge type;
private final LongGauge events; // note this is NOT an EventsWitness
private final NumberGauge events; // note this is NOT an EventsWitness
private final Snitch snitch;
private final CapacityWitness capacity;
private final DataWitness data;
@ -29,7 +29,7 @@ final public class QueueWitness implements SerializableWitness {
*/
public QueueWitness() {
type = new TextGauge("type");
events = new LongGauge("events");
events = new NumberGauge("events");
snitch = new Snitch(this);
capacity = new CapacityWitness();
data = new DataWitness();
@ -90,19 +90,19 @@ final public class QueueWitness implements SerializableWitness {
*/
public class CapacityWitness {
private final LongGauge queueSizeInBytes;
private final LongGauge pageCapacityInBytes;
private final LongGauge maxQueueSizeInBytes;
private final LongGauge maxUnreadEvents;
private final NumberGauge queueSizeInBytes;
private final NumberGauge pageCapacityInBytes;
private final NumberGauge maxQueueSizeInBytes;
private final NumberGauge maxUnreadEvents;
private final Snitch snitch;
private final static String KEY = "capacity";
private CapacityWitness() {
queueSizeInBytes = new LongGauge("queue_size_in_bytes");
pageCapacityInBytes = new LongGauge("page_capacity_in_bytes");
maxQueueSizeInBytes = new LongGauge("max_queue_size_in_bytes");
maxUnreadEvents = new LongGauge("max_unread_events");
queueSizeInBytes = new NumberGauge("queue_size_in_bytes");
pageCapacityInBytes = new NumberGauge("page_capacity_in_bytes");
maxQueueSizeInBytes = new NumberGauge("max_queue_size_in_bytes");
maxUnreadEvents = new NumberGauge("max_unread_events");
snitch = new Snitch(this);
}
@ -167,7 +167,7 @@ final public class QueueWitness implements SerializableWitness {
*
* @return the queue size in bytes. May be {@code null}
*/
public Long queueSizeInBytes() {
public Number queueSizeInBytes() {
return witness.queueSizeInBytes.getValue();
}
@ -176,7 +176,7 @@ final public class QueueWitness implements SerializableWitness {
*
* @return the page queue capacity.
*/
public Long pageCapacityInBytes() {
public Number pageCapacityInBytes() {
return witness.pageCapacityInBytes.getValue();
}
@ -185,7 +185,7 @@ final public class QueueWitness implements SerializableWitness {
*
* @return the max queue size.
*/
public Long maxQueueSizeInBytes() {
public Number maxQueueSizeInBytes() {
return witness.maxQueueSizeInBytes.getValue();
}
@ -194,7 +194,7 @@ final public class QueueWitness implements SerializableWitness {
*
* @return the max unread events.
*/
public Long maxUnreadEvents() {
public Number maxUnreadEvents() {
return witness.maxUnreadEvents.getValue();
}
@ -207,7 +207,7 @@ final public class QueueWitness implements SerializableWitness {
public class DataWitness {
private final TextGauge path;
private final LongGauge freeSpaceInBytes;
private final NumberGauge freeSpaceInBytes;
private final TextGauge storageType;
private final Snitch snitch;
private final static String KEY = "data";
@ -215,7 +215,7 @@ final public class QueueWitness implements SerializableWitness {
private DataWitness() {
path = new TextGauge("path");
freeSpaceInBytes = new LongGauge("free_space_in_bytes");
freeSpaceInBytes = new NumberGauge("free_space_in_bytes");
storageType = new TextGauge("storage_type");
snitch = new Snitch(this);
}
@ -281,7 +281,7 @@ final public class QueueWitness implements SerializableWitness {
*
* @return the free space of the queue
*/
public Long freeSpaceInBytes() {
public Number freeSpaceInBytes() {
return witness.freeSpaceInBytes.getValue();
}
@ -326,22 +326,22 @@ final public class QueueWitness implements SerializableWitness {
void innerSerialize(QueueWitness witness, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeObjectFieldStart(KEY);
MetricSerializer<Metric<Long>> longSerializer = MetricSerializer.Get.longSerializer(gen);
MetricSerializer<Metric<Number>> numberSerializer = MetricSerializer.Get.numberSerializer(gen);
MetricSerializer<Metric<String>> stringSerializer = MetricSerializer.Get.stringSerializer(gen);
stringSerializer.serialize(witness.type);
if ("persisted".equals(witness.type.getValue())) {
longSerializer.serialize(witness.events);
numberSerializer.serialize(witness.events);
//capacity
gen.writeObjectFieldStart(CapacityWitness.KEY);
longSerializer.serialize(witness.capacity.queueSizeInBytes);
longSerializer.serialize(witness.capacity.pageCapacityInBytes);
longSerializer.serialize(witness.capacity.maxQueueSizeInBytes);
longSerializer.serialize(witness.capacity.maxUnreadEvents);
numberSerializer.serialize(witness.capacity.queueSizeInBytes);
numberSerializer.serialize(witness.capacity.pageCapacityInBytes);
numberSerializer.serialize(witness.capacity.maxQueueSizeInBytes);
numberSerializer.serialize(witness.capacity.maxUnreadEvents);
gen.writeEndObject();
//data
gen.writeObjectFieldStart(DataWitness.KEY);
stringSerializer.serialize(witness.data.path);
longSerializer.serialize(witness.data.freeSpaceInBytes);
numberSerializer.serialize(witness.data.freeSpaceInBytes);
stringSerializer.serialize(witness.data.storageType);
gen.writeEndObject();
}
@ -375,7 +375,7 @@ final public class QueueWitness implements SerializableWitness {
*
* @return the count of events in the queue. {@code null}
*/
public Long events() {
public Number events() {
return witness.events.getValue();
}
}

View file

@ -24,8 +24,7 @@ public class MetricTypeTest {
nameMap.put(MetricType.COUNTER_LONG, "counter/long");
nameMap.put(MetricType.GAUGE_TEXT, "gauge/text");
nameMap.put(MetricType.GAUGE_BOOLEAN, "gauge/boolean");
nameMap.put(MetricType.GAUGE_LONG, "gauge/long");
nameMap.put(MetricType.GAUGE_DOUBLE, "gauge/double");
nameMap.put(MetricType.GAUGE_NUMBER, "gauge/number");
nameMap.put(MetricType.GAUGE_UNKNOWN, "gauge/unknown");
nameMap.put(MetricType.GAUGE_RUBYHASH, "gauge/rubyhash");
nameMap.put(MetricType.GAUGE_RUBYTIMESTAMP, "gauge/rubytimestamp");

View file

@ -8,7 +8,6 @@ import java.util.Collections;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests for {@link LongCounter}
*/

View file

@ -1,33 +0,0 @@
package org.logstash.instrument.metrics.gauge;
import org.junit.Test;
import org.logstash.instrument.metrics.MetricType;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests for {@link DoubleGauge}
*/
public class DoubleGaugeTest {
@Test
public void getValue() {
DoubleGauge gauge = new DoubleGauge("bar", 123.0);
assertThat(gauge.getValue()).isEqualTo(123.0);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_DOUBLE);
//Null
gauge = new DoubleGauge("bar");
assertThat(gauge.getValue()).isNull();
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_DOUBLE);
}
@Test
public void set() {
DoubleGauge gauge = new DoubleGauge("bar");
assertThat(gauge.getValue()).isNull();
gauge.set(123.0);
assertThat(gauge.getValue()).isEqualTo(123.0);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_DOUBLE);
}
}

View file

@ -42,43 +42,43 @@ public class LazyDelegatingGaugeTest {
@Test
public void getValue() {
//Long
LazyDelegatingGauge gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar", 99l);
LazyDelegatingGauge gauge = new LazyDelegatingGauge("bar", 99l);
assertThat(gauge.getValue()).isEqualTo(99l);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LONG);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_NUMBER);
//Double
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar", 99.0);
gauge = new LazyDelegatingGauge("bar", 99.0);
assertThat(gauge.getValue()).isEqualTo(99.0);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_DOUBLE);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_NUMBER);
//Boolean
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar", true);
gauge = new LazyDelegatingGauge("bar", true);
assertThat(gauge.getValue()).isEqualTo(true);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_BOOLEAN);
//Text
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar", "something");
gauge = new LazyDelegatingGauge("bar", "something");
assertThat(gauge.getValue()).isEqualTo("something");
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_TEXT);
//Ruby Hash
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar", rubyHash);
gauge = new LazyDelegatingGauge("bar", rubyHash);
assertThat(gauge.getValue().toString()).isEqualTo(RUBY_HASH_AS_STRING);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_RUBYHASH);
//Ruby Timestamp
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar", rubyTimestamp);
gauge = new LazyDelegatingGauge("bar", rubyTimestamp);
assertThat(gauge.getValue()).isEqualTo(timestamp);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_RUBYTIMESTAMP);
//Unknown
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar", Collections.singleton("value"));
gauge = new LazyDelegatingGauge("bar", Collections.singleton("value"));
assertThat(gauge.getValue()).isEqualTo(Collections.singleton("value"));
assertThat(gauge.getValue()).isEqualTo(gauge.get());
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_UNKNOWN);
//Null
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar");
gauge = new LazyDelegatingGauge("bar");
assertThat(gauge.getValue()).isNull();
assertThat(gauge.get()).isNull();
assertThat(gauge.getType()).isNull();
@ -87,23 +87,31 @@ public class LazyDelegatingGaugeTest {
@Test
public void set() {
//Long
LazyDelegatingGauge gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar");
LazyDelegatingGauge gauge = new LazyDelegatingGauge("bar");
gauge.set(99l);
assertThat(gauge.getValue()).isEqualTo(99l);
gauge.set(199l);
assertThat(gauge.getValue()).isEqualTo(199l);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LONG);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_NUMBER);
//Integer
gauge = new LazyDelegatingGauge("bar");
gauge.set(99);
assertThat(gauge.getValue()).isEqualTo(99);
gauge.set(199);
assertThat(gauge.getValue()).isEqualTo(199);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_NUMBER);
//Double
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar");
gauge = new LazyDelegatingGauge("bar");
gauge.set(99.0);
assertThat(gauge.getValue()).isEqualTo(99.0);
gauge.set(199.01);
assertThat(gauge.getValue()).isEqualTo(199.01);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_DOUBLE);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_NUMBER);
//Boolean
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar");
gauge = new LazyDelegatingGauge("bar");
gauge.set(true);
assertThat(gauge.getValue()).isEqualTo(true);
gauge.set(false);
@ -111,7 +119,7 @@ public class LazyDelegatingGaugeTest {
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_BOOLEAN);
//Text
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar");
gauge = new LazyDelegatingGauge("bar");
gauge.set("something");
assertThat(gauge.getValue()).isEqualTo("something");
gauge.set("something else");
@ -119,19 +127,19 @@ public class LazyDelegatingGaugeTest {
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_TEXT);
//Ruby Hash
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar");
gauge = new LazyDelegatingGauge("bar");
gauge.set(rubyHash);
assertThat(gauge.getValue().toString()).isEqualTo(RUBY_HASH_AS_STRING);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_RUBYHASH);
//Ruby Timestamp
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar");
gauge = new LazyDelegatingGauge("bar");
gauge.set(rubyTimestamp);
assertThat(gauge.getValue()).isEqualTo(timestamp);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_RUBYTIMESTAMP);
//Unknown
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar");
gauge = new LazyDelegatingGauge("bar");
gauge.set(Collections.singleton("value"));
assertThat(gauge.getValue()).isEqualTo(Collections.singleton("value"));
gauge.set(URI.create("foo")); //please don't change the type of gauge after already set
@ -139,13 +147,13 @@ public class LazyDelegatingGaugeTest {
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_UNKNOWN);
//Null
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar");
gauge = new LazyDelegatingGauge("bar");
gauge.set(null);
assertThat(gauge.getValue()).isNull();
assertThat(gauge.getType()).isNull();
//Valid, then Null
gauge = new LazyDelegatingGauge(Collections.singletonList("foo"), "bar");
gauge = new LazyDelegatingGauge("bar");
gauge.set("something");
assertThat(gauge.getValue()).isEqualTo("something");
gauge.set(null);

View file

@ -1,34 +0,0 @@
package org.logstash.instrument.metrics.gauge;
import org.junit.Test;
import org.logstash.instrument.metrics.MetricType;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests for {@link LongGauge}
*/
public class LongGaugeTest {
@Test
public void getValue() {
LongGauge gauge = new LongGauge("bar", 99l);
assertThat(gauge.getValue()).isEqualTo(99);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LONG);
//Null
gauge = new LongGauge("bar");
assertThat(gauge.getValue()).isNull();
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LONG);
}
@Test
public void set() {
LongGauge gauge = new LongGauge("bar");
assertThat(gauge.getValue()).isNull();
gauge.set(123l);
assertThat(gauge.getValue()).isEqualTo(123);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LONG);
}
}

View file

@ -0,0 +1,37 @@
package org.logstash.instrument.metrics.gauge;
import org.junit.Test;
import org.logstash.instrument.metrics.MetricType;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests for {@link NumberGauge}
*/
public class NumberGaugeTest {
@Test
public void getValue() {
NumberGauge gauge = new NumberGauge("bar", 99l);
assertThat(gauge.getValue()).isEqualTo(99l);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_NUMBER);
//other number type
gauge.set(98.00);
assertThat(gauge.getValue()).isEqualTo(98.00);
//Null
gauge = new NumberGauge("bar");
assertThat(gauge.getValue()).isNull();
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_NUMBER);
}
@Test
public void set() {
NumberGauge gauge = new NumberGauge("bar");
assertThat(gauge.getValue()).isNull();
gauge.set(123l);
assertThat(gauge.getValue()).isEqualTo(123l);
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_NUMBER);
}
}

View file

@ -23,14 +23,14 @@ public class ConfigWitnessTest {
public void testBatchDelay() {
assertThat(witness.snitch().batchDelay()).isNull();
witness.batchDelay(99);
assertThat(witness.snitch().batchDelay()).isEqualTo(99);
assertThat(witness.snitch().batchDelay()).isEqualTo(99l);
}
@Test
public void testBatchSize() {
assertThat(witness.snitch().batchSize()).isNull();
witness.batchSize(98);
assertThat(witness.snitch().batchSize()).isEqualTo(98);
assertThat(witness.snitch().batchSize()).isEqualTo(98l);
}
@Test
@ -46,7 +46,7 @@ public class ConfigWitnessTest {
public void testConfigReloadInterval() {
assertThat(witness.snitch().configReloadInterval()).isNull();
witness.configReloadInterval(97);
assertThat(witness.snitch().configReloadInterval()).isEqualTo(97);
assertThat(witness.snitch().configReloadInterval()).isEqualTo(97l);
}
@Test
@ -69,7 +69,7 @@ public class ConfigWitnessTest {
public void testWorkers() {
assertThat(witness.snitch().workers()).isNull();
witness.workers(96);
assertThat(witness.snitch().workers()).isEqualTo(96);
assertThat(witness.snitch().workers()).isEqualTo(96l);
}
@Test

View file

@ -23,7 +23,7 @@ public class DeadLetterQueueWitnessTest {
public void queueSizeInBytes() {
assertThat(witness.snitch().queueSizeInBytes()).isNull();
witness.queueSizeInBytes(99);
assertThat(witness.snitch().queueSizeInBytes()).isEqualTo(99);
assertThat(witness.snitch().queueSizeInBytes()).isEqualTo(99l);
}
@Test

View file

@ -3,7 +3,6 @@ package org.logstash.instrument.witness;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import org.logstash.instrument.metrics.gauge.LongGauge;
import static org.assertj.core.api.Assertions.assertThat;

View file

@ -2,8 +2,16 @@ package org.logstash.instrument.witness;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jruby.RubySymbol;
import org.junit.Before;
import org.junit.Test;
import org.logstash.RubyUtil;
import org.logstash.instrument.metrics.MetricType;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
@ -26,6 +34,60 @@ public class PluginWitnessTest {
assertThat(witness.snitch().name()).isEqualTo("abc");
}
@Test
public void testCustomGauge() {
witness.custom().gauge("a", "foo");
witness.custom().gauge("b", 1);
witness.custom().gauge("c", true);
witness.custom().gauge("d", URI.create("unknown"));
assertThat(witness.custom().snitch().gauges().size()).isEqualTo(4);
assertThat(witness.custom().snitch().gauge("a").getValue()).isEqualTo("foo");
assertThat(witness.custom().snitch().gauge("a").getType()).isEqualTo(MetricType.GAUGE_TEXT);
assertThat(witness.custom().snitch().gauge("b").getValue()).isEqualTo(1);
assertThat(witness.custom().snitch().gauge("b").getType()).isEqualTo(MetricType.GAUGE_NUMBER);
assertThat(witness.custom().snitch().gauge("c").getValue()).isEqualTo(Boolean.TRUE);
assertThat(witness.custom().snitch().gauge("c").getType()).isEqualTo(MetricType.GAUGE_BOOLEAN);
assertThat(witness.custom().snitch().gauge("d").getValue()).isEqualTo(URI.create("unknown"));
assertThat(witness.custom().snitch().gauge("d").getType()).isEqualTo(MetricType.GAUGE_UNKNOWN);
}
@Test
public void testCustomCounter(){
witness.custom().increment("foo");
witness.custom().increment("bar");
assertThat(witness.custom().snitch().counters().size()).isEqualTo(2);
assertThat(witness.custom().snitch().counters().values().stream().allMatch(v -> MetricType.COUNTER_LONG.equals(v.getType()))).isTrue();
assertThat(witness.custom().snitch().counter("foo").getValue()).isEqualTo(1l);
assertThat(witness.custom().snitch().counter("bar").getValue()).isEqualTo(1l);
witness.custom().increment("foo");
witness.custom().increment("foo");
witness.custom().increment("bar");
assertThat(witness.custom().snitch().counter("foo").getValue()).isEqualTo(3l);
assertThat(witness.custom().snitch().counter("bar").getValue()).isEqualTo(2l);
}
@Test
public void testRubySymbol() throws IOException {
RubySymbol symbol = RubySymbol.newSymbol(RubyUtil.RUBY, "mysymbol");
witness.custom().increment(symbol);
witness.custom().increment(symbol, 99);
assertThat(witness.custom().snitch().counter("mysymbol").getValue()).isEqualTo(100l);
witness.custom().gauge(symbol, "blah");
assertThat(witness.custom().snitch().gauge("mysymbol").getValue()).isEqualTo("blah");
witness.custom().gauge(symbol, "blah2");
assertThat(witness.custom().snitch().gauge("mysymbol").getValue()).isEqualTo("blah2");
}
@Test
public void testCustomNotSet(){
assertThat(witness.custom().snitch().counter("nothing")).isNull();
assertThat(witness.custom().snitch().gauge("nothing")).isNull();
assertThat(witness.custom().snitch().gauges()).isEmpty();
assertThat(witness.custom().snitch().counters()).isEmpty();
}
@Test
public void testEvents() {
assertThat(witness.events()).isNotNull();
@ -56,4 +118,52 @@ public class PluginWitnessTest {
String json = witness.asJson();
assertThat(json).isEqualTo("{\"id\":\"123\",\"events\":{\"duration_in_millis\":0,\"in\":1,\"out\":0,\"filtered\":0,\"queue_push_duration_in_millis\":0},\"name\":null}");
}
@Test
public void testSerializationCustomCounter() throws Exception {
witness.custom().increment("a");
witness.custom().increment("a");
witness.custom().increment("b");
String json = witness.asJson();
assertThat(json).isEqualTo("{\"id\":\"123\",\"events\":{\"duration_in_millis\":0,\"in\":0,\"out\":0,\"filtered\":0,\"queue_push_duration_in_millis\":0},\"name\":null," +
"\"a\":2,\"b\":1}");
}
@Test
public void testSerializationCustomGauge() throws Exception {
witness.custom().gauge("a", "foo");
witness.custom().gauge("b", 1);
witness.custom().gauge("c", true);
String json = witness.asJson();
assertThat(json).isEqualTo("{\"id\":\"123\",\"events\":{\"duration_in_millis\":0,\"in\":0,\"out\":0,\"filtered\":0,\"queue_push_duration_in_millis\":0},\"name\":null," +
"\"a\":\"foo\",\"b\":1,\"c\":true}");
}
@Test
public void testSerializationCustomGaugeNumericTypes() throws Exception {
short a = 1;
int b = 1;
float c = 1;
double d = 1;
BigDecimal e = new BigDecimal(1);
witness.custom().gauge("a", a);
witness.custom().gauge("b", b);
witness.custom().gauge("c", c);
witness.custom().gauge("d", d);
witness.custom().gauge("e", e);
String json = witness.asJson();
assertThat(json).isEqualTo("{\"id\":\"123\",\"events\":{\"duration_in_millis\":0,\"in\":0,\"out\":0,\"filtered\":0,\"queue_push_duration_in_millis\":0},\"name\":null," +
"\"a\":1,\"b\":1,\"c\":1.0,\"d\":1.0,\"e\":1}");
}
@Test(expected = IllegalStateException.class)
public void testSerializationUnknownCustomGauge() throws Exception {
//There are not default Jackson serializers for UUID
witness.custom().gauge("a", UUID.randomUUID());
witness.asJson();
}
}

View file

@ -1,6 +1,5 @@
package org.logstash.instrument.witness;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
@ -29,31 +28,31 @@ public class QueueWitnessTest {
public void testEvents() {
assertThat(witness.snitch().events()).isNull();
witness.events(101);
assertThat(witness.snitch().events()).isEqualTo(101);
assertThat(witness.snitch().events()).isEqualTo(101l);
}
@Test
public void testQueueSizeInBytes(){
witness.capacity().queueSizeInBytes(99);
assertThat(witness.capacity().snitch().queueSizeInBytes()).isEqualTo(99);
assertThat(witness.capacity().snitch().queueSizeInBytes()).isEqualTo(99l);
}
@Test
public void testPageCapacityInBytes(){
witness.capacity().pageCapacityInBytes(98);
assertThat(witness.capacity().snitch().pageCapacityInBytes()).isEqualTo(98);
assertThat(witness.capacity().snitch().pageCapacityInBytes()).isEqualTo(98l);
}
@Test
public void testMaxQueueSizeInBytes(){
witness.capacity().maxQueueSizeInBytes(97);
assertThat(witness.capacity().snitch().maxQueueSizeInBytes()).isEqualTo(97);
assertThat(witness.capacity().snitch().maxQueueSizeInBytes()).isEqualTo(97l);
}
@Test
public void testMaxUnreadEvents(){
witness.capacity().maxUnreadEvents(96);
assertThat(witness.capacity().snitch().maxUnreadEvents()).isEqualTo(96);
assertThat(witness.capacity().snitch().maxUnreadEvents()).isEqualTo(96l);
}
@Test
@ -65,7 +64,7 @@ public class QueueWitnessTest {
@Test
public void testFreeSpace(){
witness.data().freeSpaceInBytes(77);
assertThat(witness.data().snitch().freeSpaceInBytes()).isEqualTo(77);
assertThat(witness.data().snitch().freeSpaceInBytes()).isEqualTo(77l);
}
@Test