All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yahoo.metrics.simple.Bucket Maven / Gradle / Ivy

There is a newer version: 8.458.13
Show newest version
// Copyright Vespa.ai. 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 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> 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 malformedMetrics = LazySet.newHashSet();
        for (Map.Entry 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 getAllMetricNames() {
        Set names = new HashSet<>();
        for (Identifier id : values.keySet()) {
            names.add(id.getName());
        }
        return names;
    }

    public Collection> getValuesForMetric(String metricName) {
        List> singleMetric = new ArrayList<>();
        for (Map.Entry entry : values.entrySet()) {
            if (metricName.equals(entry.getKey().getName())) {
                singleMetric.add(locationValuePair(entry));
            }
        }
        return singleMetric;
    }

    public Map getMapForMetric(String metricName) {
        Map result = new HashMap<>();
        for (Map.Entry entry : values.entrySet()) {
            if (metricName.equals(entry.getKey().getName())) {
                result.put(entry.getKey().getLocation(), entry.getValue());
            }
        }
        return result;
    }

    public Map>> getValuesByMetricName() {
        Map>> result = new HashMap<>();
        for (Map.Entry entry : values.entrySet()) {
            List> 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 locationValuePair(Map.Entry entry) {
        return new SimpleImmutableEntry<>(entry.getKey().getLocation(), entry.getValue());
    }

    @Override
    public String toString() {
        return "Bucket [values=" + toString(values.entrySet(), 3) + "]";
    }

    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;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy