diff options
Diffstat (limited to 'metrics/src/main/java/com')
23 files changed, 0 insertions, 2861 deletions
diff --git a/metrics/src/main/java/com/yahoo/metrics/ConsumerSpec.java b/metrics/src/main/java/com/yahoo/metrics/ConsumerSpec.java deleted file mode 100644 index f97d8fd85ee..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/ConsumerSpec.java +++ /dev/null @@ -1,32 +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; - -import java.util.HashSet; -import java.util.Set; -import java.util.StringTokenizer; - -/** - * Spec saved from config. If metricSetChildren has content, metric pointed - * to is a metric set. - */ -class ConsumerSpec { - Set<String> includedMetrics = new HashSet<String>(); - - public boolean contains(Metric m) { - return includedMetrics.contains(m.getPath()); - } - - public void register(String path) { - StringTokenizer tokenizer = new StringTokenizer(path, "."); - - String total = ""; - - while (tokenizer.hasMoreTokens()) { - if (!total.isEmpty()) { - total += "."; - } - total += tokenizer.nextToken(); - includedMetrics.add(total); - } - } -} diff --git a/metrics/src/main/java/com/yahoo/metrics/CountMetric.java b/metrics/src/main/java/com/yahoo/metrics/CountMetric.java deleted file mode 100644 index 6d28a83aa0b..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/CountMetric.java +++ /dev/null @@ -1,222 +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; - -import com.yahoo.metrics.util.MetricValueSet; -import com.yahoo.metrics.util.ValueType; -import com.yahoo.metrics.util.HasCopy; -import com.yahoo.text.Utf8String; -import com.yahoo.text.XMLWriter; - -import java.util.Collection; -import java.util.Locale; -import java.util.logging.Logger; - -/** - * A metric that counts something. The value should always be positive. - */ -@SuppressWarnings("unchecked") -public class CountMetric extends Metric { - - public static final int LOG_IF_UNSET = 2; - - private static final Utf8String AVERAGE_CHANGE_PER_SECOND = new Utf8String("average_change_per_second"); - private static final Utf8String COUNT = new Utf8String("count"); - private static final Logger log = Logger.getLogger(CountMetric.class.getName()); - private final MetricValueSet<CountValue> values; - private int flags; - - public CountMetric(String name, String tags, String description, MetricSet owner) { - super(name, tags, description, owner); - values = new MetricValueSet<CountValue>(); - flags = LOG_IF_UNSET; - } - - public CountMetric(CountMetric other, CopyType copyType, MetricSet owner) { - super(other, owner); - values = new MetricValueSet<CountValue>(other.values, copyType == CopyType.CLONE ? other.values.size() : 1); - flags = other.flags; - } - - private CountValue getValues() { - return values.getValue(); - } - - public long getValue() { - CountValue val = getValues(); - return (val == null ? 0 : val.value); - } - - @SuppressWarnings("UnusedDeclaration") - public void logOnlyIfSet() { - flags &= LOG_IF_UNSET; - } - - public void set(long value) { - while (!values.setValue(new CountValue(value))) { - // try again - } - } - - public void inc() { - inc(1); - } - - public void dec() { - dec(1); - } - - public void inc(long i) { - boolean overflow; - CountValue val; - do { - val = getValues(); - if (val == null) { - val = new CountValue(0); - } - overflow = (val.value + i < val.value); - val.value += i; - } while (!values.setValue(val)); - - if (overflow) { - reset(); - log.fine("Overflow in metric " + getName() + ". Resetting it."); - } - } - - public void dec(long i) { - boolean underflow; - CountValue val; - do { - val = getValues(); - if (val == null) { - val = new CountValue(0); - } - underflow = (val.value - i > val.value); - val.value -= i; - } while (!values.setValue(val)); - - if (underflow) { - reset(); - log.fine("Underflow in metric " + getName() + ". Resetting it."); - } - } - - @Override - public void reset() { - values.reset(); - } - - @Override - public boolean logFromTotalMetrics() { - return true; - } - - @Override - public void logEvent(EventLogger logger, String fullName) { - CountValue val = getValues(); - - if ((flags & LOG_IF_UNSET) != 0 || val != null) { - logger.count(fullName, val == null ? 0 : val.value); - } - } - - @Override - public void printXml(XMLWriter writer, - int secondsPassed, - int verbosity) - { - CountValue valRef = getValues(); - if (valRef == null && verbosity < 2) { - return; - } - long val = valRef != null ? valRef.value : 0; - openXMLTag(writer, verbosity); - writer.attribute(COUNT, String.valueOf(val)); - - if (secondsPassed > 0) { - writer.attribute(AVERAGE_CHANGE_PER_SECOND, - String.format(Locale.US, "%.2f", (double)val / secondsPassed)); - } - - writer.closeTag(); - } - - // Only one metric in valuemetric, so return it on any id. - @Override - public long getLongValue(String id) { - CountValue val = getValues(); - return (val == null ? 0 : val.value); - } - - @Override - public double getDoubleValue(String id) { - CountValue val = getValues(); - return (val == null ? 0 : val.value); - } - - @Override - public boolean used() { - return getValues() != null; - } - - @Override - public void addToSnapshot(Metric m) { - CountValue val = getValues(); - if (val != null) { - ((CountMetric)m).inc(val.value); - } - } - - @Override - public void addToPart(Metric m) { - CountValue val = getValues(); - if (val != null) { - ((CountMetric)m).inc(val.value); - } - } - - @Override - public Metric clone(CopyType type, MetricSet owner, boolean includeUnused) { - return new CountMetric(this, type, owner); - } - - private static class CountValue implements ValueType, HasCopy<CountValue> { - - long value; - - private CountValue(long value) { - this.value = value; - } - - public CountValue clone() { - try { - return (CountValue)super.clone(); - } catch (CloneNotSupportedException e) { - return null; - } - } - - public void add(ValueType other) { - value += ((CountValue)other).value; - } - - public ValueType join(Collection<ValueType> sources, JoinBehavior joinBehavior) { - CountValue result = new CountValue(0); - for (ValueType t : sources) { - result.add(t); - } - if (joinBehavior == JoinBehavior.AVERAGE_ON_JOIN) { - result.value /= sources.size(); - } - return result; - } - - public String toString() { - return Long.toString(value); - } - - public CountValue copyObject() { - return new CountValue(value); - } - } -} diff --git a/metrics/src/main/java/com/yahoo/metrics/DoubleValue.java b/metrics/src/main/java/com/yahoo/metrics/DoubleValue.java deleted file mode 100644 index d102f5f7bd8..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/DoubleValue.java +++ /dev/null @@ -1,127 +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; - -import com.yahoo.metrics.util.ValueType; - -import java.util.Collection; -import java.util.Locale; - -public class DoubleValue implements ValueMetric.Value<Double> { - private int count; - private double min, max, last; - private double total; - - public DoubleValue() { - count = 0; - min = Double.POSITIVE_INFINITY; - max = Double.NEGATIVE_INFINITY; - last = 0; - total = 0; - } - - public String toString() { - return "(count " + count + ", min " + min + ", max " + max + ", last " + last + ", total " + total + ")"; - } - - public void add(Double v) { - count = count + 1; - total = total + v; - min = Math.min(min, v); - max = Math.max(max, v); - last = v; - } - - public void join(ValueMetric.Value<Double> v2, boolean createAverageOnJoin) { - //StringBuffer sb = new StringBuffer(); - //sb.append("Adding " + this + " to " + v2); - if (createAverageOnJoin) { - count += v2.getCount(); - total += v2.getTotal(); - last = v2.getLast(); - - } else { - double totalAverage = getAverage() + v2.getAverage(); - count += v2.getCount(); - total = totalAverage * count; - last += v2.getLast(); - } - min = Math.min(min, v2.getMin()); - max = Math.max(max, v2.getMax()); - //sb.append(" and got " + this); - //System.err.println(sb.toString()); - } - - public void add(ValueType other) { - DoubleValue dv = (DoubleValue) other; - count = count + dv.count; - total = total + dv.total; - min = Math.min(min, dv.min); - max = Math.max(max, dv.max); - last = dv.last; - } - - public ValueType join(Collection<ValueType> sources, JoinBehavior joinBehavior) { - DoubleValue result = new DoubleValue(); - for (ValueType t : sources) { - DoubleValue dv = (DoubleValue) t; - result.count = result.count + dv.count; - result.total = result.total + dv.total; - result.min = Math.min(result.min, dv.min); - result.max = Math.max(result.max, dv.max); - result.last += dv.last; - } - if (joinBehavior == JoinBehavior.AVERAGE_ON_JOIN) { - result.last /= sources.size(); - } else { - result.total *= sources.size(); - } - return result; - } - - public boolean overflow(ValueMetric.Value<Double> v2) { - if (count > (count + v2.getCount())) { - return true; - } - if (v2.getTotal() > 0 && getTotal() > getTotal() + v2.getTotal()) { - return true; - } - if (v2.getTotal() < 0 && getTotal() < getTotal() + v2.getTotal()) { - return true; - } - - return false; - } - - public int getCount() { return count; } - public Double getMin() { return (count > 0) ? min : 0; } - public Double getMax() { return (count > 0) ? max : 0; } - public Double getLast() { return last; } - public Double getTotal() { return total; } - - public Double getAverage() { - if (count == 0) { - return 0.0; - } - - return total / count; - } - - public String valueToString(Double val) { - if (val == Double.MIN_VALUE || val == Double.MAX_VALUE) { - return "0.00"; - } - - return String.format(Locale.US, "%.2f", val); - } - - public DoubleValue clone() { - try{ - return (DoubleValue) super.clone(); - } catch (CloneNotSupportedException e) { return null; } - } - - public ValueMetric.Value<Double> copyObject() { - return clone(); - } - -} diff --git a/metrics/src/main/java/com/yahoo/metrics/EventLogger.java b/metrics/src/main/java/com/yahoo/metrics/EventLogger.java deleted file mode 100644 index 3798b0e2e55..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/EventLogger.java +++ /dev/null @@ -1,7 +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; - -public interface EventLogger { - public void value(String name, double value); - public void count(String name, long value); -} diff --git a/metrics/src/main/java/com/yahoo/metrics/JoinBehavior.java b/metrics/src/main/java/com/yahoo/metrics/JoinBehavior.java deleted file mode 100644 index d995e116dd0..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/JoinBehavior.java +++ /dev/null @@ -1,11 +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; - -/** - * When joining multiple metrics as a result of dimension - * removal. Should the result be an average or a sum? As an example, - * a latency metric should likely be averaged, while a number of - * pending metric should likely be summed. This join behavior property - * lets the metric framework know how to remove dimensions. - **/ -public enum JoinBehavior { AVERAGE_ON_JOIN, SUM_ON_JOIN } diff --git a/metrics/src/main/java/com/yahoo/metrics/LongValue.java b/metrics/src/main/java/com/yahoo/metrics/LongValue.java deleted file mode 100644 index c18d2a5f25b..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/LongValue.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; - -import com.yahoo.metrics.util.ValueType; - -import java.util.Collection; - -/** - * @author thomasg - */ -public class LongValue - implements ValueMetric.Value<Long> -{ - private int count; - private long min, max, last; - private long total; - - public LongValue() { - count = 0; - min = Long.MAX_VALUE; - max = Long.MIN_VALUE; - last = 0; - total = 0; - } - - @Override - public void add(Long v) { - LongValue val = this; - val.count = count + 1; - val.total = total + v; - val.min = Math.min(min, v); - val.max = Math.max(max, v); - val.last = v; - } - - @Override - public void join(ValueMetric.Value<Long> v2, boolean createAverageOnJoin) { - LongValue value = this; - - if (createAverageOnJoin) { - value.count = count + v2.getCount(); - value.total = total + v2.getTotal(); - value.last = v2.getLast(); - } else { - double totalAverage = getAverage() + v2.getAverage(); - value.count = count + v2.getCount(); - value.total = (long) (totalAverage * value.count); // Total is "wrong" I guess. - value.last = last + v2.getLast(); - } - - value.min = Math.min(min, v2.getMin()); - value.max = Math.max(max, v2.getMax()); - } - - @Override - public void add(ValueType other) { - LongValue dv = (LongValue) other; - count = count + dv.count; - total = total + dv.total; - min = Math.min(min, dv.min); - max = Math.max(max, dv.max); - last = dv.last; - } - - @Override - public ValueType join(Collection<ValueType> sources, JoinBehavior joinBehavior) { - LongValue result = new LongValue(); - for (ValueType t : sources) { - LongValue dv = (LongValue) t; - result.count = result.count + dv.count; - result.total = result.total + dv.total; - result.min = Math.min(result.min, dv.min); - result.max = Math.max(result.max, dv.max); - result.last += dv.last; - } - if (joinBehavior == JoinBehavior.AVERAGE_ON_JOIN) { - result.last /= sources.size(); - } else { - result.total *= sources.size(); - } - return result; - } - - @Override - public boolean overflow(ValueMetric.Value<Long> v2) { - if (count > (count + v2.getCount())) { - return true; - } - if (v2.getTotal() > 0 && getTotal() > getTotal() + v2.getTotal()) { - return true; - } - if (v2.getTotal() < 0 && getTotal() < getTotal() + v2.getTotal()) { - return true; - } - - return false; - } - - @Override - public int getCount() { return count; } - - @Override - public Long getMin() { return (count > 0) ? min : 0; } - - @Override - public Long getMax() { return (count > 0) ? max : 0; } - - @Override - public Long getLast() { return last; } - - @Override - public Long getTotal() { return total; } - - @Override - public Double getAverage() { - if (count == 0) { - return 0.0; - } - return ((double) total) / count; - } - - @Override - public String valueToString(Long val) { - if (val == Long.MIN_VALUE || val == Long.MAX_VALUE) { - return valueToString((long)0); - } - - return val.toString(); - } - - @Override - public LongValue clone() { - try{ - return (LongValue) super.clone(); - } catch (CloneNotSupportedException e) { return null; } - } - - @Override - public ValueMetric.Value<Long> copyObject() { - return clone(); - } -} diff --git a/metrics/src/main/java/com/yahoo/metrics/Metric.java b/metrics/src/main/java/com/yahoo/metrics/Metric.java deleted file mode 100644 index ad7ffc971f6..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/Metric.java +++ /dev/null @@ -1,256 +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; - -import com.yahoo.text.XMLWriter; -import com.yahoo.text.Utf8String; - -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; - -public abstract class Metric { - - private String name; - private String tags; - private String description; - - public String getXMLTag() { - return getName(); - } - - public void setName(String name) { - this.name = name; - } - - public void setTags(String tags) { - this.tags = tags; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getTags() { - return tags; - } - - MetricSet owner; - - public Metric(String name, String tags, String description) { - this(name, tags, description, null); - } - - public Metric(String name, String tags, String description, MetricSet owner) { - this.name = name; - this.tags = tags; - this.description = description; - - if (owner != null) { - owner.registerMetric(this); - } - } - - public Metric(Metric other, MetricSet owner) { - this(other.name, other.tags, other.description, owner); - } - - public String getName() { return name; } - - public String getPath() { - if (owner == null || owner.owner == null) { - return getName(); - } - - return owner.getPath() + "." + getName(); - } - - public List<String> getPathVector() { - List<String> result = new ArrayList<>(); - result.add(getName()); - MetricSet owner = this.owner; - while (owner != null) { - result.add(0, owner.getName()); - owner = owner.owner; - } - return result; - } - - public String getDescription() { return description; } - - public String[] getTagVector() { - return getTags().split("[ \r\t\f]"); - } - - /** - * Returns true if the given tag exists in this metric's tag list. - * - * @return true if tag exists in tag list - */ - public boolean hasTag(String tag) { - for (String s : getTagVector()) { - if (s.equals(tag)) { - return true; - } - } - return false; - } - - public enum CopyType { CLONE, INACTIVE } - - /** - * The clone function will clone metrics to an identical subtree of - * metrics. Clone is primarily used for load metrics that wants to clone - * a template metric for each loadtype. But it should work generically. - * - * @param type If set to inactive, sum metrics will evaluate to primitives - * and metrics can save memory by knowing no updates are coming. - * @param includeUnused When creating snapshots we do not want to include - * unused metrics, but while generating sum metric sum in active - * metrics we want to. This has no affect if type is CLONE. - */ - public abstract Metric clone(CopyType type, MetricSet owner, boolean includeUnused); - - /** - * Utility function for assigning values from one metric of identical type - * to this metric. For simplicity sake it does a const cast and calls - * addToSnapshot, which should not alter source if reset is false. This can - * not be used to copy between active metrics and inactive copies. - * - * @return Returns itself. - */ - public Metric assignValues(Metric m) { - m.addToSnapshot(this); - // As this should only be called among active metrics, all metrics - // should exist and owner list should thus always end up empty. - return this; - } - - /** Reset all metric values. */ - public abstract void reset(); - - public boolean logFromTotalMetrics() { return false; } - - /** Implement to make metric able to log event. - * - * @param logger An event logger to use for logging. - * @param fullName The name to use for the event. - */ - public abstract void logEvent(EventLogger logger, String fullName); - - public static final Utf8String TAG_NAME = new Utf8String("name"); - public static final Utf8String TAG_TAGS = new Utf8String("tags"); - public static final Utf8String TAG_DESC = new Utf8String("description"); - - void openXMLTag(XMLWriter writer, int verbosity) { - String[] tags = getTagVector(); - - writer.openTag(getXMLTag()); - - if ( ! getXMLTag().equals(getName())) { - writer.attribute(TAG_NAME, getName()); - } - - if (verbosity >= 3 && tags.length > 0) { - String tagStr = ""; - for (String tag : tags) { - if (!tagStr.isEmpty()) { - tagStr = ","; - } - tagStr += tag; - } - - writer.attribute(TAG_TAGS, tagStr); - } - - if (verbosity >= 1 && !getDescription().isEmpty()) { - writer.attribute(TAG_DESC, getDescription()); - } - } - - /** - * The verbosity says how much to print. - * At verbosity level 0, only the most critical parts are printed. - * At verbosity level 1, descriptions are added. - * At verbosity level 2, metrics without data is added. - * At verbosity level 3, tags are included too. - */ - public abstract void printXml(XMLWriter writer, - int secondsPassed, - int verbosity); - - public String toXml(int secondsPassed, int verbosity) { - StringWriter writer = new StringWriter(); - printXml(new XMLWriter(writer), secondsPassed, verbosity); - return writer.toString(); - } - - /** - * Most metrics report numbers of some kind. To be able to report numbers - * without having code to handle each possible metric type, these functions - * exist to extract raw data to present easily. - * @param id The part of the metric to extract. For instance, an average - * metric have average, - */ - public abstract long getLongValue(String id); - public abstract double getDoubleValue(String id); - - /** - * When snapshotting we need to be able to join data from one set of metrics - * to another set of metrics taken at another time. MetricSet doesn't know - * the type of the metrics it contains, so we need a generic function for - * doing this. This function assumes metric given as input is of the exact - * same type as the one it is called on for simplicity. This is true when - * adding to snapshots as they have been created with clone and is thus - * always exactly equal. - * - * @param m Metric of exact same type as this one. (Will core if wrong) - */ - abstract void addToSnapshot(Metric m); - - /** - * For sum metrics to work with metric sets, metric sets need operator+=. - * To implement this, we need a function to join any metric type together. - * This is different from adding to snapshot. When adding to snapshots we - * join different time periods to the same metric, but when adding parts - * together we join different metrics for the same time. For instance, an - * average metric of queuesize, should just join new values to create new - * average when adding to snapshot, but when adding parts, the averages - * themselves should be added together. - * - * @param m Metric of exact same type as this one. (Will core if wrong) - */ - abstract void addToPart(Metric m); - - public boolean visit(MetricVisitor visitor, boolean tagAsAutoGenerated) { - return visitor.visitPrimitiveMetric(this, tagAsAutoGenerated); - } - - /** Set whether metrics have ever been set. */ - public abstract boolean used(); - - /** Returns true if this metric is registered in a metric set. */ - public boolean isRegistered() { return (owner != null); } - - /** - * If this metric is registered with an owner, remove itself from that owner. - */ - public void unregister() { - if (isRegistered()) { - getOwner().unregisterMetric(this); - } - } - - public MetricSet getOwner() { return owner; } - - public MetricSet getRoot() { - if (owner == null) { - if (this instanceof MetricSet) { - return (MetricSet)this; - } else { - return null; - } - } else { - return owner.getRoot(); - } - } -} diff --git a/metrics/src/main/java/com/yahoo/metrics/MetricManager.java b/metrics/src/main/java/com/yahoo/metrics/MetricManager.java deleted file mode 100644 index d22cf77c9c9..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/MetricManager.java +++ /dev/null @@ -1,704 +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; - -import com.yahoo.collections.Pair; -import com.yahoo.text.XMLWriter; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.logging.Logger; - -/** - * A metrics-enabled application should have a single MetricManager. You can register a number of MetricSets in the - * MetricManager. Each metric in the metrics sets can be used by zero or more consumers, configurable using - * readConfig(). - * - * The consumers get their data by calling the getMetrics() method, which gives them a snapshot of all the current - * metrics which are configured for the given name. - * - * Locking strategy: - * - * There are three locks in this class: - * - * Config lock: - This protects the class on config changes. It protects the _config and _consumerConfig members. - * - * Thread monitor (waiter): - This lock is kept by the worker thread while it is doing a work cycle, and it uses this - * monitor to sleep. It is used to make shutdown quick by interrupting thread, and to let functions called by clients be - * able to do a change while the worker thread is idle. - The log period is protected by the thread monitor. - The - * update hooks is protected by the thread monitor. - * - * Metric lock: - The metric log protects the active metric set when adding or removing metrics. Clients need to grab - * this lock before altering active metrics. The metric manager needs to grab this lock everytime it visits active - * metrics. - The metric log protects the snapshots. The snapshot writer is the metric worker thread and will grab the - * lock while editing them. Readers that aren't the worker thread itself must grab lock to be sure. - * - * If multiple locks is taken, the allowed locking order is: 1. Thread monitor. 2. Metric lock. 3. Config lock. - */ -public class MetricManager implements Runnable { - - private static final int STATE_CREATED = 0; - private static final int STATE_RUNNING = 1; - private static final int STATE_STOPPED = 2; - private static final Logger log = Logger.getLogger(MetricManager.class.getName()); - private final CountDownLatch termination = new CountDownLatch(1); - private final MetricSnapshot activeMetrics = new MetricSnapshot("Active metrics showing updates since " + - "last snapshot"); - private final Map<String, ConsumerSpec> consumerConfig = new HashMap<>(); - private final List<UpdateHook> periodicUpdateHooks = new ArrayList<>(); - private final List<UpdateHook> snapshotUpdateHooks = new ArrayList<>(); - private final Timer timer; - private Pair<Integer, Integer> logPeriod; - private List<MetricSnapshotSet> snapshots = new ArrayList<>(); - private MetricSnapshot totalMetrics = new MetricSnapshot("Empty metrics before init", 0, - activeMetrics.getMetrics(), false); - private int state = STATE_CREATED; - private int lastProcessedTime = 0; - private boolean forceEventLogging = false; - private boolean snapshotUnsetMetrics = false; // TODO: add to config - - public MetricManager() { - this(new Timer()); - } - - MetricManager(Timer timer) { - this.timer = timer; - initializeSnapshots(); - logPeriod = new Pair<>(snapshots.get(0).getPeriod(), 0); - } - - void initializeSnapshots() { - int currentTime = timer.secs(); - - List<Pair<Integer, String>> snapshotPeriods = new ArrayList<>(); - snapshotPeriods.add(new Pair<>(60 * 5, "5 minute")); - snapshotPeriods.add(new Pair<>(60 * 60, "1 hour")); - snapshotPeriods.add(new Pair<>(60 * 60 * 24, "1 day")); - snapshotPeriods.add(new Pair<>(60 * 60 * 24 * 7, "1 week")); - - int count = 1; - for (int i = 0; i < snapshotPeriods.size(); ++i) { - int nextCount = 1; - if (i + 1 < snapshotPeriods.size()) { - nextCount = snapshotPeriods.get(i + 1).getFirst() - / snapshotPeriods.get(i).getFirst(); - if (snapshotPeriods.get(i + 1).getFirst() % snapshotPeriods.get(i).getFirst() != 0) { - throw new IllegalStateException("Snapshot periods must be multiplum of each other"); - } - } - snapshots.add(new MetricSnapshotSet(snapshotPeriods.get(i).getSecond(), - snapshotPeriods.get(i).getFirst(), - count, - activeMetrics.getMetrics(), - snapshotUnsetMetrics)); - count = nextCount; - } - // Add all time snapshot. - totalMetrics = new MetricSnapshot("All time snapshot", - 0, activeMetrics.getMetrics(), - snapshotUnsetMetrics); - totalMetrics.reset(currentTime); - } - - public void stop() { - synchronized (this) { - int prevState = state; - state = STATE_STOPPED; - if (prevState == STATE_CREATED) { - return; - } - notifyAll(); - } - try { - termination.await(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - @SuppressWarnings("UnusedDeclaration") - void setSnapshotUnsetMetrics(boolean value) { - snapshotUnsetMetrics = value; - } - - /** - * Add a metric update hook. This will always be called prior to snapshotting and metric logging, to make the - * metrics the best as they can be at those occasions. - * - * @param hook The hook to add. - * @param period Period in seconds for how often callback should be called. The default value of 0, means only - * before snapshotting or logging, while another value will give callbacks each period seconds. - * Expensive metrics to calculate will typically only want to do it before snapshotting, while - * inexpensive metrics might want to log their value every 5 seconds or so. Any value of period >= the - * smallest snapshot time will behave identically as if period is set to 0. - */ - @SuppressWarnings("UnusedDeclaration") - public synchronized void addMetricUpdateHook(UpdateHook hook, int period) { - hook.period = period; - - // If we've already initialized manager, log period has been set. - // In this case. Call first time after period - hook.nextCall = (logPeriod.getSecond() == 0 ? 0 : timer.secs() + period); - if (period == 0) { - if (!snapshotUpdateHooks.contains(hook)) { - snapshotUpdateHooks.add(hook); - } - } else { - if (!periodicUpdateHooks.contains(hook)) { - periodicUpdateHooks.add(hook); - } - } - } - - @SuppressWarnings("UnusedDeclaration") - public synchronized void removeMetricUpdateHook(UpdateHook hook) { - if (hook.period == 0) { - snapshotUpdateHooks.remove(hook); - } else { - periodicUpdateHooks.remove(hook); - } - } - - /** - * Force a metric update for all update hooks. Useful if you want to ensure nice values before reporting something. - * This function can not be called from an update hook callback. - * - * @param includeSnapshotOnlyHooks True to also run snapshot hooks. - */ - @SuppressWarnings("UnusedDeclaration") - public synchronized void updateMetrics(boolean includeSnapshotOnlyHooks) { - log.fine("Giving " + periodicUpdateHooks.size() + " periodic update hooks."); - - updatePeriodicMetrics(0, true); - - if (includeSnapshotOnlyHooks) { - log.fine("Giving " + snapshotUpdateHooks.size() + " snapshot update hooks."); - updateSnapshotMetrics(); - } - } - - /** - * Force event logging to happen now. This function can not be called from an update hook callback. - */ - @SuppressWarnings("UnusedDeclaration") - public void forceEventLogging() { - log.fine("Forcing event logging to happen."); - // Ensure background thread is not in a current cycle during change. - - synchronized (this) { - forceEventLogging = true; - this.notifyAll(); - } - } - - /** - * Register a new metric to be included in the active metric set. You need to have grabbed the metric lock in order - * to do this. (You also need to grab that lock if you alter registration of already registered metric set.) This - * function can not be called from an update hook callback. - * - * @param m The metric to register. - */ - public void registerMetric(Metric m) { - activeMetrics.getMetrics().registerMetric(m); - } - - /** - * Unregister a metric from the active metric set. You need to have grabbed the metric lock in order to do this. - * (You also need to grab that lock if you alter registration of already registered metric set.) This function can - * not be called from an update hook callback. - * - * @param m The Metric to unregister. - */ - @SuppressWarnings("UnusedDeclaration") - public void unregisterMetric(Metric m) { - activeMetrics.getMetrics().unregisterMetric(m); - } - - /** - * Reset all metrics including all snapshots. This function can not be called from an update hook callback. - * - * @param currentTime The current time. - */ - public synchronized void reset(int currentTime) { - activeMetrics.reset(currentTime); - - for (MetricSnapshotSet m : snapshots) { - m.reset(currentTime); - } - totalMetrics.reset(currentTime); - } - - /** - * Read configuration. Before reading config, all metrics should be set up first. By doing this, the metrics manager - * can optimize reporting of consumers. readConfig() will start a config subscription. It should not be called - * multiple times. - */ -/* public synchronized void init(String configId, ThreadPool pool) { - log.fine("Initializing metric manager") - - LOG(debug, "Initializing metric manager."); - _configSubscription = Config::subscribe(configId, *this); - LOG(debug, "Starting worker thread, waiting for first " - "iteration to complete."); - Runnable::start(pool); - // Wait for first iteration to have completed, such that it is safe - // to access snapshots afterwards. - vespalib::MonitorGuard sync(_waiter); - while (_lastProcessedTime == 0) { - sync.wait(1); - } - LOG(debug, "Metric manager completed initialization."); -} - -*/ - - class ConsumerMetricVisitor extends MetricVisitor { - - ConsumerSpec metricsToMatch; - MetricVisitor clientVisitor; - - ConsumerMetricVisitor(ConsumerSpec spec, - MetricVisitor clientVisitor) - { - metricsToMatch = spec; - this.clientVisitor = clientVisitor; - log.fine("Consuming metrics: " + spec.includedMetrics); - } - - public boolean visitMetricSet(MetricSet metricSet, boolean autoGenerated) { - if (metricSet.getOwner() == null) { - return true; - } - - if (!metricsToMatch.contains(metricSet)) { - log.fine("Metric doesn't match " + metricSet.getPath()); - return false; - } - - return clientVisitor.visitMetricSet(metricSet, autoGenerated); - } - - public void doneVisitingMetricSet(MetricSet metricSet) { - if (metricSet.getOwner() != null) { - clientVisitor.doneVisitingMetricSet(metricSet); - } - } - - public boolean visitPrimitiveMetric(Metric metric, boolean autoGenerated) { - if (metricsToMatch.contains(metric)) { - return clientVisitor.visitPrimitiveMetric(metric, autoGenerated); - } else { - log.fine("Metric doesn't match " + metric.getPath()); - } - return true; - } - } - - public synchronized void visit(MetricSet metrics, MetricVisitor visitor, String consumer) { - if (consumer.isEmpty()) { - metrics.visit(visitor, false); - return; - } - - ConsumerSpec spec = getConsumerSpec(consumer); - - if (spec != null) { - ConsumerMetricVisitor consumerVis = new ConsumerMetricVisitor(spec, visitor); - metrics.visit(consumerVis, false); - } else { - log.warning("Requested metrics for non-defined consumer " + consumer); - } - } - - class XmlWriterMetricVisitor extends MetricVisitor { - - int period; - XMLWriter writer; - int verbosity; - - XmlWriterMetricVisitor(XMLWriter writer, int period, int verbosity) { - this.period = period; - this.verbosity = verbosity; - this.writer = writer; - } - - public boolean visitMetricSet(MetricSet set, boolean autoGenerated) { - if (set.used() || verbosity >= 2) { - set.openXMLTag(writer, verbosity); - return true; - } - return false; - } - - public void doneVisitingMetricSet(MetricSet set) { - writer.closeTag(); - } - - public boolean visitPrimitiveMetric(Metric metric, boolean autoGenerated) { - metric.printXml(writer, period, verbosity); - return true; - } - } - - void printXml(MetricSet set, XMLWriter writer, int period, String consumer, int verbosity) { - visit(set, new XmlWriterMetricVisitor(writer, period, verbosity), consumer); - } - - /** - * Synchronize over this while the returned object - * - * @return The MetricSnapshot of all active metrics. - */ - public MetricSnapshot getActiveMetrics() { - return activeMetrics; - } - - /** - * Synchronize over this while the returned object - * - * @return The MetricSnapshot for the total metric. - */ - public MetricSnapshot getTotalMetricSnapshot() { - return totalMetrics; - } - - public synchronized List<Integer> getSnapshotPeriods() { - List<Integer> retVal = new ArrayList<Integer>(); - - for (MetricSnapshotSet m : snapshots) { - retVal.add(m.getPeriod()); - } - return retVal; - } - - /** - * While accessing snapshots you should synchronize over this - * - * @param period The id of the snapshot period to access. - * @param getInProgressSet True to retrieve the snapshot currently being built. - * @return The appropriate MetricSnapshot. - */ - MetricSnapshot getMetricSnapshot(int period, boolean getInProgressSet) { - return getMetricSnapshotSet(period).getSnapshot(getInProgressSet); - } - - MetricSnapshot getMetricSnapshot(int period) { - return getMetricSnapshot(period, false); - } - - public MetricSnapshotSet getMetricSnapshotSet(int period) { - for (MetricSnapshotSet m : snapshots) { - if (m.getPeriod() == period) { - return m; - } - } - - throw new IllegalArgumentException("No snapshot for period of length " + period + " exists."); - } - - @SuppressWarnings("UnusedDeclaration") - public synchronized boolean hasTemporarySnapshot(int period) { - return getMetricSnapshotSet(period).hasTemporarySnapshot(); - } - - public synchronized void addMetricToConsumer(String consumerName, String metricPath) { - ConsumerSpec spec = getConsumerSpec(consumerName); - if (spec == null) { - spec = new ConsumerSpec(); - consumerConfig.put(consumerName, spec); - } - spec.register(metricPath); - } - - public synchronized ConsumerSpec getConsumerSpec(String consumer) { - return consumerConfig.get(consumer); - } - - /** - * If you join or remove metrics from the active metric sets, normally, snapshots will be recreated next snapshot - * period. However, if you want to see the effects of such changes in status pages ahead of that, you can call this - * function in order to check whether snapshots needs to be regenerated and regenerate them if needed. - */ - public synchronized void checkMetricsAltered() { - if (activeMetrics.getMetrics().isRegistrationAltered()) { - handleMetricsAltered(); - } - } - - /** - * Used by unit tests to verify that we have processed for a given time. - * - * @return Returns the timestamp of the previous tick. - */ - @SuppressWarnings("UnusedDeclaration") - public int getLastProcessedTime() { - return lastProcessedTime; - } - - class LogMetricVisitor extends MetricVisitor { - - boolean total; - EventLogger logger; - - LogMetricVisitor(boolean totalVals, EventLogger logger) { - total = totalVals; - this.logger = logger; - } - - public boolean visitPrimitiveMetric(Metric metric, boolean autoGenerated) { - if (metric.logFromTotalMetrics() == total) { - String logName = metric.getPath().replace('.', '_'); - metric.logEvent(logger, logName); - } - return true; - } - } - - public void logTotal(int currentTime, EventLogger logger) { - LogMetricVisitor totalVisitor = new LogMetricVisitor(true, logger); - LogMetricVisitor fiveMinVisitor = new LogMetricVisitor(false, logger); - - if (logPeriod.getSecond() <= currentTime) { - log.fine("Logging total metrics."); - visit(totalMetrics.getMetrics(), totalVisitor, "log"); - visit(snapshots.get(0).getSnapshot().getMetrics(), fiveMinVisitor, "log"); - if (logPeriod.getSecond() + logPeriod.getFirst() < currentTime) { - logPeriod = new Pair<Integer, Integer>(logPeriod.getFirst(), - snapshots.get(0).getFromTime() + logPeriod.getFirst()); - } else { - logPeriod = - new Pair<Integer, Integer>(logPeriod.getFirst(), logPeriod.getSecond() + logPeriod.getFirst()); - } - } - } - - public void logOutOfSequence(int currentTime, EventLogger logger) { - LogMetricVisitor totalVisitor = new LogMetricVisitor(true, logger); - LogMetricVisitor fiveMinVisitor = new LogMetricVisitor(false, logger); - - log.fine("Logging total metrics out of sequence."); - MetricSnapshot snapshot = new MetricSnapshot( - "Total out of sequence metrics from start until current time", - 0, - totalMetrics.getMetrics(), - snapshotUnsetMetrics); - - activeMetrics.addToSnapshot(snapshot, currentTime, false); - snapshot.setFromTime(totalMetrics.getFromTime()); - visit(snapshot.getMetrics(), totalVisitor, "log"); - visit(snapshot.getMetrics(), fiveMinVisitor, "log"); - } - - /** - * Runs one iteration of the thread activity. - * - * @param logger An event logger to use for any new events generated. - * @return The number of milliseconds to sleep until waking up again - */ - public synchronized int tick(EventLogger logger) { - int currentTime = timer.secs(); - - log.finest("Worker thread starting to process for time " + currentTime); - - boolean firstIteration = (logPeriod.getSecond() == 0); - // For a slow system to still be doing metrics tasks each n'th - // second, rather than each n'th + time to do something seconds, - // we constantly join next time to do something from the last timer. - // For that to work, we need to initialize timers on first iteration - // to set them to current time. - if (firstIteration) { - // Setting next log period to now, such that we log metrics - // straight away - logPeriod = new Pair<Integer, Integer>(logPeriod.getFirst(), currentTime); - for (MetricSnapshotSet m : snapshots) { - m.setFromTime(currentTime); - } - for (UpdateHook h : periodicUpdateHooks) { - h.nextCall = currentTime; - } - } - - // If metrics have changed since last time we did a snapshot, - // work that out before taking the snapshot, such that new - // metric can be included - checkMetricsAltered(); - - // Set next work time to the time we want to take next snapshot. - int nextWorkTime = snapshots.get(0).getPeriod() + snapshots.get(0).getFromTime(); - - int nextUpdateHookTime; - - if (nextWorkTime <= currentTime) { - log.fine("Time to do snapshot. Calling update hooks"); - nextUpdateHookTime = updatePeriodicMetrics(currentTime, true); - updateSnapshotMetrics(); - takeSnapshots(nextWorkTime); - } else if (forceEventLogging) { - log.fine("Out of sequence event logging. Calling update hooks"); - nextUpdateHookTime = updatePeriodicMetrics(currentTime, true); - updateSnapshotMetrics(); - } else { - // If not taking a new snapshot. Only give update hooks to - // periodic hooks wanting it. - nextUpdateHookTime = updatePeriodicMetrics(currentTime, false); - } - - // Log if it is time - if (logPeriod.getSecond() <= currentTime || forceEventLogging) { - logTotal(currentTime, logger); - } else { - logOutOfSequence(currentTime, logger); - } - - forceEventLogging = false; - lastProcessedTime = (nextWorkTime <= currentTime ? nextWorkTime : currentTime); - log.fine("Worker thread done with processing for time " + lastProcessedTime); - - int next = Math.min(logPeriod.getSecond(), snapshots.get(0).getPeriod() + snapshots.get(0).getFromTime()); - next = Math.min(next, nextUpdateHookTime); - if (currentTime < next) { - return (next - currentTime) * 1000; - } - - return 0; - } - - @Override - public synchronized void run() { - if (state != STATE_CREATED) { - throw new IllegalStateException(); - } - try { - for (state = STATE_RUNNING; state == STATE_RUNNING; ) { - int timeout = tick(new VespaLogEventLogger()); - if (timeout > 0) { - wait(timeout); - } - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } finally { - termination.countDown(); - } - } - - public synchronized void takeSnapshots(int timeToProcess) { - // If not time to do dump data from active snapshot yet, nothing to do - if (!snapshots.get(0).timeForAnotherSnapshot(timeToProcess)) { - return; - } - - log.fine("Updating " + snapshots.get(0).getName() + " snapshot from active metrics"); - // int fromTime = snapshots.get(0).getSnapshot().getToTime(); - MetricSnapshot firstTarget = (snapshots.get(0).getNextTarget()); - firstTarget.reset(timeToProcess); - activeMetrics.addToSnapshot(firstTarget, timeToProcess, false); - log.fine("Updating total metrics with five minute period of active metrics"); - activeMetrics.addToSnapshot(totalMetrics, timeToProcess, false); - activeMetrics.reset(timeToProcess); - - for (int i = 1; i < snapshots.size(); ++i) { - MetricSnapshotSet s = snapshots.get(i); - - log.fine("Adding data from last snapshot to building snapshot of " + - "next period snapshot " + s.getName()); - - MetricSnapshot target = s.getNextTarget(); - snapshots.get(i - 1).getSnapshot().addToSnapshot(target, timeToProcess, false); - target.setToTime(timeToProcess); - - if (!snapshots.get(i).haveCompletedNewPeriod(timeToProcess)) { - log.fine("Not time to roll snapshot " + s.getName() + " yet. " + - s.getBuilderCount() + " of " + s.getCount() + " snapshot " + - "taken at time" + (s.getBuilderCount() * s.getPeriod() + s.getFromTime()) + - ", and period of " + s.getPeriod() + " is not up " + - "yet as we're currently processing for time " + timeToProcess); - break; - } else { - log.fine("Rolled snapshot " + s.getName() + " at time " + timeToProcess); - } - } - } - - /** - * Utility function for updating periodic metrics. - * - * @param updateTime Update metrics timed to update at this time. - * @param outOfSchedule Force calls to all hooks. Don't screw up normal schedule though. If not time to update yet, - * update without adjusting schedule for next update. - * @return Time of next hook to be called in the future. - */ - int updatePeriodicMetrics(int updateTime, boolean outOfSchedule) { - int nextUpdateTime = Integer.MAX_VALUE; - for (UpdateHook h : periodicUpdateHooks) { - if (h.nextCall <= updateTime) { - h.updateMetrics(); - if (h.nextCall + h.period < updateTime) { - h.nextCall = updateTime + h.period; - } else { - h.nextCall += h.period; - } - } else if (outOfSchedule) { - h.updateMetrics(); - } - nextUpdateTime = Math.min(nextUpdateTime, h.nextCall); - } - return nextUpdateTime; - } - - void updateSnapshotMetrics() { - for (UpdateHook h : snapshotUpdateHooks) { - h.updateMetrics(); - } - } - - synchronized void handleMetricsAltered() { -/* if (consumerConfig.isEmpty()) { - log.fine("Setting up consumers for the first time."); - } else { - log.info("Metrics registration changes detected. Handling changes."); - } - - Map<String, ConsumerSpec> configMap = new HashMap<String, ConsumerSpec>(); - activeMetrics.getMetrics().clearRegistrationAltered(); - - - for (<config::MetricsmanagerConfig::Consumer>::const_iterator it - = _config.consumer.begin(); it != _config.consumer.end(); ++it) - { - ConsumerMetricBuilder consumerMetricBuilder(*it); - _activeMetrics.getMetrics().visit(consumerMetricBuilder); - configMap[it->name] = ConsumerSpec::SP( - new ConsumerSpec(consumerMetricBuilder._matchedMetrics)); - } - _consumerConfig.swap(configMap); - */ - log.fine("Recreating snapshots to include altered metrics"); - totalMetrics.recreateSnapshot(activeMetrics.getMetrics(), snapshotUnsetMetrics); - - for (MetricSnapshotSet set : snapshots) { - set.recreateSnapshot(activeMetrics.getMetrics(), snapshotUnsetMetrics); - } - } - - abstract class UpdateHook { - - String name; - int nextCall; - int period; - - public UpdateHook(String name) { - this.name = name; - nextCall = 0; - period = 0; - } - - public abstract void updateMetrics(); - - public String getName() { - return name; - } - } -} diff --git a/metrics/src/main/java/com/yahoo/metrics/MetricSet.java b/metrics/src/main/java/com/yahoo/metrics/MetricSet.java deleted file mode 100644 index 8f3039bff18..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/MetricSet.java +++ /dev/null @@ -1,244 +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; - -import com.yahoo.text.XMLWriter; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.logging.Logger; - -public abstract class MetricSet extends Metric { - - private static Logger log = Logger.getLogger(MetricSet.class.getName()); - - List<Metric> metricOrder = new ArrayList<>(); // Keep added order for reporting - boolean registrationAltered; // Set to true if metrics have been - // registered/unregistered since last time - // it was reset - - public MetricSet(String name, String tags, String description, MetricSet owner) { - super(name, tags, description, owner); - } - - public MetricSet(MetricSet other, CopyType copyType, MetricSet owner, boolean includeUnused) { - super(other, owner); - - for (Metric m : other.metricOrder) { - if (copyType != CopyType.INACTIVE || includeUnused || m.used()) { - m.clone(copyType, this, includeUnused); - } - } - } - - /** - * @return Returns true if registration has been altered since it was last - * cleared. Used by the metric manager to know when it needs to recalculate - * which consumers will see what. - */ - public boolean isRegistrationAltered() { return registrationAltered; } - - /** Clear all registration altered flags. */ - void clearRegistrationAltered() { - visit(new MetricVisitor() { - public boolean visitMetricSet(MetricSet set, boolean autoGenerated) { - if (autoGenerated) { - return false; - } - - set.registrationAltered = false; - return true; - } - }, false); - } - - public void registerMetric(Metric m) { - if (m.isRegistered()) { - throw new IllegalStateException("Metric " + m.getName() + - " is already registered in a metric set. Cannot register it twice."); - } - - if (getMetricInternal(m.getName()) != null) { - throw new IllegalStateException("A metric named " + m.getName() + " is already registered " - + "in metric set " + getPath()); - } - - metricOrder.add(m); - m.owner = this; - tagRegistrationAltered(); - } - - public void unregisterMetric(Metric m) { - // In case of abrubt shutdowns, don't die hard on attempts to unregister - // non-registered metrics. Just warn and ignore. - if (!metricOrder.remove(m)) { - log.warning("Attempt to unregister metric " + m.getName() + " in metric set " + getPath() + - ", where it wasn't registered to begin with."); - return; - } - - m.owner = null; - tagRegistrationAltered(); - - log.finest("Unregistered metric " + m.getName() + " from metric set " + getPath() + "."); - } - - @Override - public void reset() { - for (Metric m : metricOrder) { - m.reset(); - } - } - - @Override - public boolean visit(MetricVisitor visitor, boolean tagAsAutoGenerated) { - if (!visitor.visitMetricSet(this, tagAsAutoGenerated)) { - return true; - } - - for (Metric m : metricOrder) { - if (!m.visit(visitor, tagAsAutoGenerated)) { - break; - } - } - - visitor.doneVisitingMetricSet(this); - return true; - } - - @Override - public void logEvent(EventLogger logger, String fullName) { - throw new IllegalStateException("Can't log event from a MetricsSet: " + fullName); - } - - // These should never be called on metrics set. - @Override - public long getLongValue(String id) { - throw new IllegalStateException("Tried to get long from metricset"); - } - - @Override - public double getDoubleValue(String id) { - throw new IllegalStateException("Tried to get double from metricset"); - } - - public Metric getMetric(String name) { - int pos = name.indexOf('.'); - if (pos == -1) { - return getMetricInternal(name); - } else { - String child = name.substring(0, pos); - String rest = name.substring(pos + 1); - - Metric m = getMetricInternal(child); - if (m == null || !(m instanceof MetricSet)) { - return null; - } else { - return ((MetricSet)m).getMetric(rest); - } - } - } - - private Metric getMetricInternal(String name) { - for (Metric m : metricOrder) { - if (m.getName().equals(name)) { - return m; - } - } - return null; - } - - Map<String, Metric> createMetricMap() { - Map<String, Metric> map = new TreeMap<>(); - - for (Metric m : metricOrder) { - map.put(m.getName(), m); - } - - return map; - } - - @Override - public void addToSnapshot(Metric snapshotMetric) { - MetricSet o = (MetricSet)snapshotMetric; - - Map<String, Metric> map1 = createMetricMap(); - Set<String> seen = new HashSet<>(); - - // For all the metrics in the other's order, join ours to the snapshot. - for (Metric m : o.metricOrder) { - Metric myCopy = map1.get(m.getName()); - - if (myCopy != null) { - seen.add(m.getName()); - myCopy.addToSnapshot(m); - } - } - - // For all the remaining metrics, just join them to the other one. - for (Metric m : metricOrder) { - if (!seen.contains(m.getName())) { - m.clone(CopyType.INACTIVE, o, false); - } - } - } - - List<Metric> getRegisteredMetrics() - { return metricOrder; } - - @Override - public boolean used() { - for (Metric m : metricOrder) { - if (m.used()) { - return true; - } - } - - return false; - } - - @Override - public void addToPart(Metric partMetric) { - MetricSet o = (MetricSet)partMetric; - - Map<String, Metric> map2 = o.createMetricMap(); - - for (Metric m : metricOrder) { - Metric other = map2.get(m.getName()); - if (other != null) { - m.addToPart(other); - } else { - m.clone(CopyType.INACTIVE, o, false); - } - } - } - - private void tagRegistrationAltered() { - registrationAltered = true; - if (owner != null) { - owner.tagRegistrationAltered(); - } - } - - @Override - public void printXml(XMLWriter writer, - int secondsPassed, int verbosity) - { - if (!used() && verbosity < 3) { - return; - } - - openXMLTag(writer, verbosity); - - for (Metric m : metricOrder) { - m.printXml(writer, secondsPassed, verbosity); - } - - writer.closeTag(); - } - - -} diff --git a/metrics/src/main/java/com/yahoo/metrics/MetricSnapshot.java b/metrics/src/main/java/com/yahoo/metrics/MetricSnapshot.java deleted file mode 100644 index b64330ddbc7..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/MetricSnapshot.java +++ /dev/null @@ -1,119 +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; - -import com.yahoo.text.XMLWriter; -import com.yahoo.text.Utf8String; - -import java.io.StringWriter; - -public class MetricSnapshot -{ - String name; - int period; - int fromTime; - int toTime; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getPeriod() { - return period; - } - - public void setPeriod(int period) { - this.period = period; - } - - public int getFromTime() { - return fromTime; - } - - public void setFromTime(int fromTime) { - this.fromTime = fromTime; - } - - public int getToTime() { - return toTime; - } - - public void setToTime(int toTime) { - this.toTime = toTime; - } - - public MetricSet getMetrics() { - return snapshot; - } - - MetricSet snapshot; - - public MetricSnapshot(String name) { - this.name = name; - this.period = 0; - this.fromTime = 0; - this.toTime = 0; - snapshot = new SimpleMetricSet("metrics", "", ""); - } - - public MetricSnapshot(String name, - int period, - MetricSet source, - boolean copyUnset) { - this(name); - this.period = period; - snapshot = (MetricSet)source.clone(Metric.CopyType.INACTIVE, null, copyUnset); - } - - void reset(int currentTime) { - fromTime = currentTime; - toTime = 0; - snapshot.reset(); - } - - public void recreateSnapshot(MetricSet source, boolean copyUnset) { - MetricSet newSnapshot = (MetricSet)source.clone(Metric.CopyType.INACTIVE, null, copyUnset); - newSnapshot.reset(); - snapshot.addToSnapshot(newSnapshot); - snapshot = newSnapshot; - } - - public static final Utf8String TAG_NAME = new Utf8String("name"); - public static final Utf8String TAG_FROM = new Utf8String("from"); - public static final Utf8String TAG_TO = new Utf8String("to"); - public static final Utf8String TAG_PERIOD = new Utf8String("period"); - - public void printXml(MetricManager man, String consumer, int verbosity, XMLWriter writer) { - writer.openTag("snapshot"); - writer.attribute(TAG_NAME, name); - writer.attribute(TAG_FROM, fromTime); - writer.attribute(TAG_TO, toTime); - writer.attribute(TAG_PERIOD, period); - - for (Metric m : snapshot.getRegisteredMetrics()) { - if (m instanceof MetricSet) { - man.printXml((MetricSet)m, writer, toTime > fromTime ? (toTime - fromTime) : period, consumer, verbosity); - } - } - - writer.closeTag(); - } - - public String toXml(MetricManager man, String consumer, int verbosity) { - StringWriter str = new StringWriter(); - XMLWriter writer = new XMLWriter(str); - printXml(man, consumer, verbosity, writer); - return str.toString(); - } - - public void addToSnapshot(MetricSnapshot other, int currentTime, boolean reset) { - snapshot.addToSnapshot(other.getMetrics()); - if (reset) { - reset(currentTime); - } - other.toTime = currentTime; - } -} diff --git a/metrics/src/main/java/com/yahoo/metrics/MetricSnapshotSet.java b/metrics/src/main/java/com/yahoo/metrics/MetricSnapshotSet.java deleted file mode 100644 index 2cb07cf7dbe..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/MetricSnapshotSet.java +++ /dev/null @@ -1,116 +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; - -/** - * Represents two snapshots for the same time period. - */ -public class MetricSnapshotSet { - int count; // Number of times we need to join to building period - // before we have a full time window. - int builderCount; // Number of times we've currently added to the - // building instance. - MetricSnapshot current = null; // The last full period - MetricSnapshot building = null; // The building period - - MetricSnapshotSet(String name, int period, int count, MetricSet source, boolean snapshotUnsetMetrics) { - this.count = count; - this.builderCount = 0; - current = new MetricSnapshot(name, period, source, snapshotUnsetMetrics); - current.reset(0); - if (count != 1) { - building = new MetricSnapshot(name, period, source, snapshotUnsetMetrics); - building.reset(0); - } - } - - MetricSnapshot getNextTarget() { - if (count == 1) { - return current; - } else { - return building; - } - } - - public boolean haveCompletedNewPeriod(int newFromTime) { - if (count == 1) { - current.setToTime(newFromTime); - return true; - } - building.setToTime(newFromTime); - - // If not time to roll yet, just return - if (++builderCount < count) return false; - // Building buffer done. Use that as current and reset current. - MetricSnapshot tmp = current; - current = building; - building = tmp; - building.setFromTime(newFromTime); - building.setToTime(0); - builderCount = 0; - return true; - } - - public boolean timeForAnotherSnapshot(int currentTime) { - int lastTime = getFromTime() + builderCount * getPeriod(); - return currentTime >= lastTime + getPeriod(); - } - - public void reset(int currentTime) { - if (count != 1) building.reset(currentTime); - current.reset(currentTime); - builderCount = 0; - } - - public void recreateSnapshot(MetricSet metrics, boolean copyUnset) { - if (count != 1) building.recreateSnapshot(metrics, copyUnset); - current.recreateSnapshot(metrics, copyUnset); - } - - public void setFromTime(int fromTime) - { - if (count != 1) { - building.setFromTime(fromTime); - } else { - current.setFromTime(fromTime); - } - } - - public int getPeriod() { - return current.getPeriod(); - } - - public int getFromTime() { - return current.getFromTime(); - } - - public int getCount() { - return count; - } - - public MetricSnapshot getSnapshot() { - return getSnapshot(false); - } - - public MetricSnapshot getSnapshot(boolean getBuilding) { - if (getBuilding) { - if (count == 1) { - throw new IllegalStateException("No temporary snapshot for set " + current.name); - } - return building; - } - - return current; - } - - public boolean hasTemporarySnapshot() { - return count > 1; - } - - public String getName() { - return current.getName(); - } - - public int getBuilderCount() { - return builderCount; - } -} diff --git a/metrics/src/main/java/com/yahoo/metrics/MetricVisitor.java b/metrics/src/main/java/com/yahoo/metrics/MetricVisitor.java deleted file mode 100644 index c26d28caf83..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/MetricVisitor.java +++ /dev/null @@ -1,32 +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; - -public abstract class MetricVisitor { - /** - * Visit a metric set. - * - * @param autoGenerated True for metric sets that are generated on the - * fly such as in sum metrics. - * @return True if you want to visit the content of this metric set. - */ - public boolean visitMetricSet(MetricSet set, boolean autoGenerated) { - return true; - } - - /** - * Callback visitors can use if they need to know the tree traversal of - * metric sets. This function is not called if visitMetricSet returned - * false. - */ - public void doneVisitingMetricSet(MetricSet set) { - } - - /** - * Visit a primitive metric within an accepted metric set. - * - * @return True if you want to continue visiting, false to abort. - */ - public boolean visitPrimitiveMetric(Metric m, boolean autoGenerated) { - return true; - } -} diff --git a/metrics/src/main/java/com/yahoo/metrics/SimpleMetricSet.java b/metrics/src/main/java/com/yahoo/metrics/SimpleMetricSet.java deleted file mode 100644 index c6671cc07d9..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/SimpleMetricSet.java +++ /dev/null @@ -1,25 +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; - -/** - * A final metric set. - */ -public final class SimpleMetricSet extends MetricSet { - - public SimpleMetricSet(String name, String tags, String description) { - this(name, tags, description, null); - } - - public SimpleMetricSet(String name, String tags, String description, MetricSet owner) { - super(name, tags, description, owner); - } - - public SimpleMetricSet(SimpleMetricSet other, Metric.CopyType copyType, MetricSet owner, boolean includeUnused) { - super(other, copyType, owner, includeUnused); - } - - @Override - public Metric clone(Metric.CopyType type, MetricSet owner, boolean includeUnused) - { return new SimpleMetricSet(this, type, owner, includeUnused); } - -} diff --git a/metrics/src/main/java/com/yahoo/metrics/SumMetric.java b/metrics/src/main/java/com/yahoo/metrics/SumMetric.java deleted file mode 100644 index 3607ea7939b..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/SumMetric.java +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * @class metrics::CounterMetric - * @ingroup metrics - * - * @brief Counts a value that only moves upwards. - * - * NB! If you have a MetricSet subclass you want to create a sum for, use - * MetricSet itself as the template argument. Otherwise you'll need to override - * clone(...) in order to make it return the correct type for your - * implementation. - */ - -package com.yahoo.metrics; - -import com.yahoo.text.XMLWriter; - -import java.util.ArrayList; -import java.util.List; - -public class SumMetric extends Metric -{ - ArrayList<Metric> metricsToSum = new ArrayList<Metric>(); - - public SumMetric(String name, String tags, String description, MetricSet owner) { - super(name, tags, description, owner); - metricsToSum = new ArrayList<Metric>(); - } - - public SumMetric(SumMetric other, MetricSet owner) { - super(other, owner); - - - if (other.owner == null) { - throw new IllegalStateException( - "Cannot copy a sum metric not registered in a metric set, as " + - "we need to use parent to detect new metrics to point to."); - } - if (owner == null) { - throw new IllegalStateException( - "Cannot copy a sum metric directly. One needs to at least " + - "include metric set above it in order to include metrics " + - "summed."); - } - - metricsToSum.ensureCapacity(other.metricsToSum.size()); - List<String> parentPath = other.owner.getPathVector(); - - for (Metric metric : other.metricsToSum) { - List<String> addendPath = metric.getPathVector(); - MetricSet newAddendParent = owner; - - for (int i = parentPath.size(); i < addendPath.size() - 1; ++i) { - String path = addendPath.get(i); - Metric child = newAddendParent.getMetric(path); - if (child == null) { - throw new IllegalStateException( - "Metric " + path + " in metric set " - + newAddendParent.getPath() + " was expected to " + - "exist. This sounds like a bug."); - } - - newAddendParent = (MetricSet)child; - } - - String path = addendPath.get(addendPath.size() - 1); - Metric child = newAddendParent.getMetric(path); - if (child == null) { - throw new IllegalStateException( - "Metric " + path + " in metric set " - + newAddendParent.getPath() + " was expected to " + - "exist. This sounds like a bug."); - } - - metricsToSum.add(child); - } - } - - @Override - public boolean visit(MetricVisitor visitor, boolean tagAsAutoGenerated) { - if (metricsToSum.isEmpty()) return true; - - Metric sum = generateSum(); - - if (sum == null) { - return true; - } - - if (sum instanceof MetricSet) { - sum.visit(visitor, true); - return true; - } else { - return visitor.visitPrimitiveMetric(sum, true); - } - } - - @Override - public Metric clone(CopyType copyType, MetricSet owner, boolean includeUnused) { - if (copyType == CopyType.CLONE) { - return new SumMetric(this, owner); - } - - Metric sum = null; - for (Metric metric : metricsToSum) { - if (sum == null) { - sum = metric.clone(CopyType.INACTIVE, null, includeUnused); - sum.setName(getName()); - sum.setDescription(getDescription()); - sum.setTags(getTags()); - - if (owner != null) { - owner.registerMetric(sum); - } - } else { - metric.addToPart(sum); - } - } - - return sum; - } - - @Override - public void addToPart(Metric partMetric) { - Metric m = generateSum(); - if (m != null) { - m.addToPart(partMetric); - } - } - - @Override - public void addToSnapshot(Metric snapshotMetric) { - Metric m = generateSum(); - if (m != null) { - m.addToSnapshot(snapshotMetric); - } - } - - public void addMetricToSum(Metric metric) { - if (owner == null) { - throw new IllegalStateException( - "Sum metric needs to be registered in a parent metric set " + - "prior to adding metrics to sum."); - } - if (!metricsToSum.isEmpty() && !(metric.getClass().equals(metricsToSum.get(0).getClass()))) { - throw new IllegalStateException( - "All metrics in a metric set must be of the same type."); - } - - List<String> sumParentPath = owner.getPathVector(); - List<String> addedPath = metric.getPathVector(); - - boolean error = false; - if (addedPath.size() <= sumParentPath.size()) { - error = true; - } else for (int i=0; i<sumParentPath.size(); ++i) { - if (!sumParentPath.get(i).equals(addedPath.get(i))) { - error = true; - break; - } - } - if (error) { - throw new IllegalStateException( - "Metric added to sum is required to be a child of the sum's " + - "direct parent metric set. (Need not be a direct child) " + - "Metric set " + metric.getPath() + " is not a child of " + - owner.getPath()); - } - - ArrayList<Metric> metrics = new ArrayList<Metric>(metricsToSum.size() + 1); - for (int i = 0; i < metricsToSum.size(); ++i) { - metrics.add(metricsToSum.get(i)); - } - metrics.add(metric); - metricsToSum = metrics; - } - - public void removeMetricFromSum(Metric metric) { - metricsToSum.remove(metric); - } - - public Metric generateSum() { - Metric m = clone(CopyType.INACTIVE, null, true); - - if (m != null) { - m.owner = owner; - } - return m; - } - - @Override - public long getLongValue(String id) { - Metric s = generateSum(); - if (s == null) { - return 0; - } - return s.getLongValue(id); - } - - @Override - public double getDoubleValue(String id) { - Metric s = generateSum(); - if (s == null) { - return 0.0; - } - return generateSum().getDoubleValue(id); - } - - @Override - public void logEvent(EventLogger logger, String fullName) { - Metric s = generateSum(); - if (s != null) { - s.logEvent(logger, fullName); - } - } - - @Override - public void printXml(XMLWriter writer, int secondsPassed, int verbosity) { - Metric s = generateSum(); - if (s == null) { - openXMLTag(writer, verbosity); - writer.closeTag(); - return; - } - - generateSum().printXml(writer, secondsPassed, verbosity); - } - - @Override - public boolean used() { - for (Metric m : metricsToSum) { - if (m.used()) return true; - } - return false; - } - - @Override - public void reset() {} -} diff --git a/metrics/src/main/java/com/yahoo/metrics/Timer.java b/metrics/src/main/java/com/yahoo/metrics/Timer.java deleted file mode 100644 index 0e980b816b9..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/Timer.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. -package com.yahoo.metrics; - -/** -* @author thomasg -*/ -class Timer { - int secs() { return (int)(milliSecs() / 1000); } - long milliSecs() { return System.currentTimeMillis(); } -} diff --git a/metrics/src/main/java/com/yahoo/metrics/ValueMetric.java b/metrics/src/main/java/com/yahoo/metrics/ValueMetric.java deleted file mode 100644 index d0bc8f39140..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/ValueMetric.java +++ /dev/null @@ -1,265 +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; - -import com.yahoo.log.LogLevel; -import com.yahoo.metrics.util.HasCopy; -import com.yahoo.metrics.util.MetricValueKeeper; -import com.yahoo.metrics.util.SimpleMetricValueKeeper; -import com.yahoo.metrics.util.ThreadLocalDirectoryValueKeeper; -import com.yahoo.metrics.util.ValueType; -import com.yahoo.text.XMLWriter; -import com.yahoo.text.Utf8String; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.logging.Logger; - -/** - * A metric that represents the value of something. - */ -public class ValueMetric<N extends Number> - extends Metric -{ - private static Logger log = Logger.getLogger(ValueMetric.class.getName()); - private static AtomicBoolean hasWarnedOnNonFinite = new AtomicBoolean(false); - - public interface Value<N extends Number> extends ValueType, HasCopy<Value<N>> { - void add(N v); - void join(Value<N> v2, boolean createAverageOnJoin); - boolean overflow(Value<N> v2); - - int getCount(); - N getMin(); - N getMax(); - N getLast(); - N getTotal(); - Double getAverage(); - - String valueToString(N value); - } - - public boolean hasFlag(int flag) { return (flags & flag) != 0; } - public ValueMetric<N> setFlag(int flag) { flags |= flag; return this; } - - MetricValueKeeper<Value<N>> values; - int flags = 0; - - static int AVERAGE_METRIC = 1; - static int CREATE_AVERAGE_ON_JOIN = 2; - static int UNSET_ON_ZERO_VALUE = 4; - static int LOG_IF_UNSET = 8; - - boolean isAverageMetric() { return hasFlag(AVERAGE_METRIC); } - boolean doCreateAverageOnJoin() { return hasFlag(CREATE_AVERAGE_ON_JOIN); } - boolean isUnsetOnZeroValue() { return hasFlag(UNSET_ON_ZERO_VALUE); } - boolean doLogIfUnset() { return hasFlag(LOG_IF_UNSET); } - JoinBehavior getJoinBehavior() { - return hasFlag(CREATE_AVERAGE_ON_JOIN) ? JoinBehavior.AVERAGE_ON_JOIN - : JoinBehavior.SUM_ON_JOIN; - } - - public ValueMetric<N> averageMetric() { return setFlag(AVERAGE_METRIC); } - public ValueMetric<N> createAverageOnJoin() { return setFlag(CREATE_AVERAGE_ON_JOIN); } - public ValueMetric<N> unsetOnZeroValue() { return setFlag(UNSET_ON_ZERO_VALUE); } - public ValueMetric<N> logIfUnset() { return setFlag(LOG_IF_UNSET); } - - public ValueMetric(String name, String tags, String description, MetricSet owner) { - super(name, tags, description, owner); - //values = new MetricValueSet(); - values = new ThreadLocalDirectoryValueKeeper<>(); - } - - public ValueMetric(ValueMetric<N> other, CopyType copyType, MetricSet owner) { - super(other, owner); - if (copyType == CopyType.INACTIVE || other.values instanceof SimpleMetricValueKeeper) { - values = new SimpleMetricValueKeeper<>(); - values.set(other.values.get(getJoinBehavior())); - } else { - //values = new MetricValueSet((MetricValueSet) other.values, ((MetricValueSet) other.values).size()); - values = new ThreadLocalDirectoryValueKeeper<>(other.values); - } - this.flags = other.flags; - } - - private void logNonFiniteValueWarning() { - if (!hasWarnedOnNonFinite.getAndSet(true)) { - log.log(LogLevel.WARNING, - "Metric '" + getPath() + "' attempted updated with a value that is NaN or " + - "Infinity; update ignored! No further warnings will be printed for " + - "such updates on any metrics, but they can be observed with debug " + - "logging enabled on component " + log.getName()); - } else if (log.isLoggable(LogLevel.DEBUG)) { - log.log(LogLevel.DEBUG, - "Metric '" + getPath() + "' attempted updated with a value that is NaN or " + - "Infinity; update ignored!"); - } - } - - public void addValue(N v) { - if (v == null) throw new NullPointerException("Cannot have null value"); - if (v instanceof Long) { - LongValue lv = new LongValue(); - lv.add((Long) v); - values.add((Value<N>) lv); - } else { - Double d = (Double)v; - if (d.isNaN() || d.isInfinite()) { - logNonFiniteValueWarning(); - return; - } - DoubleValue dv = new DoubleValue(); - dv.add(d); - values.add((Value<N>) dv); - } - } - - private Value<N> getValues() { - return values.get(getJoinBehavior()); - } - - @Override - public void addToSnapshot(Metric snapshotMetric) { - Value<N> v = getValues(); - if (v != null) ((ValueMetric<N>)snapshotMetric).join(v, true); - } - - @Override - void addToPart(Metric m) { - Value<N> v = getValues(); - if (v != null) ((ValueMetric<N>) m).join(v, doCreateAverageOnJoin()); - } - - public void join(Value<N> v2, boolean createAverageOnJoin) { - Value<N> tmpVals = getValues(); - if (tmpVals == null) { - if (v2 instanceof LongValue) { - tmpVals = (Value<N>) new LongValue(); - } else { - tmpVals = (Value<N>) new DoubleValue(); - } - } - if (tmpVals.overflow(v2)) { - this.values.reset(); - log.fine("Metric " + getPath() + " overflowed, resetting it."); - return; - } - if (tmpVals.getCount() == 0) { - tmpVals = v2; - } else if (v2.getCount() == 0) { - // Do nothing - } else { - tmpVals.join(v2, createAverageOnJoin); - } - this.values.set(tmpVals); - } - - public static final Utf8String TAG_AVG = new Utf8String("average"); - public static final Utf8String TAG_LAST = new Utf8String("last"); - public static final Utf8String TAG_MIN = new Utf8String("min"); - public static final Utf8String TAG_MAX = new Utf8String("max"); - public static final Utf8String TAG_CNT = new Utf8String("count"); - public static final Utf8String TAG_TOT = new Utf8String("total"); - - @Override - public void printXml(XMLWriter writer, - int timePassed, - int verbosity) - { - Value<N> val = getValues(); - if (!inUse(val) && verbosity < 2) { - return; - } - if (val == null) val = (Value<N>) new LongValue(); - - openXMLTag(writer, verbosity); - writer.attribute(TAG_AVG, new DoubleValue().valueToString(val.getAverage())); - writer.attribute(TAG_LAST, val.valueToString(val.getLast())); - - if (val.getCount() > 0) { - writer.attribute(TAG_MIN, val.valueToString(val.getMin())); - writer.attribute(TAG_MAX, val.valueToString(val.getMax())); - } - writer.attribute(TAG_CNT, val.getCount()); - if (verbosity >= 2) { - writer.attribute(TAG_TOT, val.valueToString(val.getTotal())); - } - - writer.closeTag(); - } - - public Number getValue(String id) { - Value<N> val = getValues(); - if (val == null) return 0; - - if (id.equals("last") || (!isAverageMetric() && id.equals("value"))) { - return val.getLast(); - } else if (id.equals("average") || (isAverageMetric() && id.equals("value"))) { - return val.getAverage(); - } else if (id.equals("count")) { - return val.getCount(); - } else if (id.equals("total")) { - return val.getTotal(); - } else if (id.equals("min")) { - return val.getMin(); - } else if (id.equals("max")) { - return val.getMax(); - } else { - throw new IllegalArgumentException("No id " + id + " in value metric " + getName()); - } - } - - @Override - public long getLongValue(String id) { - return getValue(id).longValue(); - } - - @Override - public double getDoubleValue(String id) { - return getValue(id).doubleValue(); - } - - @Override - public ValueMetric<N> clone(CopyType type, MetricSet owner, boolean includeUnused) { - return new ValueMetric<>(this, type, owner); - } - - @Override - public void reset() { values.reset(); } - - @Override - public void logEvent(EventLogger logger, String fullName) { - Value<N> val = getValues(); - if (!doLogIfUnset() && !inUse(val)) { - return; - } - logger.value(fullName, val == null ? 0 - : isAverageMetric() ? val.getAverage() - : val.getLast().doubleValue()); - } - - public boolean inUse(Value<?> value) { - return (value != null - && (value.getTotal().longValue() != 0 - || (value.getCount() != 0 && !isUnsetOnZeroValue()))); - } - - @Override - public boolean used() { - return inUse(getValues()); - } - - @Override - public String toString() { - Value<N> tmpVals = getValues(); - if (tmpVals == null) { - tmpVals = (Value<N>) new LongValue(); - } - return ("count=\"" + tmpVals.getCount() + - "\" min=\"" + tmpVals.valueToString(tmpVals.getMin()) + - "\" max=\"" + tmpVals.valueToString(tmpVals.getMax()) + - "\" last=\""+ tmpVals.valueToString(tmpVals.getLast()) + - "\" total=\"" + tmpVals.valueToString(tmpVals.getTotal()) + - "\" average=\"" + new DoubleValue().valueToString(tmpVals.getAverage()) + - "\""); - } - -} diff --git a/metrics/src/main/java/com/yahoo/metrics/VespaLogEventLogger.java b/metrics/src/main/java/com/yahoo/metrics/VespaLogEventLogger.java deleted file mode 100644 index a2ee2133b13..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/VespaLogEventLogger.java +++ /dev/null @@ -1,17 +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; - -import com.yahoo.log.event.Event; - -/** - * @author thomasg - */ -public class VespaLogEventLogger implements EventLogger { - public void value(String name, double value) { - Event.value(name, value); - } - - public void count(String name, long value) { - Event.count(name, value); - } -} diff --git a/metrics/src/main/java/com/yahoo/metrics/util/HasCopy.java b/metrics/src/main/java/com/yahoo/metrics/util/HasCopy.java deleted file mode 100644 index c4b53b24adc..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/util/HasCopy.java +++ /dev/null @@ -1,7 +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.util; - -public interface HasCopy<T> { - public T copyObject(); -} - diff --git a/metrics/src/main/java/com/yahoo/metrics/util/MetricValueKeeper.java b/metrics/src/main/java/com/yahoo/metrics/util/MetricValueKeeper.java deleted file mode 100644 index c40b57c29fb..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/util/MetricValueKeeper.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.util; - -import com.yahoo.metrics.JoinBehavior; -import java.util.Collection; - -/** - * - */ -public interface MetricValueKeeper<Value> { - /** Add a value to a given value. Used when metrics are written to by metric writer. */ - public void add(Value v); - /** Set the value to exactly this, forgetting old value. This operation needs only be supported by value keepers used in inactive snapshots. */ - public void set(Value v); - /** Get the value of the metrics written. If multiple values exist, use given join behavior. */ - public Value get(JoinBehavior joinBehavior); - /** Reset the value of the metrics to zero. */ - public void reset(); - /** Return copy of current view */ - public Collection<Value> getDirectoryView(); -} diff --git a/metrics/src/main/java/com/yahoo/metrics/util/MetricValueSet.java b/metrics/src/main/java/com/yahoo/metrics/util/MetricValueSet.java deleted file mode 100644 index 0ba3138f3d7..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/util/MetricValueSet.java +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * \class MetricValueSet - * \ingroup metrics - * - * \brief Utility for doing lockless metric updates and reads. - * - * We don't want to use regular locking while updating metrics due to overhead. - * We use this class to make metric updates as safe as possible without - * requiring locks. - * - * It keeps the set of values a metric wants to set. Thus it is templated on - * the class keeping the values. All that is required of this class is that it - * has an empty constructor and a copy constructor. - * - * The locking works, by keeping a set of values, with an active pointer into - * the value vector. Assuming only one thread calls setValues(), it can update - * the active pointer safely. We assume updating the active pointer is a - * non-interruptable operations, such that other threads will see either the new - * or the old value correctly. This should be the case on our platforms. - * - * Due to the reset functionality, it is possible to miss out on a metrics - * added during the reset, but this is very unlikely. For that to happen, when - * someone sets the reset flag, the writer thread must be in setValues(), - * having already passed the check for the reset flag, but not finished setting - * the values yet. - */ - -package com.yahoo.metrics.util; - -import java.util.Collection; -import com.yahoo.metrics.JoinBehavior; - -public class MetricValueSet<Value extends HasCopy<Value> & ValueType> - implements MetricValueKeeper<Value> -{ - private final ValueType[] values; - - private void setIndexedValue(int idx, Value v) { - values[idx] = v; - } - - @SuppressWarnings("unchecked") - private Value getIndexedValue(int idx) { - return (Value) values[idx]; - } - - - private volatile int activeValueIndex; - private volatile boolean reset = false; - - public MetricValueSet() { - values = new ValueType[3]; - activeValueIndex = 0; - } - - public MetricValueSet(MetricValueSet<Value> other, int copyCount) { - values = new ValueType[copyCount]; - activeValueIndex = 0; - setValue(other.getValue()); - } - - /** Get the current values. */ - public Value getValue() { - if (reset) return null; - Value v = getIndexedValue(activeValueIndex); - return (v == null ? null : v.copyObject()); - } - - /** - * Get the current values from the metric. This function should not be - * called in parallel. Only call it from a single thread or use external - * locking. If it returns false, it means the metric have just been reset. - * In which case, redo getValues(), apply the update again, and call - * setValues() again. - */ - public boolean setValue(Value value) { - int nextIndex = (activeValueIndex + 1) % values.length; - if (reset) { - reset = false; - setIndexedValue(nextIndex, null); - activeValueIndex = nextIndex; - return false; - } else { - setIndexedValue(nextIndex, value); - activeValueIndex = nextIndex; - return true; - } - } - - /** - * Retrieve and reset in a single operation, to minimize chance of - * alteration in the process. - */ - public Value getValuesAndReset() { - Value result = getValue(); - reset = true; - return result; - } - - public String toString() { - String retVal = "MetricValueSet(reset=" + reset - + ", active " + activeValueIndex + "["; - for (ValueType n : values) retVal += n + ","; - retVal += "])"; - return retVal; - } - - public int size() { return values.length; } - - public void add(Value v) { - while (true) { - Value current = getValue(); - if (current != null) { - current.add(v); - if (setValue(current)) { - return; - } - } else { - if (setValue(v)) { - return; - } - } - } - } - - public void set(Value v) { - setValue(v); - } - - public Value get(JoinBehavior joinBehavior) { - return getValue(); - } - - public void reset() { reset = true; } - - public Collection<Value> getDirectoryView() { - return null; - } - -} diff --git a/metrics/src/main/java/com/yahoo/metrics/util/SimpleMetricValueKeeper.java b/metrics/src/main/java/com/yahoo/metrics/util/SimpleMetricValueKeeper.java deleted file mode 100644 index bf5b18f782e..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/util/SimpleMetricValueKeeper.java +++ /dev/null @@ -1,38 +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.util; - -import java.util.Collection; -import com.yahoo.metrics.JoinBehavior; - -/** - * Simple implementation of the metric value keeper for use with snapshots. Only keeps - * one instance of data, does not need to worry about threads, and should have a small - * memory footprint. - */ -public class SimpleMetricValueKeeper<Value> implements MetricValueKeeper<Value> { - private Value value; - - public SimpleMetricValueKeeper() { - } - - public void add(Value v) { - throw new UnsupportedOperationException("Not supported. This value keeper is not intended to be used for live metrics."); - } - - public void set(Value v) { - this.value = v; - } - - public Value get(JoinBehavior joinBehavior) { - return value; - } - - public void reset() { - value = null; - } - - public Collection<Value> getDirectoryView() { - return null; - } - -} diff --git a/metrics/src/main/java/com/yahoo/metrics/util/ThreadLocalDirectoryValueKeeper.java b/metrics/src/main/java/com/yahoo/metrics/util/ThreadLocalDirectoryValueKeeper.java deleted file mode 100644 index a6ef28eac0f..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/util/ThreadLocalDirectoryValueKeeper.java +++ /dev/null @@ -1,76 +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.util; - -import com.yahoo.concurrent.ThreadLocalDirectory; -import com.yahoo.metrics.DoubleValue; -import com.yahoo.metrics.LongValue; -import com.yahoo.metrics.JoinBehavior; - -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -/** - * Value keeper class using ThreadLocalDirectory to maintain thread safety from multiple threads writing. - */ -public class ThreadLocalDirectoryValueKeeper<Value extends ValueType & HasCopy<Value>> - implements MetricValueKeeper<Value>, ThreadLocalDirectory.ObservableUpdater<Value, Value> -{ - private final ThreadLocalDirectory<Value, Value> directory = new ThreadLocalDirectory<Value, Value>(this); - private List<Value> initialValues = null; - - public ThreadLocalDirectoryValueKeeper() { - } - - public ThreadLocalDirectoryValueKeeper(MetricValueKeeper<Value> other) { - initialValues = new LinkedList<Value>(); - for (Value v : other.getDirectoryView()) initialValues.add(v.copyObject()); - } - - public Value createGenerationInstance(Value value) { - return null; - } - - public Value update(Value current, Value newValue) { - if (current == null) { - if (newValue instanceof DoubleValue) { - current = (Value) new DoubleValue(); - } else { - current = (Value) new LongValue(); - } - } - current.add(newValue); - return current; - } - - public Value copy(Value value) { - return value.copyObject(); - } - - public void add(Value v) { - directory.update(v, directory.getLocalInstance()); - } - - public void set(Value v) { - throw new UnsupportedOperationException("This value keeper is only intended to use with active metrics. Set operation not supported."); - } - - public Value get(JoinBehavior joinBehavior) { - List<Value> values = directory.view(); - if (initialValues != null) values.addAll(initialValues); - if (values.isEmpty()) { - return null; - } - return (Value) values.get(0).join(Collections.<ValueType>unmodifiableList(values), joinBehavior); - } - - public void reset() { - directory.fetch(); - initialValues = null; - } - - public Collection<Value> getDirectoryView() { - return directory.view(); - } -} diff --git a/metrics/src/main/java/com/yahoo/metrics/util/ValueType.java b/metrics/src/main/java/com/yahoo/metrics/util/ValueType.java deleted file mode 100644 index e9c8e27b613..00000000000 --- a/metrics/src/main/java/com/yahoo/metrics/util/ValueType.java +++ /dev/null @@ -1,11 +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.util; - -import com.yahoo.metrics.JoinBehavior; - -import java.util.Collection; - -public interface ValueType extends Cloneable { - public void add(ValueType other); - public ValueType join(Collection<ValueType> sources, JoinBehavior joinBehavior); -} |