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

com.hotels.styx.api.metrics.codahale.SlidingWindowHistogramReservoir Maven / Gradle / Ivy

There is a newer version: 1.0.0.beta9
Show newest version
/*
  Copyright (C) 2013-2018 Expedia 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.hotels.styx.api.metrics.codahale;

import com.codahale.metrics.Reservoir;
import com.codahale.metrics.Snapshot;
import com.hotels.styx.api.Clock;
import com.hotels.styx.api.metrics.SlidingWindowHistogram;
import org.HdrHistogram.Histogram;
import org.HdrHistogram.HistogramIterationValue;

import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.hotels.styx.api.Clocks.systemClock;
import static java.lang.String.format;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * A {@link Reservoir} backed by a {@link SlidingWindowHistogram}.
 */
public class SlidingWindowHistogramReservoir implements Reservoir {
    private final SlidingWindowHistogram histogram;
    private final Clock clock;
    private volatile HistogramSnapshot snapshot;
    private boolean updated = true;
    private long snapshotCreationTime;

    public SlidingWindowHistogramReservoir() {
        this(new SlidingWindowHistogram.Builder()
                .numberOfIntervals(12)
                .intervalDuration(10, SECONDS)
                .autoResize(true)
                .build());
    }

    public SlidingWindowHistogramReservoir(SlidingWindowHistogram histogram) {
        this(histogram, systemClock());
    }

    public SlidingWindowHistogramReservoir(SlidingWindowHistogram histogram, Clock clock) {
        this.histogram = checkNotNull(histogram);
        this.clock = checkNotNull(clock);
        this.snapshotCreationTime = clock.tickMillis();
    }

    @Override
    public int size() {
        return getSnapshot().size();
    }

    @Override
    public synchronized void update(long value) {
        updated = true;
        histogram.recordValue(value);
    }

    @Override
    public synchronized Snapshot getSnapshot() {
        if (updated || snapshotExpired(clock.tickMillis())) {
            snapshot = new HistogramSnapshot(histogram);
            updated = false;
            snapshotCreationTime = clock.tickMillis();
        }
        return snapshot;
    }

    private boolean snapshotExpired(long currentTime) {
        return currentTime - snapshotCreationTime > histogram.windowSize() * histogram.timeIntervalMs();
    }

    static final class HistogramSnapshot extends Snapshot {
        private final Histogram histogram;

        HistogramSnapshot(SlidingWindowHistogram histogram) {
            this.histogram = histogram.copy();
        }

        @Override
        public double getValue(double quantile) {
            return histogram.getValueAtPercentile(quantile * 100.0);
        }

        @Override
        public long[] getValues() {
            long[] vals = new long[(int) histogram.getTotalCount()];
            int i = 0;
            for (HistogramIterationValue value : histogram.recordedValues()) {
                long val = value.getValueIteratedTo();
                for (int j = 0; j < value.getCountAddedInThisIterationStep(); j++) {
                    vals[i++] = val;
                }
            }
            if (i != vals.length) {
                throw new IllegalStateException(format("Total count was %d but iterating values produced is %d",
                        histogram.getTotalCount(), vals.length));
            }
            return vals;
        }

        @Override
        public int size() {
            return (int) histogram.getTotalCount();
        }

        @Override
        public long getMax() {
            return histogram.getMaxValue();
        }

        @Override
        public double getMean() {
            return histogram.getMean();
        }

        @Override
        public long getMin() {
            return histogram.getMinValue();
        }

        @Override
        public double getStdDev() {
            return histogram.getStdDeviation();
        }

        @Override
        public void dump(OutputStream output) {
            PrintWriter p = new PrintWriter(new OutputStreamWriter(output, UTF_8));
            for (HistogramIterationValue value : histogram.recordedValues()) {
                for (int j = 0; j < value.getCountAddedInThisIterationStep(); j++) {
                    p.printf("%d%n", value.getValueIteratedTo());
                }
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy