diff options
Diffstat (limited to 'simplemetrics/src/main/java/com')
24 files changed, 0 insertions, 2246 deletions
diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Bucket.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/Bucket.java deleted file mode 100644 index b75a0529a03..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Bucket.java +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import java.util.AbstractMap.SimpleImmutableEntry; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Logger; - -import com.yahoo.collections.LazyMap; -import com.yahoo.collections.LazySet; -import java.util.logging.Level; - -/** - * An aggregation of data which is only written to from a single thread. - * - * @author Steinar Knutsen - */ -public class Bucket { - - private static final Logger log = Logger.getLogger(Bucket.class.getName()); - private final Map<Identifier, UntypedMetric> values = LazyMap.newHashMap(); - - boolean gotTimeStamps; - long fromMillis; - long toMillis; - - public Bucket() { - this.gotTimeStamps = false; - this.fromMillis = 0; - this.toMillis = 0; - } - - public Bucket(long fromMillis, long toMillis) { - this.gotTimeStamps = true; - this.fromMillis = fromMillis; - this.toMillis = toMillis; - } - - public Set<Map.Entry<Identifier, UntypedMetric>> entrySet() { - return values.entrySet(); - } - - void put(Sample x) { - UntypedMetric value = get(x); - Measurement m = x.getMeasurement(); - switch (x.getMetricType()) { - case GAUGE: - value.put(m.getMagnitude()); - break; - case COUNTER: - value.add(m.getMagnitude()); - break; - default: - throw new IllegalArgumentException("Unsupported metric type: " + x.getMetricType()); - } - } - - void put(Identifier id, UntypedMetric value) { - values.put(id, value); - } - - boolean hasIdentifier(Identifier id) { - return values.containsKey(id); - } - - void merge(Bucket other, boolean otherIsNewer) { - LazySet<String> malformedMetrics = LazySet.newHashSet(); - for (Map.Entry<Identifier, UntypedMetric> entry : other.values.entrySet()) { - String metricName = entry.getKey().getName(); - try { - if (!malformedMetrics.contains(metricName)) { - get(entry.getKey(), entry.getValue()).merge(entry.getValue(), otherIsNewer); - } - } catch (IllegalArgumentException e) { - log.log(Level.WARNING, "Problems merging metric " + metricName + ", possibly ignoring data."); - // avoid spamming the log if there are a lot of mismatching - // threads - malformedMetrics.add(metricName); - } - } - } - - void merge(Bucket other) { - boolean otherIsNewer = resolveTimeStamps(other); - merge(other, otherIsNewer); - } - - private boolean resolveTimeStamps(Bucket other) { - boolean otherIsNewer = other.fromMillis > this.fromMillis; - if (! gotTimeStamps) { - fromMillis = other.fromMillis; - toMillis = other.toMillis; - gotTimeStamps = other.gotTimeStamps; - } else if (other.gotTimeStamps) { - fromMillis = Math.min(fromMillis, other.fromMillis); - toMillis = Math.max(toMillis, other.toMillis); - } - return otherIsNewer; - } - - private UntypedMetric get(Sample sample) { - Identifier dim = sample.getIdentifier(); - UntypedMetric v = values.get(dim); - - if (v == null) { - // please keep inside guard, as sample.getHistogramDefinition(String) touches a volatile - v = new UntypedMetric(sample.getHistogramDefinition(dim.getName())); - values.put(dim, v); - } - return v; - } - - private UntypedMetric get(Identifier dim, UntypedMetric other) { - UntypedMetric v = values.get(dim); - - if (v == null) { - v = new UntypedMetric(other.getMetricDefinition()); - values.put(dim, v); - } - return v; - } - - public Collection<String> getAllMetricNames() { - Set<String> names = new HashSet<>(); - for (Identifier id : values.keySet()) { - names.add(id.getName()); - } - return names; - } - - public Collection<Map.Entry<Point, UntypedMetric>> getValuesForMetric(String metricName) { - List<Map.Entry<Point, UntypedMetric>> singleMetric = new ArrayList<>(); - for (Map.Entry<Identifier, UntypedMetric> entry : values.entrySet()) { - if (metricName.equals(entry.getKey().getName())) { - singleMetric.add(locationValuePair(entry)); - } - } - return singleMetric; - } - - public Map<Point, UntypedMetric> getMapForMetric(String metricName) { - Map<Point, UntypedMetric> result = new HashMap<>(); - for (Map.Entry<Identifier, UntypedMetric> entry : values.entrySet()) { - if (metricName.equals(entry.getKey().getName())) { - result.put(entry.getKey().getLocation(), entry.getValue()); - } - } - return result; - } - - public Map<String, List<Map.Entry<Point, UntypedMetric>>> getValuesByMetricName() { - Map<String, List<Map.Entry<Point, UntypedMetric>>> result = new HashMap<>(); - for (Map.Entry<Identifier, UntypedMetric> entry : values.entrySet()) { - List<Map.Entry<Point, UntypedMetric>> singleMetric; - if (result.containsKey(entry.getKey().getName())) { - singleMetric = result.get(entry.getKey().getName()); - } else { - singleMetric = new ArrayList<>(); - result.put(entry.getKey().getName(), singleMetric); - } - singleMetric.add(locationValuePair(entry)); - } - return result; - } - - private SimpleImmutableEntry<Point, UntypedMetric> locationValuePair(Map.Entry<Identifier, UntypedMetric> entry) { - return new SimpleImmutableEntry<>(entry.getKey().getLocation(), entry.getValue()); - } - - @Override - public String toString() { - return "Bucket [values=" + (values != null ? toString(values.entrySet(), 3) : null) + "]"; - } - - private String toString(Collection<?> collection, int maxLen) { - StringBuilder builder = new StringBuilder(); - builder.append("["); - int i = 0; - for (Iterator<?> iterator = collection.iterator(); iterator.hasNext() && i < maxLen; i++) { - if (i > 0) { - builder.append(", "); - } - builder.append(iterator.next()); - } - builder.append("]"); - return builder.toString(); - } - - /** - * This bucket contains data newer than approximately this point in time. - */ - public long getFromMillis() { - return fromMillis; - } - - /** - * This bucket contains data older than approximately this point in time. - */ - public long getToMillis() { - return toMillis; - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Counter.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/Counter.java deleted file mode 100644 index 21cdbd3c219..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Counter.java +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import com.google.common.annotations.Beta; -import com.yahoo.metrics.simple.UntypedMetric.AssumedType; - -/** - * A counter metric. Create a counter by declaring it with - * {@link MetricReceiver#declareCounter(String)} or - * {@link MetricReceiver#declareCounter(String, Point)}. - * - * @author steinar - */ -@Beta -public class Counter { - private final Point defaultPosition; - private final String name; - private final MetricReceiver metricReceiver; - - Counter(String name, Point defaultPosition, MetricReceiver receiver) { - this.name = name; - this.defaultPosition = defaultPosition; - this.metricReceiver = receiver; - } - - /** - * Increase the dimension-less/zero-point value of this counter by 1. - */ - public void add() { - add(1L, defaultPosition); - } - - /** - * Add to the dimension-less/zero-point value of this counter. - * - * @param n the amount by which to increase this counter - */ - public void add(long n) { - add(n, defaultPosition); - } - - /** - * Increase this metric at the given point by 1. - * - * @param p the point in the metric space at which to increase this metric by 1 - */ - public void add(Point p) { - add(1L, p); - } - - /** - * Add to this metric at the given point. - * - * @param n - * the amount by which to increase this counter - * @param p - * the point in the metric space at which to add to the metric - */ - public void add(long n, Point p) { - metricReceiver.update(new Sample(new Measurement(Long.valueOf(n)), new Identifier(name, p), AssumedType.COUNTER)); - } - - /** - * Create a PointBuilder with default dimension values as given when this - * counter was declared. - * - * @return a PointBuilder reflecting the default dimension values of this - * counter - */ - public PointBuilder builder() { - return new PointBuilder(defaultPosition); - } -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/DimensionCache.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/DimensionCache.java deleted file mode 100644 index 8893a88d94c..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/DimensionCache.java +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * The persistence layer for metrics. Both CPU and memory hungry, but - * it runs in its own little world. - * - * @author Steinar Knutsen - */ -class DimensionCache { - - private static class TimeStampedMetric { - public final long millis; - public final UntypedMetric metric; - public TimeStampedMetric(long millis, UntypedMetric metric) { - this.millis = millis; - this.metric = metric; - } - } - - private final Map<String, LinkedHashMap<Point, TimeStampedMetric>> persistentData = new HashMap<>(); - private final int pointsToKeep; - - public DimensionCache(int pointsToKeep) { - this.pointsToKeep = pointsToKeep; - } - - void updateDimensionPersistence(Bucket toDelete, Bucket toPresent) { - updatePersistentData(toDelete); - padPresentation(toPresent); - } - - private void padPresentation(Bucket toPresent) { - Map<String, List<Entry<Point, UntypedMetric>>> currentMetricNames = toPresent.getValuesByMetricName(); - - for (Map.Entry<String, List<Entry<Point, UntypedMetric>>> metric : currentMetricNames.entrySet()) { - final int currentDataPoints = metric.getValue().size(); - if (currentDataPoints < pointsToKeep) { - padMetric(metric.getKey(), toPresent, currentDataPoints); - } - } - Set<String> keysMissingFromPresentation = new HashSet<>(persistentData.keySet()); - keysMissingFromPresentation.removeAll(currentMetricNames.keySet()); - for (String cachedMetric : keysMissingFromPresentation) { - padMetric(cachedMetric, toPresent, 0); - } - } - - private void updatePersistentData(Bucket toDelete) { - if (toDelete == null) { - return; - } - long millis = toDelete.gotTimeStamps ? toDelete.toMillis : System.currentTimeMillis(); - for (Map.Entry<String, List<Entry<Point, UntypedMetric>>> metric : toDelete.getValuesByMetricName().entrySet()) { - LinkedHashMap<Point, TimeStampedMetric> cachedPoints = getCachedMetric(metric.getKey()); - - for (Entry<Point, UntypedMetric> newestInterval : metric.getValue()) { - // overwriting an existing entry does not update the order - // in the map - cachedPoints.remove(newestInterval.getKey()); - TimeStampedMetric toInsert = new TimeStampedMetric(millis, newestInterval.getValue()); - cachedPoints.put(newestInterval.getKey(), toInsert); - } - } - } - - private static final long MAX_AGE_MILLIS = 4 * 3600 * 1000; - - private void padMetric(String metric, Bucket toPresent, int currentDataPoints) { - LinkedHashMap<Point, TimeStampedMetric> cachedPoints = getCachedMetric(metric); - int toAdd = pointsToKeep - currentDataPoints; - @SuppressWarnings({"unchecked","rawtypes"}) - Entry<Point, TimeStampedMetric>[] cachedEntries = cachedPoints.entrySet().toArray(new Entry[0]); - long nowMillis = System.currentTimeMillis(); - for (int i = cachedEntries.length - 1; i >= 0 && toAdd > 0; --i) { - Entry<Point, TimeStampedMetric> leastOld = cachedEntries[i]; - if (leastOld.getValue().millis + MAX_AGE_MILLIS < nowMillis) { - continue; - } - Identifier id = new Identifier(metric, leastOld.getKey()); - if ( ! toPresent.hasIdentifier(id)) { - toPresent.put(id, leastOld.getValue().metric.pruneData()); - --toAdd; - } - } - } - - @SuppressWarnings("serial") - private LinkedHashMap<Point, TimeStampedMetric> getCachedMetric(String metricName) { - LinkedHashMap<Point, TimeStampedMetric> points = persistentData.get(metricName); - if (points == null) { - points = new LinkedHashMap<>(16, 0.75f, false) { - protected @Override boolean removeEldestEntry(Map.Entry<Point, TimeStampedMetric> eldest) { - return size() > pointsToKeep; - } - }; - persistentData.put(metricName, points); - } - return points; - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Gauge.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/Gauge.java deleted file mode 100644 index 1edefd0ae5a..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Gauge.java +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import com.google.common.annotations.Beta; -import com.yahoo.metrics.simple.UntypedMetric.AssumedType; - -/** - * A gauge metric, i.e. a bucket of arbitrary sample values. Create a gauge - * metric by declaring it with {@link MetricReceiver#declareGauge(String)} or - * {@link MetricReceiver#declareGauge(String, Point)}. - * - * @author steinar - */ -@Beta -public class Gauge { - - private final Point defaultPosition; - private final String name; - private final MetricReceiver receiver; - - Gauge(String name, Point defaultPosition, MetricReceiver receiver) { - this.name = name; - this.defaultPosition = defaultPosition; - this.receiver = receiver; - } - - /** - * Record a sample with default or no position. - * - * @param x - * sample value - */ - public void sample(double x) { - sample(x, defaultPosition); - } - - /** - * Record a sample at the given position. - * - * @param x - * sample value - * @param p - * position/dimension values for the sample - */ - public void sample(double x, Point p) { - receiver.update(new Sample(new Measurement(Double.valueOf(x)), new Identifier(name, p), AssumedType.GAUGE)); - } - - /** - * Create a PointBuilder with the default dimension values reflecting those - * given when this gauge was declared. - * - * @return a builder initialized with defaults from this metric instance - */ - public PointBuilder builder() { - return new PointBuilder(defaultPosition); - } -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Identifier.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/Identifier.java deleted file mode 100644 index 4d0f470534a..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Identifier.java +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -/** - * The name of the metric and its n-dimensional position. Basically a pair of a - * Point and a metric name. Written to be robust against null input as the API - * gives very little guidance, converting null to empty string/point. Immutable. - * - * @author Steinar Knutsen - */ -public class Identifier { - - private final String name; - private final Point location; - - public Identifier(String name, Point location) { - this.name = (name == null ? "" : name); - this.location = (location == null ? Point.emptyPoint() : location); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + location.hashCode(); - result = prime * result + name.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - Identifier other = (Identifier) obj; - if (!location.equals(other.location)) { - return false; - } - if (!name.equals(other.name)) { - return false; - } - return true; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("Identifier [name=").append(name).append(", location=").append(location).append("]"); - return builder.toString(); - } - - public String getName() { - return name; - } - - public Point getLocation() { - return location; - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Measurement.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/Measurement.java deleted file mode 100644 index 4098ac1bdea..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Measurement.java +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -/** - * Wrapper class for the actually measured value. - * - * @author Steinar Knutsen - */ -public class Measurement { - - private final Number magnitude; - - public Measurement(Number magnitude) { - this.magnitude = magnitude; - } - - Number getMagnitude() { - return magnitude; - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricAggregator.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricAggregator.java deleted file mode 100644 index 7168eb49676..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricAggregator.java +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - -import com.yahoo.concurrent.ThreadLocalDirectory; -import com.yahoo.metrics.ManagerConfig; - -/** - * Worker thread to collect the data stored in worker threads and build - * snapshots for external consumption. Using the correct executor gives the - * necessary guarantees for this being invoked from only a single thread. - * - * @author Steinar Knutsen - */ -class MetricAggregator implements Runnable { - - private final ThreadLocalDirectory<Bucket, Sample> metricsCollection; - private final AtomicReference<Bucket> currentSnapshot; - private int generation = 0; - private final Bucket[] buffer; - private long fromMillis; - private final DimensionCache dimensions; - - MetricAggregator(ThreadLocalDirectory<Bucket, Sample> metricsCollection, AtomicReference<Bucket> currentSnapshot, - ManagerConfig settings) { - if (settings.reportPeriodSeconds() < 10) { - throw new IllegalArgumentException("Do not use this metrics implementation" + - " if report periods of less than 10 seconds is desired."); - } - buffer = new Bucket[settings.reportPeriodSeconds()]; - dimensions = new DimensionCache(settings.pointsToKeepPerMetric()); - fromMillis = System.currentTimeMillis(); - this.metricsCollection = metricsCollection; - this.currentSnapshot = currentSnapshot; - } - - @Override - public void run() { - Bucket toDelete = updateBuffer(); - createSnapshot(toDelete); - } - - private void createSnapshot(Bucket toDelete) { - Bucket toPresent = new Bucket(); - for (Bucket b : buffer) { - if (b == null) { - continue; - } - toPresent.merge(b); - } - dimensions.updateDimensionPersistence(toDelete, toPresent); - currentSnapshot.set(toPresent); - } - - private Bucket updateBuffer() { - List<Bucket> buckets = metricsCollection.fetch(); - long toMillis = System.currentTimeMillis(); - int bucketIndex = generation++ % buffer.length; - Bucket bucketToDelete = buffer[bucketIndex]; - Bucket latest = new Bucket(fromMillis, toMillis); - for (Bucket b : buckets) { - latest.merge(b, true); - } - buffer[bucketIndex] = latest; - this.fromMillis = toMillis; - return bucketToDelete; - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricManager.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricManager.java deleted file mode 100644 index 1956783b4c0..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricManager.java +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.logging.Logger; - -import com.yahoo.component.AbstractComponent; -import com.yahoo.concurrent.ThreadLocalDirectory; -import com.yahoo.concurrent.ThreadLocalDirectory.Updater; -import com.yahoo.container.di.componentgraph.Provider; -import com.yahoo.metrics.ManagerConfig; -import java.util.logging.Level; - -/** - * This is the coordinating class owning the executor and the top level objects - * for measured metrics. - * - * @author Steinar Knutsen - */ -public class MetricManager extends AbstractComponent implements Provider<MetricReceiver> { - - private static Logger log = Logger.getLogger(MetricManager.class.getName()); - - private final ScheduledThreadPoolExecutor executor; - private final MetricReceiver receiver; - private ThreadLocalDirectory<Bucket, Sample> metricsCollection; - - public MetricManager(ManagerConfig settings) { - this(settings, new MetricUpdater()); - } - - private MetricManager(ManagerConfig settings, Updater<Bucket, Sample> updater) { - log.log(Level.CONFIG, "setting up simple metrics gathering." + - " reportPeriodSeconds=" + settings.reportPeriodSeconds() + - ", pointsToKeepPerMetric=" + settings.pointsToKeepPerMetric()); - metricsCollection = new ThreadLocalDirectory<>(updater); - final AtomicReference<Bucket> currentSnapshot = new AtomicReference<>(null); - executor = new ScheduledThreadPoolExecutor(1); - // Fixed rate, not fixed delay, is it is not too important that each - // bucket has data for exactly one second, but one should strive for - // this.buffer to contain data for as close a period to the report - // interval as possible - executor.scheduleAtFixedRate(new MetricAggregator(metricsCollection, currentSnapshot, settings), 1, 1, TimeUnit.SECONDS); - receiver = new MetricReceiver(metricsCollection, currentSnapshot); - } - - static MetricManager constructWithCustomUpdater(ManagerConfig settings, Updater<Bucket, Sample> updater) { - return new MetricManager(settings, updater); - } - - - @Override - public void deconstruct() { - executor.shutdown(); - } - - @Override - public MetricReceiver get() { - return receiver; - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricReceiver.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricReceiver.java deleted file mode 100644 index e0e3469e257..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricReceiver.java +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicReference; - -import com.google.common.annotations.Beta; -import com.google.common.collect.ImmutableMap; -import com.yahoo.concurrent.ThreadLocalDirectory; - -/** - * The reception point for measurements. This is the class users should inject - * in constructors for declaring instances of {@link Counter} and {@link Gauge} - * for the actual measurement of metrics. - * - * @author Steinar Knutsen - */ -@Beta -public class MetricReceiver { - - public static final MetricReceiver nullImplementation = new NullReceiver(); - private final ThreadLocalDirectory<Bucket, Sample> metricsCollection; - private final AtomicReference<Bucket> currentSnapshot; - - // metricSettings is volatile for reading, the lock is for updates - private final Object histogramDefinitionsLock = new Object(); - private volatile Map<String, MetricSettings> metricSettings; - - private static final class NullCounter extends Counter { - - NullCounter() { - super(null, null, null); - } - - @Override - public void add() { - } - - @Override - public void add(long n) { - } - - @Override - public void add(Point p) { - } - - @Override - public void add(long n, Point p) { - } - - @Override - public PointBuilder builder() { - return super.builder(); - } - } - - private static final class NullGauge extends Gauge { - NullGauge() { - super(null, null, null); - } - - @Override - public void sample(double x) { - } - - @Override - public void sample(double x, Point p) { - } - - @Override - public PointBuilder builder() { - return super.builder(); - } - - } - - public static final class MockReceiver extends MetricReceiver { - - private final ThreadLocalDirectory<Bucket, Sample> collection; - - private MockReceiver(ThreadLocalDirectory<Bucket, Sample> collection) { - super(collection, null); - this.collection = collection; - } - - public MockReceiver() { - this(new ThreadLocalDirectory<>(new MetricUpdater())); - } - - /** Gathers all data since last snapshot */ - public Bucket getSnapshot() { - final Bucket merged = new Bucket(); - for (Bucket b : collection.fetch()) { - merged.merge(b, true); - } - return merged; - } - - /** Utility method for testing */ - public Point point(String dim, String val) { - return pointBuilder().set(dim, val).build(); - } - - } - - private static final class NullReceiver extends MetricReceiver { - - NullReceiver() { - super(null, null); - } - - @Override - public void update(Sample s) { - } - - @Override - public Counter declareCounter(String name) { - return new NullCounter(); - } - - @Override - public Counter declareCounter(String name, Point boundDimensions) { - return new NullCounter(); - } - - @Override - public Gauge declareGauge(String name) { - return new NullGauge(); - } - - @Override - public Gauge declareGauge(String name, Point boundDimensions) { - return new NullGauge(); - } - - @Override - public Gauge declareGauge(String name, Optional<Point> boundDimensions, MetricSettings customSettings) { - return null; - } - - @Override - public PointBuilder pointBuilder() { - return null; - } - - @Override - public Bucket getSnapshot() { - return null; - } - - @Override - void addMetricDefinition(String metricName, MetricSettings definition) { - } - - @Override - MetricSettings getMetricDefinition(String metricName) { - return null; - } - } - - public MetricReceiver(ThreadLocalDirectory<Bucket, Sample> metricsCollection, AtomicReference<Bucket> currentSnapshot) { - this.metricsCollection = metricsCollection; - this.currentSnapshot = currentSnapshot; - metricSettings = new ImmutableMap.Builder<String, MetricSettings>().build(); - } - - /** - * Update a metric. This API is not intended for clients for the - * simplemetrics API, declare a Counter or a Gauge using - * {@link #declareCounter(String)}, {@link #declareCounter(String, Point)}, - * {@link #declareGauge(String)}, or {@link #declareGauge(String, Point)} - * instead. - * - * @param sample a single simple containing all meta data necessary to update a metric - */ - public void update(Sample sample) { - // pass around the receiver instead of histogram settings to avoid reading any volatile if unnecessary - sample.setReceiver(this); - metricsCollection.update(sample); - } - - /** - * Declare a counter metric without setting any default position. - * - * @param name the name of the metric - * @return a thread-safe counter - */ - public Counter declareCounter(String name) { - return declareCounter(name, null); - } - - /** - * Declare a counter metric, with default dimension values as given. Create - * the point argument by using a builder from {@link #pointBuilder()}. - * - * @param name the name of the metric - * @param boundDimensions dimensions which have a fixed value in the life cycle of the metric object or null - * @return a thread-safe counter with given default values - */ - public Counter declareCounter(String name, Point boundDimensions) { - return new Counter(name, boundDimensions, this); - } - - /** - * Declare a gauge metric with any default position. - * - * @param name the name of the metric - * @return a thread-safe gauge instance - */ - public Gauge declareGauge(String name) { - return declareGauge(name, null); - } - - /** - * Declare a gauge metric, with default dimension values as given. Create - * the point argument by using a builder from {@link #pointBuilder()}. - * - * @param name the name of the metric - * @param boundDimensions dimensions which have a fixed value in the life cycle of the metric object or null - * @return a thread-safe gauge metric - */ - public Gauge declareGauge(String name, Point boundDimensions) { - return declareGauge(name, Optional.ofNullable(boundDimensions), null); - } - - /** - * Declare a gauge metric, with default dimension values as given. Create - * the point argument by using a builder from {@link #pointBuilder()}. - * MetricSettings instances are built using - * {@link MetricSettings.Builder}. - * - * @param name the name of the metric - * @param boundDimensions an optional of dimensions which have a fixed value in the life cycle of the metric object - * @param customSettings any optional settings - * @return a thread-safe gauge metric - */ - public Gauge declareGauge(String name, Optional<Point> boundDimensions, MetricSettings customSettings) { - if (customSettings != null) { - addMetricDefinition(name, customSettings); - } - Point defaultDimensions = null; - if (boundDimensions.isPresent()) { - defaultDimensions = boundDimensions.get(); - } - return new Gauge(name, defaultDimensions, this); - } - - /** - * Create a PointBuilder instance with no default settings. PointBuilder - * instances are not thread-safe. - * - * @return an "empty" point builder instance - */ - public PointBuilder pointBuilder() { - return new PointBuilder(); - } - - /** - * Fetch the latest metric values, aggregated over all threads for the - * configured sample history (by default five minutes). The values will be - * less than 1 second old, and this method has only a memory barrier as side - * effect. - * - * @return the latest five minutes of metrics - */ - public Bucket getSnapshot() { - return currentSnapshot.get(); - } - - /** - * Add how to build a histogram for a given metric. - * - * @param metricName the metric where samples should be put in a histogram - * @param definition settings for a histogram - */ - void addMetricDefinition(String metricName, MetricSettings definition) { - synchronized (histogramDefinitionsLock) { - // read the volatile _after_ acquiring the lock - Map<String, MetricSettings> oldMetricDefinitions = metricSettings; - Map<String, MetricSettings> builderMap = new HashMap<>(oldMetricDefinitions.size() + 1); - builderMap.putAll(oldMetricDefinitions); - builderMap.put(metricName, definition); - metricSettings = ImmutableMap.copyOf(builderMap); - } - } - - /** - * Get how to build a histogram for a given metric, or null if no histogram should be created. - * - * @param metricName the name of an arbitrary metric - * @return the corresponding histogram definition or null - */ - MetricSettings getMetricDefinition(String metricName) { - return metricSettings.get(metricName); - } -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricSettings.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricSettings.java deleted file mode 100644 index 924e311015b..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricSettings.java +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import com.google.common.annotations.Beta; - -/** - * All information needed for creating any extra data structures associated with - * a single metric, outside of its basic type. - * - * @author steinar - */ -@Beta -public final class MetricSettings { - - /** - * A builder for the immutable MetricSettings instances. - */ - @Beta - public static final class Builder { - private boolean histogram = false; - - /** - * Create a new builder for a MetricSettings instance with default - * settings. - */ - public Builder() { - } - - /** - * Set whether a resulting metric should have a histogram. Default is - * false. - * - * @param histogram - * whether to generate a histogram - * @return this, to facilitate chaining - */ - public Builder histogram(boolean histogram) { - this.histogram = histogram; - return this; - } - - /** - * Build a fresh MetricSettings instance. - * - * @return a MetricSettings instance containing the values set in this - * builder - */ - public MetricSettings build() { - return new MetricSettings(histogram); - } - } - - private final int significantDigits; // could have been static, but would - // just introduce bugs when we must - // expose this setting - private final boolean histogram; - - private MetricSettings(boolean histogram) { - this.histogram = histogram; - this.significantDigits = 2; - } - - int getSignificantdigits() { - return significantDigits; - } - - boolean isHistogram() { - return histogram; - } -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricUpdater.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricUpdater.java deleted file mode 100644 index 848132c9bea..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/MetricUpdater.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import com.yahoo.concurrent.ThreadLocalDirectory.Updater; - -/** - * The link between each single thread and the central data store. - * - * @author Steinar Knutsen - */ -class MetricUpdater implements Updater<Bucket, Sample> { - - @Override - public Bucket createGenerationInstance(Bucket previous) { - return new Bucket(); - } - - @Override - public Bucket update(Bucket current, Sample x) { - current.put(x); - return current; - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Point.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/Point.java deleted file mode 100644 index 672d05c1874..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Point.java +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import com.google.common.annotations.Beta; -import com.google.common.collect.ImmutableList; -import com.yahoo.collections.Tuple2; -import com.yahoo.jdisc.Metric.Context; - -/** - * An efficiently comparable point in a sparse vector space. - * - * @author steinar - */ -@Beta -public final class Point implements Context { - - private final Value[] location; - private final String[] dimensions; - - public Point(Map<String, ?> properties) { - this(buildParameters(properties)); - } - - private Point(Tuple2<String[], Value[]> dimensionsAndLocation) { - this(dimensionsAndLocation.first, dimensionsAndLocation.second); - } - - /** - * Only to be used by simplemetrics itself. - * - * @param dimensions dimension name, Point takes ownership of the array - * @param location dimension values, Point takes ownership of the array - */ - Point(String[] dimensions, Value[] location) { - this.dimensions = dimensions; - this.location = location; - } - - private static final Point theEmptyPoint = new Point(new String[0], new Value[0]); - - /** the canonical 0-dimensional Point. */ - public static Point emptyPoint() { return theEmptyPoint; } - - private static Tuple2<String[], Value[]> buildParameters(Map<String, ?> properties) { - String[] dimensions = properties.keySet().toArray(new String[0]); - Arrays.sort(dimensions); - Value[] location = new Value[dimensions.length]; - for (int i = 0; i < dimensions.length; ++i) { - location[i] = Value.of(String.valueOf(properties.get(dimensions[i]))); - } - return new Tuple2<>(dimensions, location); - - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Point other = (Point) obj; - if (!Arrays.equals(dimensions, other.dimensions)) { - return false; - } - if (!Arrays.equals(location, other.location)) { - return false; - } - return true; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Arrays.hashCode(dimensions); - result = prime * result + Arrays.hashCode(location); - return result; - } - - @Override - public String toString() { - final int maxLen = 3; - StringBuilder builder = new StringBuilder(); - builder.append("Point [location=") - .append(Arrays.asList(location).subList(0, Math.min(location.length, maxLen))) - .append(", dimensions=") - .append(Arrays.asList(dimensions).subList(0, Math.min(dimensions.length, maxLen))) - .append("]"); - return builder.toString(); - } - - /** - * Get an immutable list view of the values for each dimension. - */ - public List<Value> location() { - return ImmutableList.copyOf(location); - } - - /** - * Get an immutable list view of the names of each dimension. - */ - public List<String> dimensions() { - return ImmutableList.copyOf(dimensions); - } - - /** - * Get the number of dimensions defined for this Point, i.e. the size of the - * collection returned by {@link #dimensions()}. - */ - public int dimensionality() { - return dimensions.length; - } - - /** package private accessor only for simplemetrics itself */ - String[] getDimensions() { - return dimensions; - } - - /** package private accessor only for simplemetrics itself */ - Value[] getLocation() { - return location; - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/PointBuilder.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/PointBuilder.java deleted file mode 100644 index f613aab26a2..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/PointBuilder.java +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import java.util.ArrayList; -import java.util.Collections; - -import com.google.common.annotations.Beta; - -/** - * Single-use builder for the immutable Point instances used to set dimensions - * for a metric. Get a fresh instance either from a corresponding Gauge or Counter, - * or through the MetricReceiver API. - * - * @author steinar - */ -@Beta -public final class PointBuilder { - private ArrayList<String> dimensions; - private ArrayList<Value> location; - - public enum Discriminator { - LONG, DOUBLE, STRING; - } - - PointBuilder() { - this(null); - } - - PointBuilder(Point p) { - dimensions = new ArrayList<>(); - location = new ArrayList<>(); - if (p != null) { - int size = p.dimensionality(); - dimensions = new ArrayList<>(size+2); - location = new ArrayList<>(size+2); - for (String dimensionName : p.getDimensions()) { - dimensions.add(dimensionName); - } - for (Value dimensionValue : p.getLocation()) { - location.add(dimensionValue); - } - } else { - dimensions = new ArrayList<>(4); - location = new ArrayList<>(4); - } - } - - /** - * Set a named dimension to an integer value. - * - * @param dimensionName the name of the dimension to set - * @param dimensionValue to value for the given dimension - * @return this, to facilitate chaining - */ - public PointBuilder set(String dimensionName, long dimensionValue) { - return set(dimensionName, Value.of(dimensionValue)); - } - - /** - * Set a named dimension to a floating point value. - * - * @param dimensionName the name of the dimension to set - * @param dimensionValue to value for the given dimension - * @return this, to facilitate chaining - */ - public PointBuilder set(String dimensionName, double dimensionValue) { - return set(dimensionName, Value.of(dimensionValue)); - } - - /** - * Set a named dimension to a string value. - * - * @param dimensionName the name of the dimension to set - * @param dimensionValue to value for the given dimension - * @return this, to facilitate chaining - */ - public PointBuilder set(String dimensionName, String dimensionValue) { - return set(dimensionName, Value.of(dimensionValue)); - } - - private PointBuilder set(String axisName, Value w) { - // handle setting same axis multiple times nicely - int i = Collections.binarySearch(dimensions, axisName); - if (i < 0) { - dimensions.add(~i, axisName); - location.add(~i, w); - } else { - // only set location, dim obviously exists - location.set(i, w); - } - return this; - } - - /** - * Create a new Point instance using the settings stored in this - * PointBuilder. PointBuilder instances cannot be re-used after build() has - * been invoked. - * - * @return a Point instance reflecting this builder - */ - public Point build() { - Point p = Point.emptyPoint(); - int size = dimensions.size(); - if (size != 0) { - p = new Point(dimensions.toArray(new String[size]), location.toArray(new Value[size])); - } - // deny builder re-use - dimensions = null; - location = null; - return p; - } - - @Override - public String toString() { - final int maxLen = 3; - StringBuilder builder = new StringBuilder(); - builder.append("PointBuilder [dimensions=") - .append(dimensions != null ? dimensions.subList(0, Math.min(dimensions.size(), maxLen)) : null) - .append(", location=").append(location != null ? location.subList(0, Math.min(location.size(), maxLen)) : null) - .append("]"); - return builder.toString(); - } -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Sample.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/Sample.java deleted file mode 100644 index 0d2144deeb4..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Sample.java +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import com.yahoo.metrics.simple.UntypedMetric.AssumedType; - -/** - * A single metric measurement and all the meta data needed to route it - * correctly. - * - * @author Steinar Knutsen - */ -public class Sample { - - private final Identifier identifier; - private final Measurement measurement; - private final AssumedType metricType; - private MetricReceiver metricReceiver = null; - - public Sample(Measurement measurement, Identifier id, AssumedType t) { - this.identifier = id; - this.measurement = measurement; - this.metricType = t; - } - - Identifier getIdentifier() { - return identifier; - } - - Measurement getMeasurement() { - return measurement; - } - - AssumedType getMetricType() { - return metricType; - } - - void setReceiver(MetricReceiver metricReceiver) { - this.metricReceiver = metricReceiver; - } - - /** - * Get histogram definition for an arbitrary metric. Caveat emptor: This - * involves reading a volatile. - * - * @param metricName name of the metric to get histogram definition for - * @return how to define a new histogram or null - */ - MetricSettings getHistogramDefinition(String metricName) { - if (metricReceiver == null) { - return null; - } else { - return metricReceiver.getMetricDefinition(metricName); - } - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/UnitTestSetup.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/UnitTestSetup.java deleted file mode 100644 index e6856ee2970..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/UnitTestSetup.java +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import com.yahoo.metrics.ManagerConfig; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * Common code for running unit tests of simplemetrics - * - * @author ean - */ -public class UnitTestSetup { - - MetricManager metricManager; - MetricReceiver receiver; - ObservableUpdater updater; - - static class ObservableUpdater extends MetricUpdater { - CountDownLatch gotData = new CountDownLatch(1); - private volatile boolean hasBeenAccessed = false; - - @Override - public Bucket createGenerationInstance(Bucket previous) { - if (hasBeenAccessed) { - gotData.countDown(); - } - return super.createGenerationInstance(previous); - } - - @Override - public Bucket update(Bucket current, Sample x) { - hasBeenAccessed = true; - return super.update(current, x); - } - } - - void init() { - updater = new ObservableUpdater(); - metricManager = MetricManager.constructWithCustomUpdater(new ManagerConfig(new ManagerConfig.Builder()), updater); - receiver = metricManager.get(); - } - - void fini() { - receiver = null; - metricManager.deconstruct(); - metricManager = null; - updater = null; - } - - public Bucket getUpdatedSnapshot() throws InterruptedException { - updater.gotData.await(10, TimeUnit.SECONDS); - Bucket s = receiver.getSnapshot(); - long startedWaitingForSnapshot = System.currentTimeMillis(); - // just waiting for the correct snapshot being constructed (yes, this is - // necessary) - while (s == null || s.entrySet().size() == 0) { - if (System.currentTimeMillis() - startedWaitingForSnapshot > (10L * 1000L)) { - throw new RuntimeException("Test timed out."); - } - Thread.sleep(10); - s = receiver.getSnapshot(); - } - return s; - } - - public MetricReceiver getReceiver() { - return receiver; - } -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/UntypedMetric.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/UntypedMetric.java deleted file mode 100644 index f757ab15022..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/UntypedMetric.java +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -import java.util.logging.Logger; - -import org.HdrHistogram.DoubleHistogram; - -import java.util.logging.Level; - -/** - * A gauge or a counter or... who knows? The class for storing a metric when the - * metric has not been declared. - * - * @author Steinar Knutsen - */ -public class UntypedMetric { - - private static final Logger log = Logger.getLogger(UntypedMetric.class.getName()); - - private long count = 0L; - private double current = 0.0d; - private double max; - private double min; - private double sum; - private AssumedType outputFormat = AssumedType.NONE; - private final DoubleHistogram histogram; - private final MetricSettings metricSettings; - - public enum AssumedType { NONE, GAUGE, COUNTER }; - - UntypedMetric(MetricSettings metricSettings) { - this.metricSettings = metricSettings; - if (metricSettings == null || !metricSettings.isHistogram()) { - histogram = null; - } else { - histogram = new DoubleHistogram(metricSettings.getSignificantdigits()); - } - } - - void add(Number x) { - outputFormat = AssumedType.COUNTER; - count += x.longValue(); - } - - void put(Number x) { - outputFormat = AssumedType.GAUGE; - current = x.doubleValue(); - if (histogram != null) { - histogram.recordValue(current); - } - if (count > 0) { - max = Math.max(current, max); - min = Math.min(current, min); - sum += current; - } else { - max = current; - min = current; - sum = current; - } - ++count; - } - - UntypedMetric pruneData() { - UntypedMetric pruned = new UntypedMetric(null); - pruned.outputFormat = this.outputFormat; - pruned.current = this.current; - return pruned; - } - - void merge(UntypedMetric other, boolean otherIsNewer) throws IllegalArgumentException { - if (outputFormat == AssumedType.NONE) { - outputFormat = other.outputFormat; - } - if (outputFormat != other.outputFormat) { - throw new IllegalArgumentException("Mismatching output formats: " + outputFormat + " and " + other.outputFormat + "."); - } - if (count > 0) { - if (other.count > 0) { - max = Math.max(other.max, max); - min = Math.min(other.min, min); - if (otherIsNewer) { - current = other.current; - } - } - } else { - max = other.max; - min = other.min; - current = other.current; - } - count += other.count; - sum += other.sum; - if (histogram != null) { - // some config scenarios may lead to differing histogram settings, - // so doing this defensively - if (other.histogram != null) { - try { - histogram.add(other.histogram); - } catch (ArrayIndexOutOfBoundsException e) { - log.log(Level.WARNING, "Had trouble merging histograms: " + e.getMessage()); - } - } - } - } - - public boolean isCounter() { return outputFormat == AssumedType.COUNTER; } - - public long getCount() { return count; } - public double getLast() { return current; } - public double getMax() { return max; } - public double getMin() { return min; } - public double getSum() { return sum; } - - MetricSettings getMetricDefinition() { - return metricSettings; - } - - public DoubleHistogram getHistogram() { - return histogram; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append(this.getClass().getName()).append(": "); - buf.append("outputFormat=").append(outputFormat).append(", "); - if (count > 0 && outputFormat == AssumedType.GAUGE) { - buf.append("max=").append(max).append(", "); - buf.append("min=").append(min).append(", "); - buf.append("sum=").append(sum).append(", "); - } - if (histogram != null) { - buf.append("histogram=").append(histogram).append(", "); - } - if (metricSettings != null) { - buf.append("metricSettings=").append(metricSettings).append(", "); - } - buf.append("current=").append(current).append(", "); - buf.append("count=").append(count); - return buf.toString(); - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Value.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/Value.java deleted file mode 100644 index fd4113a5e22..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/Value.java +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple; - -/** - * Wrapper for dimension values. - * - * @author steinar - */ -public abstract class Value { - private static final String UNSUPPORTED_VALUE_TYPE = "Unsupported value type."; - - /** - * Marker for the type of the contained value of a Value instance. - */ - public enum Discriminator { - LONG, DOUBLE, STRING; - } - - /** - * Get the long wrapped by a Value if one exists. - * - * @throws UnsupportedOperationException if LONG is not returned by {{@link #getType()}. - */ - public long longValue() throws UnsupportedOperationException { - throw new UnsupportedOperationException(UNSUPPORTED_VALUE_TYPE); - } - - /** - * Get the double wrapped by a Value if one exists. - * - * @throws UnsupportedOperationException if DOUBLE is not returned by {{@link #getType()}. - */ - public double doubleValue() throws UnsupportedOperationException { - throw new UnsupportedOperationException(UNSUPPORTED_VALUE_TYPE); - } - - /** - * Get the string wrapped by a Value if one exists. - * - * @throws UnsupportedOperationException if STRING is not returned by {{@link #getType()}. - */ - public String stringValue() throws UnsupportedOperationException { - throw new UnsupportedOperationException(UNSUPPORTED_VALUE_TYPE); - } - - /** - * Show the (single) supported standard type representation of a Value instance. - */ - public abstract Discriminator getType(); - - private static class LongValue extends Value { - private final long value; - - LongValue(long value) { - this.value = value; - } - - @Override - public long longValue() { - return value; - } - - @Override - public Discriminator getType() { - return Discriminator.LONG; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (int) (value ^ (value >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - LongValue other = (LongValue) obj; - if (value != other.value) { - return false; - } - return true; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("LongValue [value=").append(value).append("]"); - return builder.toString(); - } - } - - private static class DoubleValue extends Value { - private final double value; - - DoubleValue(double value) { - this.value = value; - } - - @Override - public double doubleValue() { - return value; - } - - @Override - public Discriminator getType() { - return Discriminator.DOUBLE; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(value); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - DoubleValue other = (DoubleValue) obj; - if (Double.doubleToLongBits(value) != Double.doubleToLongBits(other.value)) { - return false; - } - return true; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("DoubleValue [value=").append(value).append("]"); - return builder.toString(); - } - } - - private static class StringValue extends Value { - private final String value; - - StringValue(String value) { - this.value = value; - } - - @Override - public String stringValue() { - return value; - } - - @Override - public Discriminator getType() { - return Discriminator.STRING; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((value == null) ? 0 : value.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - StringValue other = (StringValue) obj; - if (value == null) { - if (other.value != null) { - return false; - } - } else if (!value.equals(other.value)) { - return false; - } - return true; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("StringValue [value=").append(value).append("]"); - return builder.toString(); - } - } - - /** - * Helper method to wrap a long as a Value. The instance returned may or may - * not be unique. - * - * @param value - * the value to wrap - * @return an immutable wrapper - */ - public static Value of(long value) { - return new LongValue(value); - } - - /** - * Helper method to wrap a double as a Value. The instance returned may or - * may not be unique. - * - * @param value - * the value to wrap - * @return an immutable wrapper - * */ - public static Value of(double value) { - return new DoubleValue(value); - } - - /** - * Helper method to wrap a string as a Value. The instance returned may or - * may not be unique. - * - * @param value - * the value to wrap - * @return an immutable wrapper - */ - public static Value of(String value) { - return new StringValue(value); - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/JdiscMetricsFactory.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/JdiscMetricsFactory.java deleted file mode 100644 index 30102c43919..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/JdiscMetricsFactory.java +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple.jdisc; - -import java.io.PrintStream; -import java.util.logging.Logger; - -import com.yahoo.container.jdisc.MetricConsumerFactory; -import com.yahoo.container.jdisc.state.MetricSnapshot; -import com.yahoo.container.jdisc.state.SnapshotProvider; -import com.yahoo.jdisc.application.MetricConsumer; -import com.yahoo.metrics.simple.Bucket; -import com.yahoo.metrics.simple.MetricReceiver; - -/** - * A factory for all the JDisc API classes. - * - * @author Steinar Knutsen - */ -public class JdiscMetricsFactory implements MetricConsumerFactory, SnapshotProvider { - - private static final Logger log = Logger.getLogger(JdiscMetricsFactory.class.getName()); - private final SimpleMetricConsumer metricInstance; - private final MetricReceiver metricReceiver; - - public JdiscMetricsFactory(MetricReceiver receiver) { - this.metricReceiver = receiver; - this.metricInstance = new SimpleMetricConsumer(receiver); - } - - @Override - public MetricConsumer newInstance() { - // the underlying implementation is thread safe anyway to allow for stand-alone use - return metricInstance; - } - - - @Override - public MetricSnapshot latestSnapshot() { - Bucket curr = metricReceiver.getSnapshot(); - if (curr == null) { - log.warning("no snapshot from instance of " + metricReceiver.getClass()); - return null; - } else { - SnapshotConverter converter = new SnapshotConverter(curr); - return converter.convert(); - } - } - - @Override - public void histogram(PrintStream output) { - Bucket curr = metricReceiver.getSnapshot(); - if (curr == null) { - log.warning("no snapshot from instance of " + metricReceiver.getClass()); - } else { - SnapshotConverter converter = new SnapshotConverter(curr); - converter.outputHistograms(output); - } - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/SimpleMetricConsumer.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/SimpleMetricConsumer.java deleted file mode 100644 index ee5f18e78d3..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/SimpleMetricConsumer.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple.jdisc; - -import java.util.HashMap; -import java.util.Map; - -import com.yahoo.jdisc.Metric.Context; -import com.yahoo.jdisc.application.MetricConsumer; -import com.yahoo.metrics.simple.Identifier; -import com.yahoo.metrics.simple.Measurement; -import com.yahoo.metrics.simple.Point; -import com.yahoo.metrics.simple.MetricReceiver; -import com.yahoo.metrics.simple.Sample; -import com.yahoo.metrics.simple.UntypedMetric.AssumedType; - -/** - * The single user facing part of the JDisc interfaces of simple metrics. - * - * @author Steinar Knutsen - */ -public class SimpleMetricConsumer implements MetricConsumer { - - private final MetricReceiver receiver; - - public SimpleMetricConsumer(MetricReceiver receiver) { - this.receiver = receiver; - } - - @Override - public void set(String key, Number val, Context ctx) { - receiver.update(new Sample(new Measurement(val), new Identifier(key, getSimpleCoordinate(ctx)), AssumedType.GAUGE)); - } - - @Override - public void add(String key, Number val, Context ctx) { - receiver.update(new Sample(new Measurement(val), new Identifier(key, getSimpleCoordinate(ctx)), AssumedType.COUNTER)); - } - - private Point getSimpleCoordinate(Context ctx) { - if (ctx instanceof Point) { - return (Point) ctx; - } else { - return null; - } - } - - @Override - public Context createContext(Map<String, ?> properties) { - if (properties == null) - properties = new HashMap<>(); - return new Point(properties); - } - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/SnapshotConverter.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/SnapshotConverter.java deleted file mode 100644 index 495062e38f8..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/SnapshotConverter.java +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple.jdisc; - -import java.io.PrintStream; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; - -import org.HdrHistogram.DoubleHistogram; - -import com.yahoo.collections.Tuple2; -import com.yahoo.container.jdisc.state.*; -import com.yahoo.metrics.simple.Bucket; -import com.yahoo.metrics.simple.Identifier; -import com.yahoo.metrics.simple.Point; -import com.yahoo.metrics.simple.UntypedMetric; -import com.yahoo.metrics.simple.Value; -import com.yahoo.text.JSON; - -/** - * Convert simple metrics snapshots into jdisc state snapshots. - * - * @author arnej27959 - */ -class SnapshotConverter { - - private static Logger log = Logger.getLogger(SnapshotConverter.class.getName()); - - final Bucket snapshot; - final Map<Point, Map<String, MetricValue>> perPointData = new HashMap<>(); - private static final char[] DIGITS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - - public SnapshotConverter(Bucket snapshot) { - this.snapshot = snapshot; - } - - static MetricDimensions convert(Point p) { - if (p == null) { - return StateMetricContext.newInstance(null); - } - List<String> dimensions = p.dimensions(); - List<Value> location = p.location(); - Map<String, Object> pointWrapper = new HashMap<>(dimensions.size()); - for (int i = 0; i < dimensions.size(); ++i) { - pointWrapper.put(dimensions.get(i), valueAsString(location.get(i))); - } - return StateMetricContext.newInstance(pointWrapper); - } - - // TODO: just a compatibility wrapper, should be removed ASAP - private static Object valueAsString(Value value) { - switch (value.getType()) { - case STRING: - return value.stringValue(); - case LONG: - return value.longValue(); - case DOUBLE: - return value.doubleValue(); - default: - throw new IllegalStateException("simplemetrics impl is out of sync with itself, please file a ticket."); - } - } - - static MetricValue convert(UntypedMetric val) { - if (val.isCounter()) { - return CountMetric.newInstance(val.getCount()); - } else { - if (val.getHistogram() == null) { - return GaugeMetric.newInstance(val.getLast(), val.getMax(), val.getMin(), val.getSum(), val.getCount()); - } else { - return GaugeMetric.newInstance(val.getLast(), val.getMax(), val.getMin(), val.getSum(), val.getCount(), - Optional.of(buildPercentileList(val.getHistogram()))); - } - } - } - - private static List<Tuple2<String, Double>> buildPercentileList(DoubleHistogram histogram) { - List<Tuple2<String, Double>> prefixAndValues = new ArrayList<>(2); - prefixAndValues.add(new Tuple2<>("95", histogram.getValueAtPercentile(95.0d))); - prefixAndValues.add(new Tuple2<>("99", histogram.getValueAtPercentile(99.0d))); - return prefixAndValues; - } - - MetricSnapshot convert() { - for (Map.Entry<Identifier, UntypedMetric> entry : snapshot.entrySet()) { - Identifier ident = entry.getKey(); - getMap(ident.getLocation()).put(ident.getName(), convert(entry.getValue())); - } - Map<MetricDimensions, MetricSet> data = new HashMap<>(); - for (Map.Entry<Point, Map<String, MetricValue>> entry : perPointData.entrySet()) { - MetricDimensions key = convert(entry.getKey()); - MetricSet newval = new MetricSet(entry.getValue()); - MetricSet old = data.get(key); - if (old != null) { - // should not happen, this is bad - // TODO: consider merging the two MetricSet instances - log.warning("losing MetricSet when converting for: "+entry.getKey()); - } else { - data.put(key, newval); - } - } - return new MetricSnapshot(snapshot.getFromMillis(), - snapshot.getToMillis(), - TimeUnit.MILLISECONDS, - data); - } - - private Map<String, MetricValue> getMap(Point point) { - if (point == null) { - point = Point.emptyPoint(); - } - if (! perPointData.containsKey(point)) { - perPointData.put(point, new HashMap<>()); - } - return perPointData.get(point); - } - - void outputHistograms(PrintStream output) { - boolean gotHistogram = false; - for (Map.Entry<Identifier, UntypedMetric> entry : snapshot.entrySet()) { - if (entry.getValue().getHistogram() == null) { - continue; - } - gotHistogram = true; - DoubleHistogram histogram = entry.getValue().getHistogram(); - Identifier id = entry.getKey(); - String metricIdentifier = getIdentifierString(id); - output.println("# start of metric " + metricIdentifier); - histogram.outputPercentileDistribution(output, 4, 1.0d, true); - output.println("# end of metric " + metricIdentifier); - } - if (!gotHistogram) { - output.println("# No histograms currently available."); - } - } - - private String getIdentifierString(Identifier id) { - StringBuilder buffer = new StringBuilder(); - Point location = id.getLocation(); - buffer.append(id.getName()); - if (location != null) { - buffer.append(", dimensions: { "); - Iterator<String> dimensions = location.dimensions().iterator(); - Iterator<Value> values = location.location().iterator(); - boolean firstDimension = true; - while (dimensions.hasNext() && values.hasNext()) { - - if (firstDimension) { - firstDimension = false; - } else { - buffer.append(", "); - } - serializeSingleDimension(buffer, dimensions.next(), values.next()); - } - buffer.append(" }"); - } - return buffer.toString(); - - } - - private void serializeSingleDimension(StringBuilder buffer, final String dimensionName, Value dimensionValue) { - buffer.append('"'); - escape(dimensionName, buffer); - buffer.append("\": "); - switch (dimensionValue.getType()) { - case LONG: - buffer.append(Long.toString(dimensionValue.longValue())); - break; - case DOUBLE: - buffer.append(Double.toString(dimensionValue.doubleValue())); - break; - case STRING: - buffer.append('"'); - escape(dimensionValue.stringValue(), buffer); - buffer.append('"'); - break; - default: - buffer.append("\"Unknown type for this dimension, this is a bug.\""); - break; - } - } - - private void escape(final String in, final StringBuilder target) { - for (final char c : in.toCharArray()) { - switch (c) { - case ('"'): - target.append("\\\""); - break; - case ('\\'): - target.append("\\\\"); - break; - case ('\b'): - target.append("\\b"); - break; - case ('\f'): - target.append("\\f"); - break; - case ('\n'): - target.append("\\n"); - break; - case ('\r'): - target.append("\\r"); - break; - case ('\t'): - target.append("\\t"); - break; - default: - if (c < 32) { - target.append("\\u").append(fourDigitHexString(c)); - } else { - target.append(c); - } - break; - } - } - } - - private static char[] fourDigitHexString(final char c) { - final char[] hex = new char[4]; - int in = ((c) & 0xFFFF); - for (int i = 3; i >= 0; --i) { - hex[i] = DIGITS[in & 0xF]; - in >>>= 4; - } - return hex; - } -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/package-info.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/package-info.java deleted file mode 100644 index d191a5764c0..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/jdisc/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * JDisc metrics API for simple metrics implementation. - * - * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a> - */ -@ExportPackage -package com.yahoo.metrics.simple.jdisc; - -import com.yahoo.osgi.annotation.ExportPackage; diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/package-info.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/package-info.java deleted file mode 100644 index 9306c7c59db..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/package-info.java +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * A metrics API with declarable metric, and also an implementation of the - * JDisc Metrics API where the newest state is made continously available. - * - * <p> - * Users should have an instance of {@link com.yahoo.metrics.simple.MetricReceiver} - * injected in the constructor where needed, then declare metrics as instances - * of {@link com.yahoo.metrics.simple.Counter} and - * {@link com.yahoo.metrics.simple.Gauge} using - * {@link com.yahoo.metrics.simple.MetricReceiver#declareCounter(String)}, - * {@link com.yahoo.metrics.simple.MetricReceiver#declareCounter(String, Point)}, - * {@link com.yahoo.metrics.simple.MetricReceiver#declareGauge(String)}, - * {@link com.yahoo.metrics.simple.MetricReceiver#declareGauge(String, Point)}, or - * {@link com.yahoo.metrics.simple.MetricReceiver#declareGauge(String, java.util.Optional, MetricSettings)}. - * </p> - * - * <p> - * Clients input data through the API in {@link com.yahoo.metrics.simple.MetricReceiver}, - * while the internal work is done by {@link com.yahoo.metrics.simple.MetricAggregator}. - * Initialization is done top-down from {@link com.yahoo.metrics.simple.MetricManager}. - * The link between calls to MetricReceiver and MetricAggregator is the role of - * {@link com.yahoo.metrics.simple.MetricUpdater}. - * </p> - * - * @author Steinar Knutsen - */ -@PublicApi -@ExportPackage -package com.yahoo.metrics.simple; - -import com.yahoo.api.annotations.PublicApi; -import com.yahoo.osgi.annotation.ExportPackage; diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/runtime/MetricProperties.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/runtime/MetricProperties.java deleted file mode 100644 index 9c3ecec10fc..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/runtime/MetricProperties.java +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.metrics.simple.runtime; - -import java.nio.file.Path; -import java.nio.file.Paths; - -/** - * Constants used by Vespa to make the simple metrics implementation available - * to other components. - * - * @author Steinar Knutsen - */ -public final class MetricProperties { - - private MetricProperties() { - } - - public static final String BUNDLE_SYMBOLIC_NAME = "simplemetrics"; - -} diff --git a/simplemetrics/src/main/java/com/yahoo/metrics/simple/runtime/package-info.java b/simplemetrics/src/main/java/com/yahoo/metrics/simple/runtime/package-info.java deleted file mode 100644 index e7c7cd166eb..00000000000 --- a/simplemetrics/src/main/java/com/yahoo/metrics/simple/runtime/package-info.java +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * Settings and properties used for setting up the simple metrics library in a - * container. - * - * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a> - */ -@ExportPackage -package com.yahoo.metrics.simple.runtime; - -import com.yahoo.osgi.annotation.ExportPackage; - |