com.facebook.stats.mx.StatsUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.stats.mx.StatsUtil.java

Source

/*
 * Copyright (C) 2012 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.facebook.stats.mx;

import com.facebook.stats.EventCounterIf;
import com.facebook.stats.MultiWindowDistribution;
import com.facebook.stats.MultiWindowRate;
import com.facebook.stats.MultiWindowSpread;
import com.facebook.stats.QuantileDigest;
import com.facebook.stats.ReadableMultiWindowCounter;
import com.facebook.stats.ReadableMultiWindowGauge;
import com.facebook.stats.ReadableMultiWindowRate;
import com.google.common.collect.ImmutableList;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.ReadableDateTime;

import java.util.List;
import java.util.Map;

/**
 * Helper methods for converting stat objects into key/value pairs that conform to standing
 * naming conventions around <type>.<time_window>
 */
public class StatsUtil {
    /**
     * @deprecated replaced by addRateAndSumToCounters
     */
    @Deprecated
    public static void adddKeyToCounters(String baseKey, ReadableMultiWindowRate rate,
            Map<String, Long> counterMap) {
        addRateToCounters(baseKey, rate, counterMap);
        addSumToCounters(baseKey, rate, counterMap);
    }

    public static void addRateAndSumToCounters(String baseKey, ReadableMultiWindowRate rate,
            Map<String, Long> counterMap) {
        addRateToCounters(baseKey, rate, counterMap);
        addSumToCounters(baseKey, rate, counterMap);
    }

    public static void addRateToCounters(String baseKey, ReadableMultiWindowRate rate,
            Map<String, Long> counterMap) {
        counterMap.put(baseKey + ".rate", rate.getAllTimeRate());
        counterMap.put(baseKey + ".rate.3600", rate.getHourRate());
        counterMap.put(baseKey + ".rate.600", rate.getTenMinuteRate());
        counterMap.put(baseKey + ".rate.60", rate.getMinuteRate());
    }

    public static void addSumToCounters(String baseKey, ReadableMultiWindowRate rate,
            Map<String, Long> counterMap) {
        counterMap.put(baseKey + ".sum", rate.getAllTimeSum());
        counterMap.put(baseKey + ".sum.3600", rate.getHourSum());
        counterMap.put(baseKey + ".sum.600", rate.getTenMinuteSum());
        counterMap.put(baseKey + ".sum.60", rate.getMinuteSum());
    }

    public static void addGaugeAvgToCounters(String baseKey, ReadableMultiWindowGauge gauge,
            Map<String, Long> counterMap) {
        counterMap.put(baseKey + ".avg", gauge.getAllTimeAvg());
        counterMap.put(baseKey + ".avg.3600", gauge.getHourAvg());
        counterMap.put(baseKey + ".avg.600", gauge.getTenMinuteAvg());
        counterMap.put(baseKey + ".avg.60", gauge.getMinuteAvg());
    }

    public static void addGaugeSamplesToCounters(String baseKey, ReadableMultiWindowGauge gauge,
            Map<String, Long> counterMap) {
        counterMap.put(baseKey + ".samples", gauge.getAllTimeSamples());
        counterMap.put(baseKey + ".samples.3600", gauge.getHourSamples());
        counterMap.put(baseKey + ".samples.600", gauge.getTenMinuteSamples());
        counterMap.put(baseKey + ".samples.60", gauge.getMinuteSamples());
    }

    /**
     * internal helper method
     *
     * @param baseKey base baseKey name, adds standard time ranges ".60", ".3600", ...
     * @param counter the counter to add
     * @param counterMap map of counters
     */
    private static void addValueToCounters(String baseKey, ReadableMultiWindowCounter counter,
            Map<String, Long> counterMap) {
        counterMap.put(baseKey, counter.getAllTimeValue());
        counterMap.put(baseKey + ".3600", counter.getHourValue());
        counterMap.put(baseKey + ".600", counter.getTenMinuteValue());
        counterMap.put(baseKey + ".60", counter.getMinuteValue());
    }

    public static void addSpreadToCounters(String baseKey, MultiWindowSpread spread, Map<String, Long> counterMap) {
        addValueToCounters(baseKey + ".min", spread.getMin(), counterMap);
        addValueToCounters(baseKey + ".max", spread.getMax(), counterMap);
        addGaugeAvgToCounters(baseKey, spread.getGauge(), counterMap);
        addGaugeSamplesToCounters(baseKey, spread.getGauge(), counterMap);
    }

    public static void addQuantileToCounters(String baseKey, MultiWindowDistribution quantiles,
            Map<String, Long> counterMap) {
        addQuantilesToCounters(baseKey, ".60", counterMap, quantiles.getOneMinuteQuantiles());
        addQuantilesToCounters(baseKey, ".600", counterMap, quantiles.getTenMinuteQuantiles());
        addQuantilesToCounters(baseKey, ".3600", counterMap, quantiles.getOneHourQuantiles());
        addQuantilesToCounters(baseKey, "", counterMap, quantiles.getAllTimeQuantiles());
    }

    public static void addHistogramToExportedValues(String baseKey, MultiWindowDistribution quantiles,
            Map<String, String> values) {
        addHistogramToExportedValues(baseKey, ".60", values, quantiles.getOneMinute());
        addHistogramToExportedValues(baseKey, ".600", values, quantiles.getTenMinutes());
        addHistogramToExportedValues(baseKey, ".3600", values, quantiles.getOneHour());
        addHistogramToExportedValues(baseKey, "", values, quantiles.getAllTime());
    }

    private static void addHistogramToExportedValues(String baseKey, String windowKey, Map<String, String> values,
            QuantileDigest digest) {
        values.put(baseKey + ".hist" + windowKey, serializeHistogram(digest));
    }

    private static String serializeHistogram(QuantileDigest digest) {
        int buckets = 100;

        long min = digest.getMin();
        long max = digest.getMax();
        long bucketSize = (max - min + buckets) / buckets;

        ImmutableList.Builder<Long> boundaryBuilder = ImmutableList.builder();
        for (int i = 1; i < buckets + 1; ++i) {
            boundaryBuilder.add(min + bucketSize * i);
        }

        ImmutableList<Long> boundaries = boundaryBuilder.build();
        List<QuantileDigest.Bucket> counts = digest.getHistogram(boundaries);

        StringBuilder builder = new StringBuilder();

        // add bogus bucket (fb303 ui ignores the first one, for whatever reason)
        builder.append("-1:0:0,");

        for (int i = 0; i < boundaries.size(); ++i) {
            long lowBoundary = min;
            if (i > 0) {
                lowBoundary = boundaries.get(i - 1);
            }

            builder.append(lowBoundary).append(':').append(Math.round(counts.get(i).getCount())).append(':')
                    .append(Math.round(counts.get(i).getMean())).append(',');
        }

        // add a final bucket so that fb303 ui shows the max value
        builder.append(max);
        builder.append(":0:0");

        return builder.toString();
    }

    private static void addQuantilesToCounters(String baseKey, String windowKey, Map<String, Long> counters,
            Map<MultiWindowDistribution.Quantile, Long> oneMinuteQuantiles) {
        for (Map.Entry<MultiWindowDistribution.Quantile, Long> entry : oneMinuteQuantiles.entrySet()) {
            counters.put(baseKey + "." + entry.getKey().getKey() + windowKey, entry.getValue());
        }
    }

    public static void setAllTimeSum(MultiWindowRate rate, long value) {
        long old = rate.getAllTimeSum();
        if (old > value) {
            throw new IllegalArgumentException(
                    "MultiWindowRate counters can not decrement their allTimeSum (" + old + " > " + value + ")");
        }
        if (old == value) {
            return;
        }
        long delta = value - old;
        rate.add(delta);
    }

    public static Duration extentOf(EventCounterIf counter1, EventCounterIf counter2) {
        ReadableDateTime start = counter1.getStart();
        ReadableDateTime end = counter1.getEnd();

        if (counter2.getStart().isBefore(start)) {
            start = counter2.getStart();
        }

        if (counter2.getEnd().isAfter(end)) {
            end = counter2.getEnd();
        }

        return new Duration(start, end);
    }

    /**
     * helper method that will set the value of a counter
     */
    public static long setCounterValue(StatType statType, long value, Stats stats) {
        long oldValue = StatsUtil.setCounterValue(statType.getKey(), value, stats);

        return oldValue;
    }

    /**
     * helper method that will set the value of a counter
     */
    public static long setCounterValue(String key, long value, Stats stats) {
        long oldValue = stats.resetCounter(key);

        stats.incrementCounter(key, value);

        return oldValue;
    }
}